diff --git a/.htaccess b/.htaccess new file mode 100644 index 000000000..80d7e878f --- /dev/null +++ b/.htaccess @@ -0,0 +1,23 @@ +RewriteEngine On +RewriteRule ^favicon.ico$ styles/bootstrap/favicon.ico [L] + +# Store the current location in an environment variable CWD to use +# mod_rewrite in .htaccess files without knowing the RewriteBase +RewriteCond $0#%{REQUEST_URI} ([^#]*)#(.*)\1$ +RewriteRule ^.*$ - [E=CWD:%2] + +# Anything below the following dirs will never be rewritten +RewriteRule "^pdfviewer/.*$" "-" [L] +RewriteRule "^views/bootstrap/images.*$" "-" [L] +RewriteRule "^out/images.*$" "-" [L] +RewriteRule "^styles/.*$" "-" [L] + +# Accessing a file in an extension is always possible +# Added for old extensions which do not use routes +RewriteCond %{REQUEST_FILENAME} -f +RewriteRule "^ext/.*$" "-" [L] + +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteCond %{REQUEST_FILENAME} !-l +RewriteRule ^.*$ %{ENV:CWD}index.php [QSA,L] diff --git a/CHANGELOG b/CHANGELOG index 95c681865..974e3099f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,40 @@ +-------------------------------------------------------------------------------- + Changes in version 5.1.10 +-------------------------------------------------------------------------------- +- add new hook on ViewDetails page +- running Controller::factory() will include class file only once +- use only Packagist for external dependencies +- set configured command timeout when creating pdf preview +- show numbers of reviews in main menu again +- do not send multiple emails after triggering a workflow transition, if a user + is involved in more than one of the following transitions +- fix javascript errors in out/out.TriggerWorkflow.php +- minor corrections in worklflow manager +- fix lots of javascript errors when removing, rewinding a workflow and + running, returning from a subworkflow +- show splash messages after triggering a workflow transition +- reindex document version also if time of last indexing is equal to creation + time of document version +- allow mimetypes (not just file extensions) in config variable viewOnlineFileTypes +- added Slim-Framework for a simple router +- move most of the login code into a controller, added more hooks in login process +- failed login is reported in log file +- update of cytoscape library, fix output of workflow on TriggerWorkflowGraph +- call hook preIndexDocument and postAddDocument even if the hook addDocument + was implemented by a user extension +- call hook preIndexDocument and postUpdateDocument even if the hook updateDocument + was implemented by a user extension +- call hook postEditFolder even if the hook editFolder was implemented by a + user extension +- whether the apache module xsendfile is used, can be configured +- add hooks for filtering tasks shown in the menu bar +- allow to set more parameters when upload a document or creating a new folder + via restapi +- add an input field on the substitute user and extension list page for filtering + table rows by string +- do not list users/groups in select menu on DocumentAccess page which already + has an access right + -------------------------------------------------------------------------------- Changes in version 5.1.9 -------------------------------------------------------------------------------- diff --git a/Makefile b/Makefile index 5e89f1b9f..3d8dc4be3 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -VERSION=5.1.9 -SRC=CHANGELOG inc conf utils index.php languages views op out controllers doc styles TODO LICENSE webdav install restapi pdfviewer +VERSION=$(shell php -r 'include("inc/inc.Version.php"); $$v=new SeedDMS_Version(); echo $$v->version();') +SRC=CHANGELOG inc conf utils index.php .htaccess languages views op out controllers doc styles TODO LICENSE webdav install restapi pdfviewer # webapp NODISTFILES=utils/importmail.php utils/seedddms-importmail utils/remote-email-upload utils/remote-upload utils/da-bv-reminder.php utils/seeddms-da-bv-reminder .svn .gitignore styles/blue styles/hc styles/clean views/blue views/hc views/clean views/pca diff --git a/SeedDMS_Core/Core/inc.ClassDMS.php b/SeedDMS_Core/Core/inc.ClassDMS.php index cd25d5d4f..d42bfe9b6 100644 --- a/SeedDMS_Core/Core/inc.ClassDMS.php +++ b/SeedDMS_Core/Core/inc.ClassDMS.php @@ -376,7 +376,7 @@ class SeedDMS_Core_DMS { $this->callbacks = array(); $this->version = '@package_version@'; if($this->version[0] == '@') - $this->version = '5.1.9'; + $this->version = '5.1.10'; } /* }}} */ /** diff --git a/SeedDMS_Core/Core/inc.ClassDocument.php b/SeedDMS_Core/Core/inc.ClassDocument.php index 6d7560052..6680f6d9d 100644 --- a/SeedDMS_Core/Core/inc.ClassDocument.php +++ b/SeedDMS_Core/Core/inc.ClassDocument.php @@ -3961,7 +3961,7 @@ class SeedDMS_Core_DocumentContent extends SeedDMS_Core_Object { /* {{{ */ if (!$this->_workflowState) { $queryStr= - "SELECT b.* FROM `tblWorkflowDocumentContent` a LEFT JOIN `tblWorkflowStates` b ON a.`state` = b.id WHERE `workflow`=". intval($this->_workflow->getID()) + "SELECT b.* FROM `tblWorkflowDocumentContent` a LEFT JOIN `tblWorkflowStates` b ON a.`state` = b.`id` WHERE `workflow`=". intval($this->_workflow->getID()) ." AND a.`version`='".$this->_version ."' AND a.`document` = '". $this->_document->getID() ."' "; $recs = $db->getResultArray($queryStr); @@ -4016,7 +4016,7 @@ class SeedDMS_Core_DocumentContent extends SeedDMS_Core_Object { /* {{{ */ if (!isset($this->_workflow)) { $queryStr= - "SELECT b.* FROM `tblWorkflowDocumentContent` a LEFT JOIN `tblWorkflows` b ON a.`workflow` = b.id WHERE a.`version`='".$this->_version + "SELECT b.* FROM `tblWorkflowDocumentContent` a LEFT JOIN `tblWorkflows` b ON a.`workflow` = b.`id` WHERE a.`version`='".$this->_version ."' AND a.`document` = '". $this->_document->getID() ."' " ." ORDER BY `date` DESC LIMIT 1"; $recs = $db->getResultArray($queryStr); @@ -4641,10 +4641,11 @@ class SeedDMS_Core_DocumentContent extends SeedDMS_Core_Object { /* {{{ */ if (!$this->_workflowState) $this->getWorkflowState(); $workflowstate = $this->_workflowState; - $transitions = $this->_workflow->getNextTransitions($workflowstate); - foreach($transitions as $transition) { - if($this->triggerWorkflowTransitionIsAllowed($user, $transition)) { - $needwkflaction = true; + if($transitions = $this->_workflow->getNextTransitions($workflowstate)) { + foreach($transitions as $transition) { + if($this->triggerWorkflowTransitionIsAllowed($user, $transition)) { + $needwkflaction = true; + } } } } diff --git a/SeedDMS_Core/Core/inc.DBAccessPDO.php b/SeedDMS_Core/Core/inc.DBAccessPDO.php index ce1efd7bc..710a578fc 100644 --- a/SeedDMS_Core/Core/inc.DBAccessPDO.php +++ b/SeedDMS_Core/Core/inc.DBAccessPDO.php @@ -222,12 +222,21 @@ class SeedDMS_Core_DatabaseAccess { * Destructor of SeedDMS_Core_DatabaseAccess */ function __destruct() { /* {{{ */ - if($this->_logfp) { + if($this->_logfile && $this->_logfp) { fwrite($this->_logfp, microtime()." END --------------------------------------------\n"); fclose($this->_logfp); } } /* }}} */ + /** + * Set the file pointer to a log file + * + * Once it is set, all queries will be logged into this file + */ + function setLogFp($fp) { /* {{{ */ + $this->_logfp = $fp; + } /* }}} */ + /** * Connect to database * diff --git a/SeedDMS_Core/package.xml b/SeedDMS_Core/package.xml index cbbeed696..50aa5d16b 100644 --- a/SeedDMS_Core/package.xml +++ b/SeedDMS_Core/package.xml @@ -12,11 +12,11 @@ uwe@steinmann.cx yes - 2018-11-13 + 2018-11-23 - 5.1.9 - 5.1.9 + 5.1.10 + 5.1.10 stable @@ -24,10 +24,8 @@ GPL License -context can be passed to getAccessMode() -call hook in SeedDMS_Core_Folder::getAccessMode() -new optional parameter $listguest for SeedDMS_Core_Document::getReadAccessList() -remove deprecated methods SeedDMS_Core_Document::convert(), SeedDMS_Core_Document::wasConverted(), SeedDMS_Core_Document::viewOnline(), SeedDMS_Core_Document::getUrl() +fix php warning if workflow state doesn' have next transition +add method SeedDMS_Core_DatabaseAccess::setLogFp() @@ -1618,5 +1616,24 @@ SeedDMS_Core_Document::getNotifyList() has new parameter to include disabled use fix possible sql injection in SeedDMS_Core_User + + 2018-11-13 + + + 5.1.9 + 5.1.9 + + + stable + stable + + GPL License + +context can be passed to getAccessMode() +call hook in SeedDMS_Core_Folder::getAccessMode() +new optional parameter $listguest for SeedDMS_Core_Document::getReadAccessList() +remove deprecated methods SeedDMS_Core_Document::convert(), SeedDMS_Core_Document::wasConverted(), SeedDMS_Core_Document::viewOnline(), SeedDMS_Core_Document::getUrl() + + diff --git a/SeedDMS_Preview/Preview/Base.php b/SeedDMS_Preview/Preview/Base.php index 4d6b9cf1f..da153b305 100644 --- a/SeedDMS_Preview/Preview/Base.php +++ b/SeedDMS_Preview/Preview/Base.php @@ -44,7 +44,13 @@ class SeedDMS_Preview_Base { */ protected $timeout; - function __construct($previewDir, $timeout=5) { /* {{{ */ + /** + * @var boolean $xsendfile set to true if mod_xѕendfile is to be used + * @access protected + */ + protected $xsendfile; + + function __construct($previewDir, $timeout=5, $xsendfile=true) { /* {{{ */ if(!is_dir($previewDir)) { if (!SeedDMS_Core_File::makeDir($previewDir)) { $this->previewDir = ''; @@ -55,6 +61,7 @@ class SeedDMS_Preview_Base { $this->previewDir = $previewDir; } $this->timeout = intval($timeout); + $this->xsendfile = $xsendfile; } /* }}} */ static function execWithTimeout($cmd, $timeout=5) { /* {{{ */ @@ -112,6 +119,18 @@ class SeedDMS_Preview_Base { $this->converters = $arr; } /* }}} */ + /** + * Enable/Disable xsendfile extension + * + * Merges the list of passed converters with the already existing ones. + * Existing converters will be overwritten. + * + * @param boolean $xsendfile turn on/off use of xsendfile module in apache + */ + function setXsendfile($xsendfile) { /* {{{ */ + $this->xsendfile = $xsendfile; + } /* }}} */ + /** * Add a list of converters * @@ -144,7 +163,7 @@ class SeedDMS_Preview_Base { * @param string $filename */ protected function sendFile($filename) { /* {{{ */ - if(function_exists('apache_get_modules') && in_array('mod_xsendfile',apache_get_modules())) { + if($this->xsendfile && function_exists('apache_get_modules') && in_array('mod_xsendfile',apache_get_modules())) { header("X-Sendfile: ".$filename); } else { /* Make sure output buffering is off */ diff --git a/SeedDMS_Preview/Preview/PdfPreviewer.php b/SeedDMS_Preview/Preview/PdfPreviewer.php index 6833a7ae8..daae6a4ed 100644 --- a/SeedDMS_Preview/Preview/PdfPreviewer.php +++ b/SeedDMS_Preview/Preview/PdfPreviewer.php @@ -24,8 +24,8 @@ */ class SeedDMS_Preview_PdfPreviewer extends SeedDMS_Preview_Base { - function __construct($previewDir, $timeout=5) { /* {{{ */ - parent::__construct($previewDir, $timeout); + function __construct($previewDir, $timeout=5, $xsendfile=true) { /* {{{ */ + parent::__construct($previewDir, $timeout, $xsendfile); $this->converters = array( 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => "unoconv -d document -f pdf --stdout -v '%f' > '%o'", 'application/vnd.oasis.opendocument.text' => "unoconv -d document -f pdf --stdout -v '%f' > '%o'", @@ -53,9 +53,10 @@ class SeedDMS_Preview_PdfPreviewer extends SeedDMS_Preview_Base { return false; $document = $object->getDocument(); + $dms = $document->_dms; $dir = $this->previewDir.'/'.$document->getDir(); switch(get_class($object)) { - case "SeedDMS_Core_DocumentContent": + case $dms->getClassname('documentcontent'): $target = $dir.'p'.$object->getVersion(); break; case "SeedDMS_Core_DocumentFile": diff --git a/SeedDMS_Preview/Preview/Previewer.php b/SeedDMS_Preview/Preview/Previewer.php index 1f2521b71..b8df0ca1c 100644 --- a/SeedDMS_Preview/Preview/Previewer.php +++ b/SeedDMS_Preview/Preview/Previewer.php @@ -29,8 +29,8 @@ class SeedDMS_Preview_Previewer extends SeedDMS_Preview_Base { */ protected $width; - function __construct($previewDir, $width=40, $timeout=5) { /* {{{ */ - parent::__construct($previewDir, $timeout); + function __construct($previewDir, $width=40, $timeout=5, $xsendfile=true) { /* {{{ */ + parent::__construct($previewDir, $timeout, $xsendfile); $this->converters = array( 'image/png' => "convert -resize %wx '%f' '%o'", 'image/gif' => "convert -resize %wx '%f' '%o'", @@ -52,7 +52,7 @@ class SeedDMS_Preview_Previewer extends SeedDMS_Preview_Base { * @param integer $width width of preview image * @return string file name of preview image */ - public function getFileName($object, $width) { /* {{{ */ + protected function getFileName($object, $width) { /* {{{ */ if(!$object) return false; diff --git a/SeedDMS_Preview/package.xml b/SeedDMS_Preview/package.xml index 2afd6da7b..753cf4768 100644 --- a/SeedDMS_Preview/package.xml +++ b/SeedDMS_Preview/package.xml @@ -11,11 +11,11 @@ uwe@steinmann.cx yes - 2018-03-08 + 2019-02-11 - 1.2.8 - 1.2.0 + 1.2.10 + 1.2.10 stable @@ -23,7 +23,8 @@ GPL License -preview is also created if SeedDMS_Core_DocumentContent has a child class +new parameter for enabling/disabling xsendfile +fix creation of pdf preview if document content class is not SeedDMS_Core_DocumentContent @@ -370,5 +371,38 @@ mod_xsendfile if available execWithTimeout() reads data from stderr and returns it together with stdout in array + + 2018-03-08 + + + 1.2.8 + 1.2.0 + + + stable + stable + + GPL License + +preview is also created if SeedDMS_Core_DocumentContent has a child class + + + + 2018-07-13 + + + 1.2.9 + 1.2.9 + + + stable + stable + + GPL License + +make sure list of converters is always an array +usage of mod_sendfile can be configured + + diff --git a/controllers/class.AddDocument.php b/controllers/class.AddDocument.php index dd5bff46f..ff61cafaf 100644 --- a/controllers/class.AddDocument.php +++ b/controllers/class.AddDocument.php @@ -63,8 +63,8 @@ class SeedDMS_Controller_AddDocument extends SeedDMS_Controller_Common { $maxsizeforfulltext = $this->getParam('maxsizeforfulltext'); $defaultaccessdocs = $this->getParam('defaultaccessdocs'); - $result = $this->callHook('addDocument'); - if($result === null) { + $document = $this->callHook('addDocument'); + if($document === null) { $filesize = SeedDMS_Core_File::fileSize($userfiletmp); $res = $folder->addDocument($name, $comment, $expires, $owner, $keywords, $cats, $userfiletmp, utf8_basename($userfilename), @@ -87,13 +87,6 @@ class SeedDMS_Controller_AddDocument extends SeedDMS_Controller_Common { } } - if($index) { - $idoc = new $indexconf['IndexedDocument']($dms, $document, isset($settings->_converters['fulltext']) ? $settings->_converters['fulltext'] : null, !($filesize < $settings->_maxSizeForFullText)); - if(!$this->callHook('preIndexDocument', $document, $idoc)) { - } - $index->addDocument($idoc); - } - /* Add a default notification for the owner of the document */ if($settings->_enableOwnerNotification) { $res = $document->addNotify($user->getID(), true); @@ -107,13 +100,24 @@ class SeedDMS_Controller_AddDocument extends SeedDMS_Controller_Common { if($document->getGroupAccessMode($notgroup) >= M_READ) $res = $document->addNotify($notgroup->getID(), false); } - - if(!$this->callHook('postAddDocument', $document)) { - } - $result = $document; + } elseif($result === false) { + if(empty($this->errormsg)) + $this->errormsg = 'hook_addDocument_failed'; + return false; } - return $result; + if($index && $document) { + $idoc = new $indexconf['IndexedDocument']($dms, $document, isset($settings->_converters['fulltext']) ? $settings->_converters['fulltext'] : null, !($filesize < $settings->_maxSizeForFullText)); + if(false !== $this->callHook('preIndexDocument', $document, $idoc)) { + $index->addDocument($idoc); + $index->commit(); + } + } + + if(!$this->callHook('postAddDocument', $document)) { + } + + return $document; } /* }}} */ } diff --git a/controllers/class.Download.php b/controllers/class.Download.php index c8e381014..81a8c6ba7 100644 --- a/controllers/class.Download.php +++ b/controllers/class.Download.php @@ -28,7 +28,25 @@ class SeedDMS_Controller_Download extends SeedDMS_Controller_Common { switch($type) { case "version": - $content = $this->params['content']; + $version = $this->params['version']; + $document = $this->params['document']; + if($version < 1) { + $content = $this->callHook('documentLatestContent', $document); + if($content === null) + $content = $document->getLatestContent(); + } else { + $content = $this->callHook('documentContent', $document, $version); + if($content === null) + $content = $document->getContentByVersion($version); + } + if (!is_object($content)) { + $this->errormsg = 'invalid_version'; + return false; + } + /* set params['content'] for compatiblity with older extensions which + * expect the content in the controller + */ + $this->params['content'] = $content; if(null === $this->callHook('version')) { if(file_exists($dms->contentDir . $content->getPath())) { header("Content-Transfer-Encoding: binary"); @@ -43,5 +61,6 @@ class SeedDMS_Controller_Download extends SeedDMS_Controller_Common { } break; } + return true; } } diff --git a/controllers/class.EditFolder.php b/controllers/class.EditFolder.php index eeaf02634..f41399fe5 100644 --- a/controllers/class.EditFolder.php +++ b/controllers/class.EditFolder.php @@ -84,11 +84,14 @@ class SeedDMS_Controller_EditFolder extends SeedDMS_Controller_Common { } } - if(!$this->callHook('postEditFolder')) { - } + } elseif($result === false) { + if(empty($this->errormsg)) + $this->errormsg = 'hook_editFolder_failed'; + return false; + } - } else - return $result; + if(!$this->callHook('postEditFolder')) { + } return true; } diff --git a/controllers/class.Login.php b/controllers/class.Login.php index 5863676f8..bf5abc190 100644 --- a/controllers/class.Login.php +++ b/controllers/class.Login.php @@ -21,14 +21,206 @@ * @version Release: @package_version@ */ class SeedDMS_Controller_Login extends SeedDMS_Controller_Common { + /** + * @var array $user set if user could be logged in + * @access protected + */ + static protected $user; - public function run() { + public function getUser() { /* {{{ */ + return self::$user; + } /* }}} */ + + public function run() { /* {{{ */ $dms = $this->params['dms']; - $user = $this->params['user']; $settings = $this->params['settings']; $session = $this->params['session']; + $sesstheme = $this->params['sesstheme']; + $lang = $this->params['lang']; + $login = $this->params['login']; + $pwd = $this->params['pwd']; - if($this->callHook('postLogin')) { + self::$user = null; + + /* The preLogin hook may set self::$user which will prevent any further + * authentication process. + */ + if($this->callHook('preLogin')) { } - } + + $user = self::$user; + + /* The password may only be empty if the guest user tries to log in. + * There is just one guest account with id $settings->_guestID which + * is allowed to log in without a password. All other guest accounts + * are treated like regular logins + */ + if(!$user && $settings->_enableGuestLogin && (int) $settings->_guestID) { + $guestUser = $dms->getUser((int) $settings->_guestID); + if(!$guestUser) { + $this->setErrorMsg("login_error_text"); + return false; + } + if(($login != $guestUser->getLogin())) { + if ((!isset($pwd) || strlen($pwd)==0)) { + $this->setErrorMsg("login_error_text"); + return false; + } + } else { + $user = $guestUser; + } + } + + /* Run any additional authentication method. The hook must return a + * valid user, if the authentication succeeded. If it fails, it must + * return false and if the hook doesn't care at all, if must return null. + */ + if(!$user) { + $user = $this->callHook('authenticate'); + if(false === $user) { + if(empty($this->errormsg)) + $this->setErrorMsg("authentication_failed"); + return false; + } + } + + /* Deprecated: Run any additional authentication implemented in a hook */ + if(!$user && isset($GLOBALS['SEEDDMS_HOOKS']['authentication'])) { + foreach($GLOBALS['SEEDDMS_HOOKS']['authentication'] as $authObj) { + if(!$user && method_exists($authObj, 'authenticate')) { + $user = $authObj->authenticate($dms, $settings, $login, $pwd); + } + } + } + + /* Authenticate against LDAP server {{{ */ + if (!$user && isset($settings->_ldapHost) && strlen($settings->_ldapHost)>0) { + require_once("../inc/inc.ClassLdapAuthentication.php"); + $authobj = new SeedDMS_LdapAuthentication($dms, $settings); + $user = $authobj->authenticate($login, $pwd); + } /* }}} */ + + /* Authenticate against SeedDMS database {{{ */ + if(!$user) { + require_once("../inc/inc.ClassDbAuthentication.php"); + $authobj = new SeedDMS_DbAuthentication($dms, $settings); + $user = $authobj->authenticate($login, $pwd); + } /* }}} */ + + /* If the user is still not authenticated, then exit with an error */ + if(!$user) { + $this->callHook('loginFailed'); + $this->setErrorMsg("login_error_text"); + return false; + } + + self::$user = $user; + + /* Check for other restrictions which prevent the user from login, though + * the authentication was successfull. + * Checking for a guest login the second time, makes only sense if there are + * more guest users and the login was done with a password and a user name + * unequal to 'guest'. + */ + $userid = $user->getID(); + if (($userid == $settings->_guestID) && (!$settings->_enableGuestLogin)) { + $this->setErrorMsg("guest_login_disabled"); + return false; + } + + // Check if account is disabled + if($user->isDisabled()) { + $this->setErrorMsg("login_disabled_text"); + return false; + } + + // control admin IP address if required + if ($user->isAdmin() && ($_SERVER['REMOTE_ADDR'] != $settings->_adminIP ) && ( $settings->_adminIP != "") ){ + $this->setErrorMsg("invalid_user_id"); + return false; + } + + /* Run any additional checks which may prevent login */ + if(false === $this->callHook('restrictLogin', $user)) { + if(empty($this->errormsg)) + $this->setErrorMsg("login_restrictions_apply"); + return false; + } + + /* Clear login failures if login was successful */ + $user->clearLoginFailures(); + + // Capture the user's language and theme settings. + if (isset($_REQUEST["lang"]) && strlen($_REQUEST["lang"])>0 && is_numeric(array_search($_REQUEST["lang"],getLanguages())) ) { + $lang = $_REQUEST["lang"]; + $user->setLanguage($lang); + } + else { + $lang = $user->getLanguage(); + if (strlen($lang)==0) { + $lang = $settings->_language; + $user->setLanguage($lang); + } + } + if ($sesstheme) { + $user->setTheme($sesstheme); + } + else { + $sesstheme = $user->getTheme(); + if (strlen($sesstheme)==0) { + $sesstheme = $settings->_theme; + // $user->setTheme($sesstheme); + } + } + + // Delete all sessions that are more than 1 week or the configured + // cookie lifetime old. Probably not the most + // reliable place to put this check -- move to inc.Authentication.php? + if($settings->_cookieLifetime) + $lifetime = intval($settings->_cookieLifetime); + else + $lifetime = 7*86400; + if(!$session->deleteByTime($lifetime)) { + $this->setErrorMsg("error_occured"); + return false; + } + + if (isset($_COOKIE["mydms_session"])) { + /* This part will never be reached unless the session cookie is kept, + * but op.Logout.php deletes it. Keeping a session could be a good idea + * for retaining the clipboard data, but the user id in the session should + * be set to 0 which is not possible due to foreign key constraints. + * So for now op.Logout.php will delete the cookie as always + */ + /* Load session */ + $dms_session = $_COOKIE["mydms_session"]; + if(!$resArr = $session->load($dms_session)) { + /* Turn off http only cookies if jumploader is enabled */ + setcookie("mydms_session", $dms_session, time()-3600, $settings->_httpRoot, null, null, !$settings->_enableLargeFileUpload); //delete cookie + header("Location: " . $settings->_httpRoot . "out/out.Login.php?referuri=".$refer); + exit; + } else { + $session->updateAccess($dms_session); + $session->setUser($userid); + } + } else { + // Create new session in database + if(!$id = $session->create(array('userid'=>$userid, 'theme'=>$sesstheme, 'lang'=>$lang))) { + $this->setErrorMsg("error_occured"); + return false; + } + + // Set the session cookie. + if($settings->_cookieLifetime) + $lifetime = time() + intval($settings->_cookieLifetime); + else + $lifetime = 0; + setcookie("mydms_session", $id, $lifetime, $settings->_httpRoot, null, null, !$settings->_enableLargeFileUpload); + } + + if($this->callHook('postLogin', $user)) { + } + + return true; + } /* }}} */ } diff --git a/controllers/class.Preview.php b/controllers/class.Preview.php new file mode 100644 index 000000000..985d45dab --- /dev/null +++ b/controllers/class.Preview.php @@ -0,0 +1,75 @@ + + * @copyright Copyright (C) 2010-2013 Uwe Steinmann + * @version Release: @package_version@ + */ + +/** + * Class which does the busines logic for previewing a document + * + * @category DMS + * @package SeedDMS + * @author Uwe Steinmann + * @copyright Copyright (C) 2010-2013 Uwe Steinmann + * @version Release: @package_version@ + */ +class SeedDMS_Controller_Preview extends SeedDMS_Controller_Common { + + public function run() { + $dms = $this->params['dms']; + $type = $this->params['type']; + $settings = $this->params['settings']; + + switch($type) { + case "version": + $version = $this->params['version']; + $document = $this->params['document']; + $width = $this->params['width']; + if($version < 1) { + $content = $this->callHook('documentLatestContent', $document); + if($content === null) + $content = $document->getLatestContent(); + } else { + $content = $this->callHook('documentContent', $document, $version); + if($content === null) + $content = $document->getContentByVersion($version); + } + if (!is_object($content)) { + $this->errormsg = 'invalid_version'; + return false; + } + /* set params['content'] for compatiblity with older extensions which + * expect the content in the controller + */ + $this->params['content'] = $content; + if(null === $this->callHook('version')) { + if($width) + $previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir, $width); + else + $previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir); + $previewer->setConverters($settings->_converters['preview']); + $previewer->setXsendfile($settings->_enableXsendfile); + if(!$previewer->hasPreview($content)) { + if(!$previewer->createPreview($content)) { + } + } + if(!$previewer->hasPreview($content)) { + header('Content-Type: image/svg+xml'); + readfile('../views/'.$theme.'/images/empty.svg'); + exit; + } + header('Content-Type: image/png'); + $previewer->getPreview($content); + } + break; + } + return true; + } +} diff --git a/controllers/class.RemoveDocument.php b/controllers/class.RemoveDocument.php index 0c6271dc2..e522ed268 100644 --- a/controllers/class.RemoveDocument.php +++ b/controllers/class.RemoveDocument.php @@ -47,20 +47,23 @@ class SeedDMS_Controller_RemoveDocument extends SeedDMS_Controller_Common { if (!$document->remove()) { $this->errormsg = "error_occured"; return false; - } else { - - if(!$this->callHook('postRemoveDocument')) { - } - - /* Remove the document from the fulltext index */ - if($index) { - $lucenesearch = new $indexconf['Search']($index); - if($hit = $lucenesearch->getDocument($documentid)) { - $index->delete($hit->id); - $index->commit(); - } - } } + } elseif($result === false) { + if(empty($this->errormsg)) + $this->errormsg = 'hook_removeDocument_failed'; + return false; + } + + /* Remove the document from the fulltext index */ + if($index) { + $lucenesearch = new $indexconf['Search']($index); + if($hit = $lucenesearch->getDocument($documentid)) { + $index->delete($hit->id); + $index->commit(); + } + } + + if(!$this->callHook('postRemoveDocument')) { } return true; diff --git a/controllers/class.RemoveFolder.php b/controllers/class.RemoveFolder.php index 860fd9b0e..eec8f16f9 100644 --- a/controllers/class.RemoveFolder.php +++ b/controllers/class.RemoveFolder.php @@ -61,14 +61,15 @@ class SeedDMS_Controller_RemoveFolder extends SeedDMS_Controller_Common { if (!$folder->remove()) { $this->errormsg = 'error_occured'; return false; - } else { - - if(!$this->callHook('postRemoveFolder')) { - } - } - } else - return $result; + } elseif($result === false) { + if(empty($this->errormsg)) + $this->errormsg = 'hook_removeFolder_failed'; + return false; + } + + if(!$this->callHook('postRemoveFolder')) { + } return true; } diff --git a/controllers/class.UpdateDocument.php b/controllers/class.UpdateDocument.php index f7184b20e..6c7b97838 100644 --- a/controllers/class.UpdateDocument.php +++ b/controllers/class.UpdateDocument.php @@ -35,7 +35,6 @@ class SeedDMS_Controller_UpdateDocument extends SeedDMS_Controller_Common { return null; } - $name = $this->getParam('name'); $comment = $this->getParam('comment'); $dms = $this->params['dms']; $user = $this->params['user']; @@ -56,8 +55,8 @@ class SeedDMS_Controller_UpdateDocument extends SeedDMS_Controller_Common { $workflow = $this->getParam('workflow'); $maxsizeforfulltext = $this->getParam('maxsizeforfulltext'); - $result = $this->callHook('updateDocument'); - if($result === null) { + $content = $this->callHook('updateDocument'); + if($content === null) { $filesize = SeedDMS_Core_File::fileSize($userfiletmp); if($contentResult=$document->addContent($comment, $user, $userfiletmp, utf8_basename($userfilename), $filetype, $userfiletype, $reviewers, $approvers, $version=0, $attributes, $workflow)) { @@ -67,28 +66,33 @@ class SeedDMS_Controller_UpdateDocument extends SeedDMS_Controller_Common { } } - if($index) { - $lucenesearch = new $indexconf['Search']($index); - if($hit = $lucenesearch->getDocument((int) $document->getId())) { - $index->delete($hit->id); - } - $idoc = new $indexconf['IndexedDocument']($dms, $document, isset($settings->_converters['fulltext']) ? $settings->_converters['fulltext'] : null, !($filesize < $settings->_maxSizeForFullText)); - if(!$this->callHook('preIndexDocument', $document, $idoc)) { - } - $index->addDocument($idoc); - $index->commit(); - } - - if(!$this->callHook('postUpdateDocument', $document, $contentResult->getContent())) { - } - $result = $contentResult->getContent(); + $content = $contentResult->getContent(); } else { $this->errormsg = 'error_update_document'; $result = false; } + } elseif($result === false) { + if(empty($this->errormsg)) + $this->errormsg = 'hook_updateDocument_failed'; + return false; } - return $result; + if($index && $content) { + $lucenesearch = new $indexconf['Search']($index); + if($hit = $lucenesearch->getDocument((int) $document->getId())) { + $index->delete($hit->id); + } + $idoc = new $indexconf['IndexedDocument']($dms, $document, isset($settings->_converters['fulltext']) ? $settings->_converters['fulltext'] : null, !($filesize < $settings->_maxSizeForFullText)); + if(false !== $this->callHook('preIndexDocument', $document, $idoc)) { + $index->addDocument($idoc); + $index->commit(); + } + } + + if(!$this->callHook('postUpdateDocument', $document, $content)) { + } + + return $content; } /* }}} */ } diff --git a/controllers/class.ViewOnline.php b/controllers/class.ViewOnline.php index df072f6bb..b4c01be66 100644 --- a/controllers/class.ViewOnline.php +++ b/controllers/class.ViewOnline.php @@ -26,11 +26,28 @@ class SeedDMS_Controller_ViewOnline extends SeedDMS_Controller_Common { $dms = $this->params['dms']; $settings = $this->params['settings']; $type = $this->params['type']; - $content = $this->params['content']; - $document = $content->getDocument(); switch($type) { case "version": + $version = $this->params['version']; + $document = $this->params['document']; + if($version < 1) { + $content = $this->callHook('documentLatestContent', $document); + if($content === null) + $content = $document->getLatestContent(); + } else { + $content = $this->callHook('documentContent', $document, $version); + if($content === null) + $content = $document->getContentByVersion($version); + } + if (!is_object($content)) { + $this->errormsg = 'invalid_version'; + return false; + } + /* set params['content'] for compatiblity with older extensions which + * expect the content in the controller + */ + $this->params['content'] = $content; if(null === $this->callHook('version')) { header("Content-Type: " . $content->getMimeType()); $efilename = rawurlencode($content->getOriginalFileName()); @@ -46,5 +63,7 @@ class SeedDMS_Controller_ViewOnline extends SeedDMS_Controller_Common { } break; } + return true; } } + diff --git a/doc/README.Converters b/doc/README.Converters new file mode 100644 index 000000000..5256f0f89 --- /dev/null +++ b/doc/README.Converters @@ -0,0 +1,50 @@ +Conversion to pdf +================= + +text/plain +text/csv +application/vnd.oasis.opendocument.text +application/msword +application/vnd.wordperfect +application/rtf + unoconv -d document -f pdf --stdout -v '%f' > '%o' + +image/png +image/jpg +image/jpeg + convert -f pdf -density 300 '%f' '%o' + +application/vnd.ms-powerpoint +application/vnd.openxmlformats-officedocument.presentationml.presentation + unoconv -d presentation -f pdf --stdout -v '%f' > '%o' + +application/vnd.ms-excel +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + unoconv -d spreadsheet -f pdf --stdout -v '%f' > '%o' + +Preview +======== + +image/jpg +image/jpeg +image/png + convert -resize %wx '%f' '%o' + +application/pdf + gs -dBATCH -dNOPAUSE -sDEVICE=png16m -dPDFFitPage -r72x72 -sOutputFile=- -dFirstPage=1 -dLastPage=1 -q '%f' | convert -resize %wx png:- '%o' + +text/plain + a2ps -1 -a1 -R -B -o - '%f' | gs -dBATCH -dNOPAUSE -sDEVICE=png16m -dFirstPage=1 -dLastPage=1 -dPDFFitPage -r72x72 -sOutputFile=- -q - | convert -resize %wx png:- '%o' + +application/msword +application/vnd.oasis.opendocument.spreadsheet +application/vnd.oasis.opendocument.text +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet +application/vnd.ms-excel +application/vnd.openxmlformats-officedocument.wordprocessingml.document +application/rtf +application/vnd.ms-powerpoint +text/csv +application/vnd.wordperfect + /usr/bin/unoconv -d document -e PageRange=1 -f pdf --stdout -v '%f' | gs -dBATCH -dNOPAUSE -sDEVICE=pngalpha -dPDFFitPage -r72x72 -sOutputFile=- -dFirstPage=1 -dLastPage=1 -q - | convert -resize %wx png:- '%o' + diff --git a/doc/README.Dist-Layout b/doc/README.Dist-Layout index 5dd8a2d57..6822c63b5 100644 --- a/doc/README.Dist-Layout +++ b/doc/README.Dist-Layout @@ -21,7 +21,7 @@ SeedDMS_Lucene, SeedDMS_Preview, SeedDMS_SQLiteFTS. 'seeddms-5.1.x' are the sources of seeddms and 'www' being a link on it. This layout has disadvantages when updating the source of seeddms, because -the directories 'conf' and 'ext' has to be moved from 'seeddms-5.1.x' to +the directories 'conf' and 'ext' had to be moved from 'seeddms-5.1.x' to 'seeddms-5.1.(x+1)'. 'conf' was also visible over the web unless it was protected by an .htaccess file. The .htaccess file has been shipped, but it is far better to keep senѕitive data out of the document root in the first @@ -31,11 +31,14 @@ The new layout mostly retains that structure but uses more soft links to place the local data outside of 'seeddms-5.1.x' which makes updating a lot easier and moves the configuration out of the document root. As MS Windows does not support soft links, this change will only apply to Linux/Unix -systems. The new layout is the following: +systems. MS Windows users just skip all the soft links and set seeddms-5.1.x +as the document root. The new layout is the following: seeddms51x ---+--- data --+-- log | | - | +-- ext + | +-- cache + | | + | +-- 1048576 | | | +-- ... | @@ -69,17 +72,16 @@ seeddms51x ---+--- data --+-- log | +-- index.php -> ../seeddms/index.php | - +-- ext -> ../data/ext + +-- ext In order to convert to this layout you need to do the following in the seeddms51x -directory: +directory (replace the 'x' in '5.1.x' with the correct number): ln -s seeddms-5.1.x seeddms mv www/conf . -mv www/ext data -rm www -mdkir www +mv seeddms-5.1.x/ext www cd www +rm inc op out views controllers styles languages webdav restapi pdfviewer index.php ln -s ../seeddms/inc ln -s ../seeddms/op ln -s ../seeddms/out @@ -91,4 +93,3 @@ ln -s ../seeddms/webdav ln -s ../seeddms/restapi ln -s ../seeddms/pdfviewer ln -s ../seeddms/index.php -ln -s ../data/ext diff --git a/doc/README.Fail2ban b/doc/README.Fail2ban new file mode 100644 index 000000000..835e446d1 --- /dev/null +++ b/doc/README.Fail2ban @@ -0,0 +1,18 @@ +Adding authentication failure check for fail2ban +================================================= + +You will have to use 5.1.10 for this to work. + +Add a filter /etc/fail2ban/filter.d/seeddms.conf with the content + +[Definition] + +failregex = \[error\] -- \(\) op.Login login failed + +then configure a new jail in /etc/fail2ban/jail.d/seeddms.conf + +[seeddms] +enabled = yes +port = http,https +filter = seeddms +logpath = /home/www-data/seeddms-demo/data/log/*.log diff --git a/doc/README.Hooks b/doc/README.Hooks index 5e171ed4e..361a8e8c9 100644 --- a/doc/README.Hooks +++ b/doc/README.Hooks @@ -13,61 +13,153 @@ The SeedDMS application distinguishes between view hooks usually return some html output which is send to the browser and either replaces the default output or adds additional information. -A view hooks which returns false will be considered as not being called -at all. +A view hooks which returns null will be considered as not being called +at all. If the hook is expected to return something, it must be either +a string or an array of strings. controller hooks implement additional functions which either replace existing functions or add new ones. If such a hook returns null then this is treated as if the hook was not called. If the hook returns false it will prevent other hooks implementing the same function from being called. All other return values will not stop other hooks from -being called. +being called. A controller hook may set the error msg of the calling +controller. Currently available controller hooks ------------------------------------ AddDocument::preAddDocument Called before a new document will be added + If the hook returns false the document will not be added and the error msg + set by the hook will be issued. This hook is called before the parameters + are fetch from the controller. Therefore it is possible to modify them + in this hook. + +AddDocument::addDocument + Called when the new document is to be added + + This hook can be used to replace the code for adding a document. In + that case it must return a document or false. If + the hook does not return null, the original code for adding the + document will be skipped. + AddDocument::postAddDocument Called after a new document has been added + This hook will be called after a document was added, both by the + original code and within the hook addDocument. The hook is not called + if adding the document failed. The document will be passed to the hook. + The return value of this hook should always be null. + AddDocument::preIndexDocument Called before a new document will be indexed + This hook will be called after the document was added and before + the hook postAddDocument. The parameters passed + are the document and the indexed document. Returning false will prevent + the document from being indexed. + UpdateDocument::preUpdateDocument Called before a new document will be updated + If the hook returns false the document will not be updated and the error msg + set by the hook will be issued. This hook is called before the parameters + are fetch from the controller. Therefore it is possible to modify them + in this hook. + +UpdateDocument::updateDocument + Called when the document is to be updated + + This hook can be used to replace the code for updating a document. In + that case it must return a document content or false. If + the hook returns null, the original code for adding the + document will be executed. + UpdateDocument::postUpdateDocument Called after a new document has been updated + This hook will be called after a document was updated, both by the + original code and within the hook addDocument. + The document and content will be passed to the hook. + The return value of this hook should always be null. + UpdateDocument::preIndexDocument Called before an updated document will be indexed + This hook will be called after the document was updated and before + the hook postUpdateDocument. The parameters passed + are the document and the indexed document. Returning false will prevent + the document from being indexed. + RemoveDocument::preRemoveDocument Called before a document will be removed + If the hook returns false the document will not be removed and the error msg + set by the hook will be issued. + RemoveDocument::removeDocument - Called for removing the document. If the hook returns null the + Called when the document is to be removed + + If the hook returns null the regular document removal will happen. RemoveDocument::postRemoveDocument Called after a document was removed + This hook will be called after a document was removed, both by the + original code and within the hook removeDocument. It will not be + called if removing the document failed. + The return value of this hook should always be null. + RemoveFolder::preRemoveFolder - Called before a document will be removed + Called before a folder will be removed + + If the hook returns false the folder will not be removed and the error msg + set by the hook will be issued. RemoveFolder::removeFolder - Called for removing the folder. If the hook returns null the - regular folder removal will happen. + Called for removing the folder. + + If the hook returns null the regular folder removal will happen. + Keep in mind, that the hook function must also update the + full text index. RemoveFolder::postRemoveFolder Called after a document was removed + This hook will be called after a folder was removed, both by the + original code and within the hook removeFolder. It will not be + called if removing the folder failed. + The return value of this hook should always be null. + EditFolder::preEditFolder + Called before a folder will be updated + + If the hook returns false the folder will not be updated and the error msg + set by the hook will be issued. This hook is called before the parameters + are fetch from the controller. Therefore it is possible to modify them + in this hook. EditFolder::EditFolder + Called when the folder is to be updated + + This hook can be used to replace the code for updating a folder. If + the hook returns null, the original code for adding the + document will be executed. EditFolder::postEditFolder + Called after a folder was updated + + This hook will be called after a folder was updated, both by the + original code and within the hook removeFolder. It will not be + called if updating the folder failed. + The return value of this hook should always be null. + +TransferDocument::preTransferDocument + +TransferDocument::transferDocument + +TransferDocument::postTransferDocument ViewOnline::version Called when a document is downloaded for online view @@ -75,11 +167,34 @@ ViewOnline::version Download::version Called when a document is downloaded for saving on disk +Login::preLogin + Called before a user is logged in + +Login::authenticate + Called before any other authentication is done + + If this hooks returns a user, no other authentication will be done. + If it returns false, the login fails as well. + +Login::restrictLogin + Called right before the user is considered to be logged in + + This hook can contain a last check which keeps the user from being + logged in. Return false to stop login. The authenticated user is + passed to the hook. + Login::postLogin Called after user in fully logged in + The logged in user is passed to the hook. + +Login::loginFailed + Called if authentication failed + Logout::postLogout Called after user is logged out +IndexDocument::preIndexDocument + Currently available view hooks ------------------------------------ diff --git a/ext/example/class.example.php b/ext/example/class.example.php index fce09e0b0..af5b8eee9 100644 --- a/ext/example/class.example.php +++ b/ext/example/class.example.php @@ -43,6 +43,7 @@ class SeedDMS_ExtExample extends SeedDMS_ExtBase { * $GLOBALS['SEEDDMS_HOOKS'] : all hooks added so far */ function init() { /* {{{ */ + $GLOBALS['SEEDDMS_HOOKS']['initDMS'][] = new SeedDMS_ExtExample_InitDMS; $GLOBALS['SEEDDMS_HOOKS']['view']['addDocument'][] = new SeedDMS_ExtExample_AddDocument; $GLOBALS['SEEDDMS_HOOKS']['view']['viewFolder'][] = new SeedDMS_ExtExample_ViewFolder; $GLOBALS['SEEDDMS_SCHEDULER']['tasks']['example']['example'] = new SeedDMS_ExtExample_Task; @@ -52,6 +53,65 @@ class SeedDMS_ExtExample extends SeedDMS_ExtBase { } /* }}} */ } +class SeedDMS_ExtExample_HomeController { /* {{{ */ + + protected $dms; + + protected $settings; + + public function __construct($dms, $settings) { + $this->dms = $dms; + $this->settings = $settings; + } + + public function home($request, $response, $args) { + $response->getBody()->write('Output of route /ext/example/home'.get_class($this->dms)); + return $response; + } + + public function echos($request, $response, $args) { + $response->getBody()->write('Output of route /ext/example/echo'); + return $response; + } +} /* }}} */ + +/** + * Class containing methods for hooks when the dms is initialized + * + * @author Uwe Steinmann + * @package SeedDMS + * @subpackage example + */ +class SeedDMS_ExtExample_InitDMS { /* {{{ */ + + /** + * Hook after initializing the application + * + * This method sets the callback 'onAttributeValidate' in SeedDMS_Core + */ + public function addRoute($arr) { /* {{{ */ + $dms = $arr['dms']; + $settings = $arr['settings']; + $app = $arr['app']; + + $container = $app->getContainer(); + $container['HomeController'] = function($c) use ($dms, $settings) { +// $view = $c->get("view"); // retrieve the 'view' from the container + return new SeedDMS_ExtExample_HomeController($dms, $settings); + }; + + $app->get('/ext/example/home', 'HomeController:home'); + + $app->get('/ext/example/echos', + function ($request, $response) use ($app) { + echo "Output of route /ext/example/echo"; + } + ); + return null; + } /* }}} */ + +} /* }}} */ + /** * Class containing methods for hooks when a document is added * diff --git a/inc/inc.Authentication.php b/inc/inc.Authentication.php index 7ab085b95..de9e93a5c 100644 --- a/inc/inc.Authentication.php +++ b/inc/inc.Authentication.php @@ -25,7 +25,6 @@ if (!strncmp("/op", $refer, 3)) { } if (!isset($_COOKIE["mydms_session"])) { if($settings->_enableGuestLogin && $settings->_enableGuestAutoLogin) { - require_once("../inc/inc.ClassSession.php"); $session = new SeedDMS_Session($db); if(!$dms_session = $session->create(array('userid'=>$settings->_guestID, 'theme'=>$settings->_theme, 'lang'=>$settings->_language))) { header("Location: " . $settings->_httpRoot . "out/out.Login.php?referuri=".$refer); @@ -33,7 +32,6 @@ if (!isset($_COOKIE["mydms_session"])) { } $resArr = $session->load($dms_session); } elseif($settings->_autoLoginUser) { - require_once("../inc/inc.ClassSession.php"); if(!($user = $dms->getUser($settings->_autoLoginUser))/* || !$user->isGuest()*/) { header("Location: " . $settings->_httpRoot . "out/out.Login.php?referuri=".$refer); exit; diff --git a/inc/inc.ClassController.php b/inc/inc.ClassController.php index 608e91fba..04e70dca7 100644 --- a/inc/inc.ClassController.php +++ b/inc/inc.ClassController.php @@ -49,7 +49,7 @@ class Controller { if(!file_exists($filename)) $filename = ''; if($filename) { - require($filename); + require_once($filename); $controller = new $classname($params); /* Set some configuration parameters */ $controller->setParam('postVars', $_POST); diff --git a/inc/inc.ClassControllerCommon.php b/inc/inc.ClassControllerCommon.php index ea22d7147..7e5f33737 100644 --- a/inc/inc.ClassControllerCommon.php +++ b/inc/inc.ClassControllerCommon.php @@ -35,6 +35,12 @@ class SeedDMS_Controller_Common { */ protected $errormsg; + /** + * @var mixed $lasthookresult result of last hook + * @access protected + */ + protected $lasthookresult; + function __construct($params) { $this->params = $params; $this->error = 0; @@ -132,22 +138,59 @@ class SeedDMS_Controller_Common { } /* }}} */ /** - * Call a controller hook + * Call all hooks registered for a controller * - * If a hook returns false, then no other hook will be called, because the + * Executes all hooks registered for the current controller. + * A hook is just a php function which is passed the current controller and + * additional paramaters passed to this method. + * + * If a hook returns false, then no other hook will be called, because this * method returns right away. If hook returns null, then this is treated like - * it was never called and the default action is executed. Any other value - * returned by the hook will be returned by this method. + * it was never called and the next hook is called. Any other value + * returned by a hook will be temporarily saved (possibly overwriting a value + * from a previously called hook) and the next hook is called. + * The temporarily saved return value is eventually returned by this method + * when all hooks are called and no following hook failed. + * The temporarily saved return value is also saved in a protected class + * variable $lasthookresult which is initialized to null. This could be used + * by following hooks to check if preceding hook did already succeed. + * + * Consider that a failing hook (returns false) will imediately quit this + * function an return false, even if a formerly called hook has succeeded. + * Also consider, that a second succeeding hook will overwrite the return value + * of a previously called hook. + * Third, keep in mind that there is no predefined order of hooks. + * + * Example 1: Assuming the hook 'loginRestrictions' in the 'Login' controller + * is implemented by two extensions. + * One extension restricts login to a certain time of the day and a second one + * checks the strength of the password. If the password strength is to low, it + * will prevent login. If the hook in the first extension allows login (returns true) + * and the second doesn't (returns false), then this method will return false. + * If the hook in the second extension doesn't care and therefore returns null, then + * this method will return true. + * + * Example 2: Assuming the hook 'authenticate' in the 'Login' controller + * is implemented by two extensions. This hook must return false if authentication + * fails, null if the hook does not care, or a + * valid user in case of a successful authentication. + * If the first extension is able to authenticate the user, the hook in the second + * extension will still be called and could fail. So the return value of this + * method is false. The second hook could actually succeed as well and return a + * different user than the first hook which will eventually be returned by this + * method. The last hook will always win. If you need to know if a previously + * called hook succeeded, you can check the class variable $lasthookresult in the + * hook. * * @param $hook string name of hook * @return mixed false if one of the hooks fails, - * true if all hooks succedded, + * true/value if all hooks succedded, * null if no hook was called */ function callHook($hook) { /* {{{ */ $tmp = explode('_', get_class($this)); if(isset($GLOBALS['SEEDDMS_HOOKS']['controller'][lcfirst($tmp[2])])) { - $r = null; + $this->lasthookresult = null; foreach($GLOBALS['SEEDDMS_HOOKS']['controller'][lcfirst($tmp[2])] as $hookObj) { if (method_exists($hookObj, $hook)) { switch(func_num_args()) { @@ -165,11 +208,11 @@ class SeedDMS_Controller_Common { return $result; } if($result !== null) { - $r = $result; + $this->lasthookresult = $result; } } } - return $r; + return $this->lasthookresult; } return null; } /* }}} */ diff --git a/inc/inc.ClassSettings.php b/inc/inc.ClassSettings.php index 3c48ee88b..f2ad438db 100644 --- a/inc/inc.ClassSettings.php +++ b/inc/inc.ClassSettings.php @@ -174,6 +174,8 @@ class Settings { /* {{{ */ var $_partitionSize = 2000000; // max size of files uploaded by fine-uploader, set to 0 for unlimited var $_maxUploadSize = 0; + // enable/disables xsendfile + var $_enableXsendfile = true; // enable/disable users images var $_enableUserImage = false; // enable/disable replacing documents by webdav @@ -311,22 +313,11 @@ class Settings { /* {{{ */ exit; } } - $this->load($configFilePath); + if(!$this->load($configFilePath)) { + echo "Your configuration contains errors."; + exit; + } - // files with one of the following endings will be converted with the - // given commands for windows users - $this->_convertFileTypes = array(".doc" => "cscript \"" . $this->_rootDir."op/convert_word.js\" {SOURCE} {TARGET}", - ".xls" => "cscript \"".$this->_rootDir."op/convert_excel.js\" {SOURCE} {TARGET}", - ".ppt" => "cscript \"".$this->_rootDir."op/convert_pp.js\" {SOURCE} {TARGET}"); - // uncomment the next line for linux users - // $this->_convertFileTypes = array(".doc" => "mswordview -o {TARGET} {SOURCE}"); - - if (!is_null($this->_smtpServer)) - ini_set("SMTP", $this->_smtpServer); - if (!is_null($this->_smtpPort)) - ini_set("smtp_port", $this->_smtpPort); - if (!is_null($this->_smtpSendFrom)) - ini_set("sendmail_from", $this->_smtpSendFrom); if (!is_null($this->_maxExecutionTime)) ini_set("max_execution_time", $this->_maxExecutionTime); } /* }}} */ @@ -523,6 +514,7 @@ class Settings { /* {{{ */ $this->_enableLargeFileUpload = Settings::boolVal($tab["enableLargeFileUpload"]); $this->_partitionSize = strval($tab["partitionSize"]); $this->_maxUploadSize = strval($tab["maxUploadSize"]); + $this->_enableXsendfile = Settings::boolVal($tab["enableXsendfile"]); } // XML Path: /configuration/system/authentication @@ -858,6 +850,7 @@ class Settings { /* {{{ */ $this->setXMLAttributValue($node, "enableLargeFileUpload", $this->_enableLargeFileUpload); $this->setXMLAttributValue($node, "partitionSize", $this->_partitionSize); $this->setXMLAttributValue($node, "maxUploadSize", $this->_maxUploadSize); + $this->setXMLAttributValue($node, "enableXsendfile", $this->_enableXsendfile); // XML Path: /configuration/system/authentication $node = $this->getXMLNode($xml, '/configuration/system', 'authentication'); diff --git a/inc/inc.ClassViewCommon.php b/inc/inc.ClassViewCommon.php index e1a287d0e..934bb403c 100644 --- a/inc/inc.ClassViewCommon.php +++ b/inc/inc.ClassViewCommon.php @@ -121,10 +121,10 @@ class SeedDMS_View_Common { break; } if($tmpret !== null) { - if(is_string($tmpret)) - $ret .= $tmpret; - elseif(is_array($tmpret) || is_object($tmpret)) { - $ret = ($ret === null) ? $tmpret : array_merge($ret, $tmpret); + if(is_string($tmpret)) { + $ret = ($ret === null) ? $tmpret : (is_string($ret) ? $ret.$tmpret : array_merge($ret, array($tmpret))); + } elseif(is_array($tmpret) || is_object($tmpret)) { + $ret = ($ret === null) ? $tmpret : (is_string($ret) ? array_merge(array($ret), $tmpret) : array_merge($ret, $tmpret)); } else $ret = $tmpret; } diff --git a/inc/inc.Settings.php b/inc/inc.Settings.php index 50616d8c2..9e4479424 100644 --- a/inc/inc.Settings.php +++ b/inc/inc.Settings.php @@ -30,6 +30,9 @@ if(!defined("SEEDDMS_INSTALL") && file_exists(dirname($settings->_configFilePath if(isset($settings->_extraPath)) ini_set('include_path', $settings->_extraPath. PATH_SEPARATOR .ini_get('include_path')); +/* composer is installed in pear directory */ +require_once 'vendor/autoload.php'; + if(isset($settings->_maxExecutionTime)) ini_set('max_execution_time', $settings->_maxExecutionTime); diff --git a/inc/inc.Utils.php b/inc/inc.Utils.php index c2c7829ad..15e9a7452 100644 --- a/inc/inc.Utils.php +++ b/inc/inc.Utils.php @@ -348,9 +348,9 @@ function add_log_line($msg="", $priority=null) { /* {{{ */ else $ip = $_SERVER['REMOTE_ADDR']; if($user) - $logger->log($user->getLogin()." (".$ip.") ".basename($_SERVER["REQUEST_URI"], ".php").$msg, $priority); + $logger->log($user->getLogin()." (".$ip.") ".basename($_SERVER["REQUEST_URI"], ".php").($msg ? ' '.$msg : ''), $priority); else - $logger->log("-- (".$ip.") ".basename($_SERVER["REQUEST_URI"], ".php").$msg, $priority); + $logger->log("-- (".$ip.") ".basename($_SERVER["REQUEST_URI"], ".php").($msg ? ' '.$msg : ''), $priority); } /* }}} */ function _add_log_line($msg="") { /* {{{ */ @@ -563,7 +563,8 @@ function addDirSep($str) { /* {{{ */ * @param string $filename */ function sendFile($filename) { /* {{{ */ - if(function_exists('apache_get_modules') && in_array('mod_xsendfile',apache_get_modules())) { + global $settings; + if($settings->_enableXsendfile && function_exists('apache_get_modules') && in_array('mod_xsendfile',apache_get_modules())) { header("X-Sendfile: ".$filename); } else { /* Make sure output buffering is off */ diff --git a/inc/inc.Version.php b/inc/inc.Version.php index 13abdbe01..f9240bab5 100644 --- a/inc/inc.Version.php +++ b/inc/inc.Version.php @@ -20,7 +20,7 @@ class SeedDMS_Version { - public $_number = "5.1.9"; + public $_number = "5.1.10"; private $_string = "SeedDMS"; function __construct() { diff --git a/index.php b/index.php index 265567b17..757176741 100644 --- a/index.php +++ b/index.php @@ -1,33 +1,78 @@ -_siteDefaultPage) && strlen($settings->_siteDefaultPage)>0 ? $settings->_siteDefaultPage : "out/out.ViewFolder.php")); -?> - - - SeedDMS - - - - - - - +getUri(); + if($uri->getBasePath()) + $file = $uri->getPath(); + else + $file = substr($uri->getPath(), 1); + if(file_exists($file) && is_file($file)) { + $_SERVER['SCRIPT_FILENAME'] = basename($file); + include($file); + exit; + } +// print_r($request->getUri()); +// exit; + return $c['response'] + ->withStatus(302) + ->withHeader('Location', isset($settings->_siteDefaultPage) && strlen($settings->_siteDefaultPage)>0 ? $settings->_httpRoot.$settings->_siteDefaultPage : $settings->_httpRoot."out/out.ViewFolder.php"); + }; + }; + $app = new \Slim\App($c); + + if(isset($GLOBALS['SEEDDMS_HOOKS']['initDMS'])) { + foreach($GLOBALS['SEEDDMS_HOOKS']['initDMS'] as $hookObj) { + if (method_exists($hookObj, 'addRoute')) { + $hookObj->addRoute(array('dms'=>$dms, 'user'=>$user, 'app'=>$app, 'settings'=>$settings)); + } + } + } + + $app->run(); +} else { + + header("Location: ". (isset($settings->_siteDefaultPage) && strlen($settings->_siteDefaultPage)>0 ? $settings->_siteDefaultPage : "out/out.ViewFolder.php")); +?> + + + SeedDMS + + + + + + + + diff --git a/install/install.php b/install/install.php index 126de3d44..ccc4abcee 100644 --- a/install/install.php +++ b/install/install.php @@ -122,8 +122,10 @@ function fileExistsInIncludePath($file) { /* {{{ */ /** * Load default settings + set */ +require_once('../inc/inc.Version.php'); +$ver = new SeedDMS_Version(); define("SEEDDMS_INSTALL", "on"); -define("SEEDDMS_VERSION", "5.1.9"); +define("SEEDDMS_VERSION", $ver->version()); require_once('../inc/inc.ClassSettings.php'); diff --git a/languages/ar_EG/lang.inc b/languages/ar_EG/lang.inc index bbb3b9794..2578d6f78 100644 --- a/languages/ar_EG/lang.inc +++ b/languages/ar_EG/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (1305) +// Translators: Admin (1307) $text = array( '2_factor_auth' => '', @@ -186,6 +186,7 @@ URL: [url]', 'at_least_n_users_of_group' => '', 'august' => 'أغسطس', 'authentication' => '', +'authentication_failed' => '', 'author' => 'ﺎﻠﻤﻨﺸﺋ', 'automatic_status_update' => 'تغير الحالة تلقائيا', 'back' => 'العودة للخلف', @@ -469,6 +470,7 @@ URL: [url]', 'error_add_aro' => '', 'error_add_permission' => '', 'error_cleared_cache' => '', +'error_edit_task' => '', 'error_extension_getlist' => '', 'error_importfs' => '', 'error_no_document_selected' => 'لم يتم اختيار مستند', @@ -477,8 +479,12 @@ URL: [url]', 'error_remove_document' => '', 'error_remove_folder' => 'ﺡﺪﺛ ﺦﻃﺃ ﺎﺜﻧﺍﺀ ﺡﺬﻓ ﺎﻠﻤﺠﻟﺩ', 'error_remove_permission' => '', +'error_rm_workflow' => '', +'error_rm_workflow_action' => '', +'error_rm_workflow_state' => '', 'error_toogle_permission' => '', 'error_transfer_document' => '', +'error_trigger_workflow' => '', 'error_update_document' => '', 'error_uploading_reviewer_only' => '', 'es_ES' => 'الإسبانية', @@ -621,7 +627,6 @@ URL: [url]', 'index_waiting' => 'ﻲﻨﺘﻇﺭ', 'individuals' => 'افراد', 'individuals_in_groups' => '', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => '', 'inherited' => 'موروث', 'inherits_access_copy_msg' => 'نسخ قائمة صلاحيات موروثة.', @@ -714,9 +719,11 @@ URL: [url]', 'login_error_title' => 'خطأ في الدخول', 'login_not_given' => 'لم يتم ادخال اسم المستخدم', 'login_ok' => 'دخول صحيح', +'login_restrictions_apply' => '', 'logout' => 'خروج', 'log_management' => 'ادارة ملفات السجلات', -'lo_LA' => '', +'lo_LA' => 'ﺎﻠﻤﻛﺎﻧ', +'malformed_expiration_date' => '', 'manager' => 'مدير', 'manager_of_group' => '', 'mandatory_approvergroups' => '', @@ -731,6 +738,7 @@ URL: [url]', 'max_upload_size' => 'الحجم الاقصى للملف', 'may' => 'مايو', 'menu_dropfolder' => '', +'menu_upload_from_dropfolder' => '', 'mimetype' => 'Mime type', 'minutes' => 'دقائق', 'misc' => 'متنوعات', @@ -1133,6 +1141,8 @@ URL: [url]', 'settings_Advanced' => 'متقدم', 'settings_advancedAcl' => '', 'settings_advancedAcl_desc' => '', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', 'settings_allowReviewerOnly' => '', 'settings_allowReviewerOnly_desc' => '', 'settings_apache_mod_rewrite' => 'Apache - Module Rewrite', @@ -1284,6 +1294,8 @@ URL: [url]', 'settings_enableVersionModification_desc' => '', 'settings_enableWebdavReplaceDoc' => '', 'settings_enableWebdavReplaceDoc_desc' => '', +'settings_enableXsendfile' => '', +'settings_enableXsendfile_desc' => '', 'settings_encryptionKey' => '', 'settings_encryptionKey_desc' => '', 'settings_error' => 'خطأ', @@ -1507,6 +1519,7 @@ URL: [url]', 'splash_edit_event' => '', 'splash_edit_group' => '', 'splash_edit_role' => '', +'splash_edit_task' => '', 'splash_edit_user' => '', 'splash_error_add_to_transmittal' => '', 'splash_error_rm_download_link' => '', @@ -1537,6 +1550,9 @@ URL: [url]', 'splash_rm_transmittal' => '', 'splash_rm_user' => '', 'splash_rm_user_processes' => '', +'splash_rm_workflow' => '', +'splash_rm_workflow_action' => '', +'splash_rm_workflow_state' => '', 'splash_saved_file' => '', 'splash_save_user_data' => '', 'splash_send_download_link' => '', @@ -1549,6 +1565,7 @@ URL: [url]', 'splash_toogle_group_manager' => '', 'splash_transfer_document' => '', 'splash_transfer_objects' => '', +'splash_trigger_workflow' => '', 'state_and_next_state' => '', 'statistic' => '', 'status' => 'الحالة', @@ -1762,7 +1779,7 @@ URL: [url]', 'workflow_summary' => 'ملخص مسار العمل', 'workflow_transition_without_user_group' => '', 'workflow_user_summary' => 'ملخص المستخدم', -'x_more_objects' => '', +'x_more_objects' => 'ﺎﻟﺮﻘﻣ', 'year_view' => 'عرض السنة', 'yes' => 'نعم', 'zh_CN' => 'الصينية (CN)', diff --git a/languages/bg_BG/lang.inc b/languages/bg_BG/lang.inc index 4e03d2f85..9d4d80eab 100644 --- a/languages/bg_BG/lang.inc +++ b/languages/bg_BG/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (850) +// Translators: Admin (858) $text = array( '2_factor_auth' => '', @@ -169,6 +169,7 @@ $text = array( 'at_least_n_users_of_group' => '', 'august' => 'Август', 'authentication' => '', +'authentication_failed' => '', 'author' => 'Автор', 'automatic_status_update' => 'Автоматично изменение на статуса', 'back' => 'Назад', @@ -206,13 +207,13 @@ $text = array( 'change_revisors' => '', 'change_status' => 'Промени статусът', 'charts' => 'Графики', -'chart_docsaccumulated_title' => '', -'chart_docspercategory_title' => '', +'chart_docsaccumulated_title' => 'Брой документи', +'chart_docspercategory_title' => 'Документи според категория', 'chart_docspermimetype_title' => '', -'chart_docspermonth_title' => '', -'chart_docsperstatus_title' => '', -'chart_docsperuser_title' => '', -'chart_selection' => '', +'chart_docspermonth_title' => 'Нови документи за месец', +'chart_docsperstatus_title' => 'Документи според статус', +'chart_docsperuser_title' => 'Документи на юзър', +'chart_selection' => 'Изберете диаграма', 'chart_sizeperuser_title' => '', 'checkedout_file_has_different_version' => '', 'checkedout_file_has_disappeared' => '', @@ -422,6 +423,7 @@ $text = array( 'error_add_aro' => '', 'error_add_permission' => '', 'error_cleared_cache' => '', +'error_edit_task' => '', 'error_extension_getlist' => '', 'error_importfs' => '', 'error_no_document_selected' => 'Няма избрани документи', @@ -430,8 +432,12 @@ $text = array( 'error_remove_document' => '', 'error_remove_folder' => '', 'error_remove_permission' => '', +'error_rm_workflow' => '', +'error_rm_workflow_action' => '', +'error_rm_workflow_state' => '', 'error_toogle_permission' => '', 'error_transfer_document' => '', +'error_trigger_workflow' => '', 'error_update_document' => '', 'error_uploading_reviewer_only' => '', 'es_ES' => 'Испански', @@ -550,7 +556,6 @@ $text = array( 'index_waiting' => '', 'individuals' => 'Личности', 'individuals_in_groups' => '', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => '', 'inherited' => 'наследен', 'inherits_access_copy_msg' => 'Изкопирай наследения список', @@ -643,9 +648,11 @@ $text = array( 'login_error_title' => 'Грешка при влизане', 'login_not_given' => 'Не е указан потребител', 'login_ok' => 'Входът успешен', +'login_restrictions_apply' => '', 'logout' => 'Изход', 'log_management' => 'Управление на логове', -'lo_LA' => '', +'lo_LA' => 'Лаос', +'malformed_expiration_date' => '', 'manager' => 'Началник', 'manager_of_group' => '', 'mandatory_approvergroups' => '', @@ -660,6 +667,7 @@ $text = array( 'max_upload_size' => 'Лимит за размер на файла', 'may' => 'май', 'menu_dropfolder' => '', +'menu_upload_from_dropfolder' => '', 'mimetype' => 'Mime тип', 'minutes' => 'минути', 'misc' => 'Разни', @@ -996,6 +1004,8 @@ $text = array( 'settings_Advanced' => 'Допълнително', 'settings_advancedAcl' => '', 'settings_advancedAcl_desc' => '', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', 'settings_allowReviewerOnly' => '', 'settings_allowReviewerOnly_desc' => '', 'settings_apache_mod_rewrite' => 'Apache - Module Rewrite', @@ -1147,6 +1157,8 @@ $text = array( 'settings_enableVersionModification_desc' => 'Разреши/забрани промяната на версия на документ от обикновен потребител след като версията е качена. Администраторите могат винаги да променят версията след качване.', 'settings_enableWebdavReplaceDoc' => '', 'settings_enableWebdavReplaceDoc_desc' => '', +'settings_enableXsendfile' => '', +'settings_enableXsendfile_desc' => '', 'settings_encryptionKey' => 'Кодиращ ключ', 'settings_encryptionKey_desc' => 'Този стринг се използва за създаване на уникален идентификатор, който добавен като невидимо поле към формуляр, предотвратява CSRF атаки.', 'settings_error' => 'Грешка', @@ -1155,7 +1167,7 @@ $text = array( 'settings_expandFolderTree_val0' => 'започвайки от сгънато дърво', 'settings_expandFolderTree_val1' => 'започвайки от сгънато дърво с разгънато перво ниво', 'settings_expandFolderTree_val2' => 'започвайки от напълно разгънато дърво', -'settings_Extensions' => '', +'settings_Extensions' => 'Разширения', 'settings_extraPath' => 'Extra PHP include Path', 'settings_extraPath_desc' => 'Път към доп. софт. Това е директорията съдържаща напр. the adodb directory or additional pear packages', 'settings_firstDayOfWeek' => 'Първи ден на седмицата', @@ -1370,6 +1382,7 @@ $text = array( 'splash_edit_event' => '', 'splash_edit_group' => '', 'splash_edit_role' => '', +'splash_edit_task' => '', 'splash_edit_user' => '', 'splash_error_add_to_transmittal' => '', 'splash_error_rm_download_link' => '', @@ -1400,6 +1413,9 @@ $text = array( 'splash_rm_transmittal' => '', 'splash_rm_user' => '', 'splash_rm_user_processes' => '', +'splash_rm_workflow' => '', +'splash_rm_workflow_action' => '', +'splash_rm_workflow_state' => '', 'splash_saved_file' => '', 'splash_save_user_data' => '', 'splash_send_download_link' => '', @@ -1412,6 +1428,7 @@ $text = array( 'splash_toogle_group_manager' => '', 'splash_transfer_document' => '', 'splash_transfer_objects' => '', +'splash_trigger_workflow' => '', 'state_and_next_state' => '', 'statistic' => '', 'status' => 'Статус', diff --git a/languages/ca_ES/lang.inc b/languages/ca_ES/lang.inc index 37a9e89c6..f09c7f3b1 100644 --- a/languages/ca_ES/lang.inc +++ b/languages/ca_ES/lang.inc @@ -174,6 +174,7 @@ URL: [url]', 'at_least_n_users_of_group' => '', 'august' => 'Agost', 'authentication' => '', +'authentication_failed' => '', 'author' => 'Autor', 'automatic_status_update' => 'Canvi automátic d\'estat', 'back' => 'Endarrere', @@ -427,6 +428,7 @@ URL: [url]', 'error_add_aro' => '', 'error_add_permission' => '', 'error_cleared_cache' => '', +'error_edit_task' => '', 'error_extension_getlist' => '', 'error_importfs' => '', 'error_no_document_selected' => '', @@ -435,8 +437,12 @@ URL: [url]', 'error_remove_document' => '', 'error_remove_folder' => '', 'error_remove_permission' => '', +'error_rm_workflow' => '', +'error_rm_workflow_action' => '', +'error_rm_workflow_state' => '', 'error_toogle_permission' => '', 'error_transfer_document' => '', +'error_trigger_workflow' => '', 'error_update_document' => '', 'error_uploading_reviewer_only' => '', 'es_ES' => 'Castellà', @@ -555,7 +561,6 @@ URL: [url]', 'index_waiting' => '', 'individuals' => 'Individuals', 'individuals_in_groups' => '', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => '', 'inherited' => 'Heredat', 'inherits_access_copy_msg' => 'Copiar llista d\'accés heretat', @@ -648,9 +653,11 @@ URL: [url]', 'login_error_title' => 'Error d\'accés', 'login_not_given' => 'Nom d\'usuari no facilitat.', 'login_ok' => 'Accés amb èxit', +'login_restrictions_apply' => '', 'logout' => 'Desconnectar', 'log_management' => 'Gestió de fitxers de registre', 'lo_LA' => 'Laosià', +'malformed_expiration_date' => '', 'manager' => 'Manager', 'manager_of_group' => '', 'mandatory_approvergroups' => '', @@ -665,6 +672,7 @@ URL: [url]', 'max_upload_size' => 'Mida màxima de pujada de cada fitxer', 'may' => 'Maig', 'menu_dropfolder' => '', +'menu_upload_from_dropfolder' => '', 'mimetype' => '', 'minutes' => '', 'misc' => 'Miscelànea', @@ -1001,6 +1009,8 @@ URL: [url]', 'settings_Advanced' => '', 'settings_advancedAcl' => '', 'settings_advancedAcl_desc' => '', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', 'settings_allowReviewerOnly' => '', 'settings_allowReviewerOnly_desc' => '', 'settings_apache_mod_rewrite' => 'Apache - Module Rewrite', @@ -1152,6 +1162,8 @@ URL: [url]', 'settings_enableVersionModification_desc' => '', 'settings_enableWebdavReplaceDoc' => '', 'settings_enableWebdavReplaceDoc_desc' => '', +'settings_enableXsendfile' => '', +'settings_enableXsendfile_desc' => '', 'settings_encryptionKey' => '', 'settings_encryptionKey_desc' => '', 'settings_error' => 'Error', @@ -1375,6 +1387,7 @@ URL: [url]', 'splash_edit_event' => '', 'splash_edit_group' => '', 'splash_edit_role' => '', +'splash_edit_task' => '', 'splash_edit_user' => '', 'splash_error_add_to_transmittal' => '', 'splash_error_rm_download_link' => '', @@ -1405,6 +1418,9 @@ URL: [url]', 'splash_rm_transmittal' => '', 'splash_rm_user' => '', 'splash_rm_user_processes' => '', +'splash_rm_workflow' => '', +'splash_rm_workflow_action' => '', +'splash_rm_workflow_state' => '', 'splash_saved_file' => '', 'splash_save_user_data' => '', 'splash_send_download_link' => '', @@ -1417,6 +1433,7 @@ URL: [url]', 'splash_toogle_group_manager' => '', 'splash_transfer_document' => '', 'splash_transfer_objects' => '', +'splash_trigger_workflow' => '', 'state_and_next_state' => '', 'statistic' => 'Estadístiques', 'status' => 'Estat', diff --git a/languages/cs_CZ/lang.inc b/languages/cs_CZ/lang.inc index df4ec5c2c..a045cd91c 100644 --- a/languages/cs_CZ/lang.inc +++ b/languages/cs_CZ/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (1521), kreml (455) +// Translators: Admin (1521), kreml (579) $text = array( '2_factor_auth' => 'dvoufaktorové ověření', @@ -59,7 +59,7 @@ URL: [url]', 'add_document_link' => 'Přidat odkaz', 'add_document_notify' => 'Přiřaďte oznámení', 'add_doc_reviewer_approver_warning' => 'Pozn.: Dokumenty se automaticky označí jako vydané, když není přidělen žádný recenzent nebo schvalovatel.', -'add_doc_workflow_warning' => 'Pozn. Není-li zadán pracovní postup, jsou dokumenty automaticky označeny jako uvolněné.', +'add_doc_workflow_warning' => 'Pozn. Dokumenty jsou automaticky označeny jako vydané, pokud není přiřazeno žádné workflow.', 'add_event' => 'Přidat akci', 'add_group' => 'Přidat novou skupinu', 'add_member' => 'Přidat člena', @@ -76,9 +76,9 @@ URL: [url]', 'add_transmittal' => 'Přidat přenos', 'add_user' => 'Přidat nového uživatele', 'add_user_to_group' => 'Přidat uživatele do skupiny', -'add_workflow' => 'Přidat nový pracovní postup', -'add_workflow_action' => 'Přidat novou akci pracovního postupu', -'add_workflow_state' => 'Přidat nový stav pracovního postupu', +'add_workflow' => 'Přidat nové workflow', +'add_workflow_action' => 'Přidat novou akci workflow', +'add_workflow_state' => 'Přidat nový stav workflow', 'admin' => 'Správce', 'admin_tools' => 'Nástroje správce', 'all' => 'Vše', @@ -198,6 +198,7 @@ URL: [url]', 'at_least_n_users_of_group' => 'Alespoň [number_of_users] uživatelů z [group]', 'august' => 'Srpen', 'authentication' => 'Autentizace', +'authentication_failed' => '', 'author' => 'Autor', 'automatic_status_update' => 'Automatická změna stavu', 'back' => 'Přejít zpět', @@ -215,10 +216,10 @@ URL: [url]', 'cannot_change_final_states' => 'Upozornění: Nemůžete měnit stav dokumentu: zamítnutého, s vypršenou platností, posuzovaného nebo schvalovaného.', 'cannot_delete_user' => 'Uživatele nejde smazat', 'cannot_delete_yourself' => 'Nelze odstranit sám sebe', -'cannot_move_root' => 'Chyba: Není možné přesunout kořenový adresář.', +'cannot_move_root' => 'Chyba: Není možné přesunout kořenovovou složku.', 'cannot_retrieve_approval_snapshot' => 'Není možné získat informaci o stavu schválení této verze dokumentu.', 'cannot_retrieve_review_snapshot' => 'Není možné získat informaci o stavu recenze této verze dokumentu.', -'cannot_rm_root' => 'Chyba: Není možné smazat kořenový adresář.', +'cannot_rm_root' => 'Chyba: Není možné smazat kořenovou složku.', 'categories' => 'Kategorie', 'categories_loading' => 'Počkejte prosím, dokud nebude načten seznam kategorií ...', 'category' => 'Kategorie', @@ -260,16 +261,16 @@ URL: [url]', 'choose_target_file' => 'Zvolte soubor', 'choose_target_folder' => 'Vyberte cílovou složku', 'choose_user' => 'Vyberte uživatele', -'choose_workflow' => 'Zvolte pracovní postup', -'choose_workflow_action' => 'Zvolte akci pracovního postupu', -'choose_workflow_state' => 'Zvolte stav pracovního postupu', +'choose_workflow' => 'Vyberte workflow', +'choose_workflow_action' => 'Vyberte akci workflow', +'choose_workflow_state' => 'Vyberte stav workflow', 'class_name' => 'Název třídy', 'clear_cache' => 'Vymazat vyrovnávací paměť', 'clear_clipboard' => 'Vyčistit schránku', 'clear_password' => 'Vymazat heslo', 'clipboard' => 'Schránka', 'close' => 'Zavřít', -'command' => '', +'command' => 'příkaz', 'comment' => 'Komentář', 'comment_changed_email' => '', 'comment_for_current_version' => 'Komentář k aktuální verzi', @@ -342,7 +343,7 @@ URL: [url]', 'documents_to_receipt' => 'Dokumenty čekající na potvrzení příjmu', 'documents_to_review' => 'Dokumenty čekající na recenzi uživatele', 'documents_to_revise' => 'Dokumenty čekající na revizi', -'documents_to_trigger_workflow' => 'Dokumenty v pracovním postupu', +'documents_to_trigger_workflow' => 'Dokumenty ve workflow', 'documents_user_draft' => 'Návrhy', 'documents_user_expiration' => 'Dokumenty s vypršenou platností', 'documents_user_needs_correction' => 'Dokumenty, které je třeba opravit', @@ -381,7 +382,7 @@ Nadřazená složka: [folder_path] Uživatel: [username]', 'document_deleted_email_subject' => '[sitename]: [name] - Dokument smazán', 'document_duplicate_name' => 'Duplicitní název dokumentu', -'document_has_no_workflow' => 'Dokument nemá pracovní postup', +'document_has_no_workflow' => 'Dokument nemá workflow', 'document_infos' => 'Informace o dokumentu', 'document_is_checked_out' => 'Dokument je aktuálně zkontrolován. Pokud nahrajete novou verzi, nemůžete již kontrolovanou verzi zkontrolovat.', 'document_is_not_locked' => 'Tento dokument není zamčený', @@ -476,7 +477,7 @@ Odkaz je platný do [valid]. 'edit_folder_access' => 'Upravit přístup', 'edit_folder_attrdefgrp' => 'Upravit atributy skupin', 'edit_folder_notify' => 'Seznam upozornění', -'edit_folder_props' => 'Upravit adresář', +'edit_folder_props' => 'Upravit složku', 'edit_group' => 'Upravit skupinu', 'edit_online' => 'Upravit online', 'edit_task' => 'Upravit úkol', @@ -500,6 +501,7 @@ Odkaz je platný do [valid]. 'error_add_aro' => 'Chyba při přidávání požadavku přístupu k objektu', 'error_add_permission' => 'Chyba při přidání oprávnění', 'error_cleared_cache' => 'Chyba při vymazání mezipaměti', +'error_edit_task' => '', 'error_extension_getlist' => 'Chyba při získání seznamu rozšíření z úložiště', 'error_importfs' => 'Chyba při importu formy souborového systému', 'error_no_document_selected' => 'Není vybrán žádný dokument.', @@ -508,8 +510,12 @@ Odkaz je platný do [valid]. 'error_remove_document' => 'Při mazání dokumentu došlo k chybě', 'error_remove_folder' => 'Při mazání složky došlo k chybě', 'error_remove_permission' => 'Chyba při odebrání oprávnění', +'error_rm_workflow' => 'Chyba při odstraňování workflow', +'error_rm_workflow_action' => 'Chyba pří odstraňování akce workflow', +'error_rm_workflow_state' => 'Chyba pří odstraňování stavu workflow', 'error_toogle_permission' => 'Chyba při změně oprávnění', 'error_transfer_document' => 'Chyba při přenosu dokumentu', +'error_trigger_workflow' => 'Chyba při spouštění přechodu workflow', 'error_update_document' => '', 'error_uploading_reviewer_only' => 'Chyba při vytváření dokumentu. Dokument má recenzenta, ale nemá schvalovatele.', 'es_ES' => 'Španělština', @@ -593,7 +599,7 @@ Nová složka: [new_folder_path] Uživatel: [username] URL: [url]', 'folder_moved_email_subject' => '[sitename]: [name] - Složka přesunuta', -'folder_renamed_email' => 'Adresář přejmenován', +'folder_renamed_email' => 'Složka přejmenována', 'folder_renamed_email_body' => 'Složka přejmenována Složka: [name] Nadřazená složka: [folder_path] @@ -601,7 +607,7 @@ Starý název: [old_name] Uživatel: [username] URL: [url]', 'folder_renamed_email_subject' => '[sitename]: [name] - Složka přejmenována', -'folder_title' => 'Adresář \'[foldername]\'', +'folder_title' => 'Složka \'[foldername]\'', 'force_update' => 'Aktualizace', 'friday' => 'Pátek', 'friday_abbr' => 'Pá', @@ -609,16 +615,16 @@ URL: [url]', 'fr_FR' => 'Francouzština', 'fullsearch' => 'Fulltextové vyhledávání', 'fullsearch_hint' => 'Použijte fultext index', -'fulltextsearch_disabled' => '', +'fulltextsearch_disabled' => 'fulltextové vyhledávání zakázáno', 'fulltext_converters' => 'Index konverze dokumentu', 'fulltext_info' => 'Fulltext index info', 'global_attributedefinitiongroups' => 'Skupiny atributů', 'global_attributedefinitions' => 'Atributy', 'global_default_keywords' => 'Globální klíčová slova', 'global_document_categories' => 'Globální kategorie', -'global_workflows' => 'Pracovní postupy', -'global_workflow_actions' => 'Akce pracovního postupu', -'global_workflow_states' => 'Stavy pracovního postupu', +'global_workflows' => 'Workflows', +'global_workflow_actions' => 'Akce workflow', +'global_workflow_states' => 'Stavy workflow', 'group' => 'Skupina', 'groups' => 'Skupiny', 'group_approval_summary' => 'Souhrn schválení skupiny', @@ -658,8 +664,7 @@ URL: [url]', 'index_pending' => 'Probíhá indexování', 'index_waiting' => 'Čekání', 'individuals' => 'Jednotlivci', -'individuals_in_groups' => '', -'indivіduals_in_groups' => 'Členové skupiny', +'individuals_in_groups' => 'Členové skupiny', 'info_recipients_tab_not_released' => 'Potvrzení o příjmu této verze dokumentu není možné, protože verze není uvolněna.', 'inherited' => 'Zděděno', 'inherits_access_copy_msg' => 'Zkopírovat zděděný seznam řízení přístupu', @@ -677,7 +682,7 @@ URL: [url]', 'invalid_expiration_date_end' => 'Neplatný konečný datum pro rozmezí datumu vypršení platnosti.', 'invalid_expiration_date_start' => 'Neplatný počáteční datum pro rozmezí datumu vypršení platnosti.', 'invalid_file_id' => 'Neplatné ID souboru', -'invalid_folder_id' => 'Neplatné ID adresáře', +'invalid_folder_id' => 'Neplatné ID složky', 'invalid_group_id' => 'Neplatné ID skupiny', 'invalid_link_id' => 'Neplatné ID odkazu', 'invalid_request_token' => 'Neplatný token Požadavku', @@ -685,12 +690,12 @@ URL: [url]', 'invalid_sequence' => 'Neplatná hodnota posloupnosti', 'invalid_status' => 'Neplatný stav dokumentu', 'invalid_target_doc_id' => 'Neplatné cílové ID dokumentu', -'invalid_target_folder' => 'Neplatné cílové ID adresáře', +'invalid_target_folder' => 'Neplatné cílové ID složky', 'invalid_user_id' => 'Neplatné ID uživatele', 'invalid_version' => 'Neplatná verze dokumentu', 'in_folder' => 'Ve složce', 'in_revision' => 'V revizi', -'in_workflow' => 'Zpracováváno', +'in_workflow' => 'Ve workflow', 'is_disabled' => 'Zakázat účet', 'is_hidden' => 'Utajit v seznamu uživatelů', 'it_IT' => 'Italština', @@ -752,9 +757,11 @@ URL: [url]', 'login_error_title' => 'Chyba při přihlašování', 'login_not_given' => 'Nebylo zadané uživatelské jméno', 'login_ok' => 'Přihlášení proběhlo úspěšně', +'login_restrictions_apply' => '', 'logout' => 'Odhlášení', 'log_management' => 'Správa LOG souborů', 'lo_LA' => 'Laosština', +'malformed_expiration_date' => '', 'manager' => 'Správce', 'manager_of_group' => 'Jste správcem této skupiny', 'mandatory_approvergroups' => 'Stanovená skupina schvalovatelů', @@ -769,6 +776,7 @@ URL: [url]', 'max_upload_size' => 'Max. délka pro nahrání jednoho souboru', 'may' => 'Květen', 'menu_dropfolder' => 'Vhazovací složka', +'menu_upload_from_dropfolder' => '', 'mimetype' => 'Typ "MIME"', 'minutes' => 'minuty', 'misc' => 'Různé', @@ -786,13 +794,13 @@ URL: [url]', 'move' => 'Přesunout', 'move_clipboard' => 'Přesun schránky', 'move_document' => 'Přesunout dokument', -'move_folder' => 'Přesunout adresář', +'move_folder' => 'Přesun složky', 'my_account' => 'Můj účet', 'my_documents' => 'Moje dokumenty', 'my_transmittals' => 'Moje přenosy', 'name' => 'Název', 'needs_correction' => 'Vyžaduje opravu', -'needs_workflow_action' => 'Tento dokument vyžaduje Vaši pozornost. Prosím zkontrolujte záložku pracovního postupu.', +'needs_workflow_action' => 'Tento dokument vyžaduje vaši pozornost. Zkontrolujte prosím kartu workflow.', 'network_drive' => 'Síťové úložiště', 'never' => 'nikdy', 'new' => 'Nový', @@ -817,9 +825,9 @@ Komentář: [comment] Uživatel: [username] URL: [url]', 'new_file_email_subject' => '[sitename]: [document] - Nová příloha', -'new_folder' => 'Nový adresář', +'new_folder' => 'Nová složka', 'new_password' => 'Nové heslo', -'new_subfolder_email' => 'Nový adresář', +'new_subfolder_email' => 'Nová složka', 'new_subfolder_email_body' => 'Nová složka Název: [name] Nadřazená složka: [folder_path] @@ -875,8 +883,8 @@ URL: [url]', 'no_user_image' => 'nebyl nalezen žádný obrázek', 'no_version_check' => 'Chyba při kontrole nové verze SeedDMS. Může to být způsobeno nastavením allow_url_fopen na 0 ve vaší php konfiguraci.', 'no_version_modification' => 'Žádná změna verze', -'no_workflow_available' => 'Neí dostupný žádný pracovní postup', -'objectcheck' => 'Kontrola adresáře/dokumentu', +'no_workflow_available' => 'Není k dispozici žádné workflow', +'objectcheck' => 'Kontrola složky/dokumentu', 'object_check_critical' => 'Kritické chyby', 'object_check_warning' => 'Varování', 'obsolete' => 'Zastaralé', @@ -923,7 +931,7 @@ Pokud budete mít problém s přihlášením i po změně hesla, kontaktujte Adm 'pending_receipt' => 'Probíhá potvrzování přijetí', 'pending_reviews' => 'Probíhá recenze', 'pending_revision' => 'Probíhá revize', -'pending_workflows' => 'Probíhá pracovní postup', +'pending_workflows' => 'Čekající workflows', 'personal_default_keywords' => 'Osobní klíčová slova', 'pl_PL' => 'Polština', 'possible_substitutes' => 'zástupci', @@ -986,39 +994,40 @@ URL: [url]', 'removed_recipient' => 'byl odstraněn ze seznamu příjemců.', 'removed_reviewer' => 'byl odstraněn ze seznamu recenzentů.', 'removed_revisor' => 'byl odstraněn ze seznamu kontrolorů.', -'removed_workflow_email_body' => 'Odstraněn pracovní postup z verze dokumentu: [name] +'removed_workflow_email_body' => 'Odstraněno workflow z verze dokumentu +Dokument: [name] Verze: [version] -Praconí postup: [workflow] +Workflow: [workflow] Nadřazená složka: [folder_path] Uživatel: [username] URL: [url]', -'removed_workflow_email_subject' => '[sitename]: [name] - Odstraněn pracovní postup z verze dokumentu', +'removed_workflow_email_subject' => '[sitename]: [name] - Odstraněno workflow z verze dokumentu', 'removeFolderFromDropFolder' => 'Odstranit složku po nahrání', 'remove_marked_files' => 'Odstranit označené soubory', 'repaired' => 'opraveno', 'repairing_objects' => 'Opravuji dokumenty a složky.', -'request_workflow_action_email_body' => 'Pracovní postup dosáhl stavu, který vyžaduje vaši akci. +'request_workflow_action_email_body' => 'Workflow dosáhlo stavu, který vyžaduje vaši akci. Dokument: [name] Verze: [verze] -Pracovní postup: [workflow] +Workflow: [workflow] Současný stav: [current_state] -Nadřazený adresář: [path_folder] +Nadřazená složka: [path_folder] Uživatel: [username] URL: [url]', -'request_workflow_action_email_subject' => '[sitename]: [name] - Pracovní postup dosáhl stavu, který vyžaduje vaši akci.', +'request_workflow_action_email_subject' => '[sitename]: [name] - Je vyžádána akce workflow', 'reset_checkout' => 'Finalizovat zpracování', 'restrict_access' => 'Není přístup k', 'results_page' => 'Stránka s výsledky', -'return_from_subworkflow' => 'Návrat z podřízeného pracovního postupu', -'return_from_subworkflow_email_body' => 'Návrat z podřízeného pracovního postupu +'return_from_subworkflow' => 'Návrat z podřízeného workflow', +'return_from_subworkflow_email_body' => 'Návrat z podřízeného workflow Dokument: [name] Verze: [version] -Pracovní postup: [workflow] -Podřízený pracovní postup: [subworkflow] +Workflow: [workflow] +Podřízené workflow: [subworkflow] Nadřazená složka: [folder_path] Uživatel: [username] URL: [url]', -'return_from_subworkflow_email_subject' => '[sitename]: [name] - Návrat z podřízeného pracovního postupu', +'return_from_subworkflow_email_subject' => '[sitename]: [name] - Návrat z podřízeného workflow', 'reverse_links' => 'Dokumenty, které mají vazbu na aktuální dokument', 'reviewers' => 'Recenzenti', 'reviewer_already_assigned' => 'je už pověřen jako recenzent', @@ -1082,16 +1091,16 @@ URL: [url]', 'revisors' => 'Revizoři', 'revisor_already_assigned' => 'Uživatel je již přiřazen jako revizor.', 'revisor_already_removed' => 'Revizor byl již z revizního procesu odstraněn nebo již dokument revidoval.', -'rewind_workflow' => 'Nové spuštění pracovního postupu', -'rewind_workflow_email_body' => 'Pracovní postup byl spuštěn znovu +'rewind_workflow' => 'Zpět ve workflow', +'rewind_workflow_email_body' => 'Workflow vráceno zpět Dokument: [name] Verze: [version] -Pracovní postup: [workflow] +Workflow: [workflow] Nadřazená složka: [folder_path] Uživatel: [username] URL: [url]', -'rewind_workflow_email_subject' => '[sitename]: [name] - Nové spuštění pracovního postupu', -'rewind_workflow_warning' => 'Pokud spustíte znovu pracovní postup, pak záznam o dosavadním průběhu bude trvale smazán', +'rewind_workflow_email_subject' => '[sitename]: [name] - Workflow vráceno zpět', +'rewind_workflow_warning' => 'Pokud spustíte znovu workflow, pak záznam o dosavadním průběhu bude trvale smazán', 'rm_attrdef' => 'Odstranit definici atributu', 'rm_attrdefgroup' => 'Odstranit tuto skupinu atributů', 'rm_attr_value' => 'Odstranit hodnotu', @@ -1109,10 +1118,10 @@ URL: [url]', 'rm_user' => 'Odstranit tohoto uživatele', 'rm_user_from_processes' => 'Odstranit uživatele z procesu', 'rm_version' => 'Odstranit verzi', -'rm_workflow' => 'Odstranit pracovní postup', -'rm_workflow_action' => 'Odstranit akci pracovního postupu', -'rm_workflow_state' => 'Odstranit stav pracovního postupu', -'rm_workflow_warning' => 'Chystáte se odstranit pracovní postup z dokumentu. To nelze vrátit zpět.', +'rm_workflow' => 'Odstranit workflow', +'rm_workflow_action' => 'Odstranit akci workflow', +'rm_workflow_state' => 'Odstranit stav workflow', +'rm_workflow_warning' => 'Chystáte se odstranit workflow z dokumentu. To nelze vrátit zpět.', 'role' => 'Role', 'role_admin' => 'Administrátor', 'role_guest' => 'Host', @@ -1122,7 +1131,7 @@ URL: [url]', 'role_type' => 'Typ', 'role_user' => 'Uživatel', 'ro_RO' => 'Rumunština', -'run_subworkflow' => 'Spustit vedlejší pracovní postup', +'run_subworkflow' => 'Spustit dílčí workflow', 'run_subworkflow_email_body' => 'Vedlejší pracovní postup spuštěn Dokument: [name] Verze: [version] @@ -1131,7 +1140,7 @@ Vedlejší pracovní postup: [subworkflow] Nadřazená složka: [folder_path] Uživatel: [username] URL: [url]', -'run_subworkflow_email_subject' => '[sitename]: [name] - Vedlejší pracovní postup spuštěn', +'run_subworkflow_email_subject' => '[sitename]: [name] - Dílčí workflow spuštěno', 'ru_RU' => 'Ruština', 'saturday' => 'Sobota', 'saturday_abbr' => 'So', @@ -1183,7 +1192,7 @@ URL: [url]', 'select_user' => 'Vybrat uživatele', 'select_users' => 'Kliknutím vybrat uživatele', 'select_value' => 'Vybrat hodnotu', -'select_workflow' => 'Vybrat pracovní postup', +'select_workflow' => 'Vybrat workflow', 'send_email' => 'Odeslat e-mail', 'send_login_data' => 'Odeslat přihlašovací údaje', 'send_login_data_body' => 'Přihlašovací údaje @@ -1211,8 +1220,10 @@ Jméno: [username] 'settings_Advanced' => 'Pokročilé', 'settings_advancedAcl' => 'Pokročilá kontrola přístupu', 'settings_advancedAcl_desc' => 'Pokročilá kontrola přístupu umožní zapnout / vypnout některé moduly softwaru. Nemůže být použita pro přístupová práva k dokumentům a složkám.', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', 'settings_allowReviewerOnly' => 'Nastavit pouze recenzenta', -'settings_allowReviewerOnly_desc' => 'Aktivujte, pokud má být nastaven pouze recenzent, ale žádný schvalovatel v tradičním režimu pracovního postupu.', +'settings_allowReviewerOnly_desc' => 'Aktivujte, pokud má být nastaven pouze recenzent, ale žádný schvalovatel v tradičním režimu workflow.', 'settings_apache_mod_rewrite' => 'Apache - Module Rewrite', 'settings_Authentication' => 'Nastavení autentizace', 'settings_autoLoginUser' => 'Automatické přihlášení', @@ -1285,7 +1296,7 @@ Jméno: [username] 'settings_enableAdminReceipt' => 'Povolit přijetí dokumentů pro administrátory', 'settings_enableAdminReceipt_desc' => 'Povolte to, pokud chcete, aby správci byli uvedeni jako příjemci dokumentů.', 'settings_enableAdminRevApp' => 'Povolit kontrolu / schválení administrátorů', -'settings_enableAdminRevApp_desc' => 'Povolte, pokud chcete, aby správci byli uvedeni jako recenzenti / schvalující osoby a pro přechody pracovních postupů.', +'settings_enableAdminRevApp_desc' => 'Povolte, pokud chcete, aby správci byli uvedeni jako recenzenti/schvalující a pro přechody workflow.', 'settings_enableCalendar' => 'Povolit kalendář', 'settings_enableCalendar_desc' => 'Povolení / zakázání kalendáře', 'settings_enableClipboard' => 'Povolit schránku', @@ -1322,28 +1333,28 @@ Jméno: [username] 'settings_enableMultiUpload_desc' => 'Při vytváření nového dokumentu lze nahrát více souborů. Každý vytvoří nový dokument.', 'settings_enableNotificationAppRev' => 'Povolit oznámení posuzovateli / schvalovateli', 'settings_enableNotificationAppRev_desc' => 'Označit pro oznamování posuzovateli / schvalovateli, pokud je přidána nová verze dokumentu.', -'settings_enableNotificationWorkflow' => 'Odeslání upozornění uživatelům v příštím cyklu pracovního postupu', -'settings_enableNotificationWorkflow_desc' => 'Je-li tato volba povolena, uživatelé a skupiny, které je třeba provést v příštím cyklu pracovního postupu, budou upozorněny. Dokonce i když pro dokument nepřidali oznámení.', +'settings_enableNotificationWorkflow' => 'Odeslání upozornění uživatelům v příštím přechodu workflow', +'settings_enableNotificationWorkflow_desc' => 'Je-li tato volba povolena, budou uživatelé a skupiny, jichž je třeba v příštím přechodu workflow, upozorněny. Dokonce i když nemají pro dokument nastaveno oznámení.', 'settings_enableOwnerNotification' => 'Povolit oznámení vlastníka standardně', 'settings_enableOwnerNotification_desc' => 'Označit pro přidání oznámení pro vlastníka v případě, kdy dokument je přidán.', 'settings_enableOwnerReceipt' => 'Povolit příjem dokumentů vlastníkem', 'settings_enableOwnerReceipt_desc' => 'Povolte to, pokud chcete, aby byl majitel dokumentu uveden jako příjemce.', 'settings_enableOwnerRevApp' => 'Povolit posouzení / schválení pro majitele', -'settings_enableOwnerRevApp_desc' => 'Povolte to, pokud chcete, aby byl vlastník dokumentu uveden jako posuzovatel / schvalovatel a pro přechody pracovního postupu.', +'settings_enableOwnerRevApp_desc' => 'Povolte, pokud chcete, aby byl vlastník dokumentu uveden jako posuzovatel/schvalovatel a pro přechody workflow.', 'settings_enablePasswordForgotten' => 'Povolit zaslání zapomenutého hesla', 'settings_enablePasswordForgotten_desc' => 'Chcete-li povolit uživateli nastavit nové heslo a poslat ho e-mailem, zaškrtněte tuto možnost.', 'settings_enableReceiptWorkflow' => 'Povolit potvrzení příjmu dokumentů', -'settings_enableReceiptWorkflow_desc' => 'Povolit zapnutí pracovního postupu pro potvrzení příjmu dokumentu.', +'settings_enableReceiptWorkflow_desc' => 'Povolte, pro spuštění workflow při potvrzení příjmu dokumentu.', 'settings_enableRecursiveCount' => 'Povolit rekurzivní počítání dokumentů / složek', 'settings_enableRecursiveCount_desc' => 'Při zapnutí je počet dokumentů a složek v zobrazení složek určen počítáním všech objektů při rekurzivním zpracování složek a počítáním těch dokumentů a složek, ke kterým má uživatel přístup.', 'settings_enableRevisionOnVoteReject' => 'Odmítnutí jedním revizorem', 'settings_enableRevisionOnVoteReject_desc' => 'Pokud je nastaveno, tak dokument bude odmítnut, pokud jen jeden revizor odmítne dokument.', 'settings_enableRevisionWorkflow' => 'Povolit revizi dokumentů', -'settings_enableRevisionWorkflow_desc' => 'Povolit, aby bylo možné spustit pracovní postup pro revizi dokumentu po uplynutí daného časového období.', +'settings_enableRevisionWorkflow_desc' => 'Povolit, aby bylo možné spustit workflow pro revidování dokumentu po uplynutí dané doby.', 'settings_enableSelfReceipt' => 'Povolit příjem dokumentů pro přihlášeného uživatele', 'settings_enableSelfReceipt_desc' => 'Povolte to, pokud chcete, aby byl aktuálně přihlášený uživatel uveden jako příjemce dokumentu.', 'settings_enableSelfRevApp' => 'Povolit posouzení / schválení pro přihlášeného uživatele', -'settings_enableSelfRevApp_desc' => 'Povolte, pokud chcete aktuálně přihlášeného uvést jako posuzovatele / schvalovatele a pro přechody pracovního postupu', +'settings_enableSelfRevApp_desc' => 'Povolte, pokud chcete, aby byl aktuálně přihlášený uživatel uveden jako posuzovatel/schvalovatel a pro přechody workflow', 'settings_enableSessionList' => 'Povolit seznam uživatelů online v nabídce', 'settings_enableSessionList_desc' => 'Povolit seznam aktuálně přihlášených uživatelů v nabídce.', 'settings_enableThemeSelector' => 'Volba tématu', @@ -1351,7 +1362,7 @@ Jméno: [username] 'settings_enableUpdateReceipt' => 'Povolit úpravu stávajícího příjmu dokumentů', 'settings_enableUpdateReceipt_desc' => 'Povolte to, pokud uživatel, který provedl příjem, může změnit své rozhodnutí.', 'settings_enableUpdateRevApp' => 'Povolit úpravu revize / schválení', -'settings_enableUpdateRevApp_desc' => 'Povolte, pokud uživatel, který provedl revizi / schválení, může změnit rozhodnutí, dokud není aktuální krok pracovního postupu dokončen.', +'settings_enableUpdateRevApp_desc' => 'Povolte, pokud uživatel, který revidoval/schválíl, může změnit rozhodnutí, pokud není aktuální krok workflow dokončen.', 'settings_enableUserImage' => 'Povolit obrázek uživatele', 'settings_enableUserImage_desc' => 'Povolit obrázky uživatelů', 'settings_enableUsersView' => 'Povolit zobrazení uživatelů', @@ -1362,6 +1373,8 @@ Jméno: [username] 'settings_enableVersionModification_desc' => 'Povolit / zakázat úpravu verze dokumentu běžnému uživateli po té, co byla verze nahrána. Administrátor může vždy změnit verzi po nahrání.', 'settings_enableWebdavReplaceDoc' => 'Nahradit dokument při ukládání', 'settings_enableWebdavReplaceDoc_desc' => 'Je-li tato možnost povolena, uložení nové verze dokumentu nahrazuje starý dokument namísto vytvoření nové verze. Platí to pouze tehdy, pokud se uživatel, typ mozku a název souboru rovnají poslední verzi. To může být užitečné, když aplikace automaticky ukládají dokument v pevných intervalech.', +'settings_enableXsendfile' => '', +'settings_enableXsendfile_desc' => '', 'settings_encryptionKey' => 'Šifrovací klíč', 'settings_encryptionKey_desc' => 'Tento řetězec se používá k vytvoření jedinečného identifikátoru, který je přidán jako skryté pole formuláře, aby se zabránilo útokům CSRF.', 'settings_error' => 'Chyba', @@ -1526,7 +1539,7 @@ Jméno: [username] 'settings_tasksInMenu_receipt' => 'Přijetí', 'settings_tasksInMenu_review' => 'Recenze', 'settings_tasksInMenu_revision' => 'Revize', -'settings_tasksInMenu_workflow' => 'Pracovní postup', +'settings_tasksInMenu_workflow' => 'Workflow', 'settings_theme' => 'Výchozí téma', 'settings_theme_desc' => 'Výchozí styl (název podsložky ve složce "styles")', 'settings_titleDisplayHack' => 'Hack zobrazení dlouhých názvů', @@ -1543,8 +1556,8 @@ Jméno: [username] 'settings_viewOnlineFileTypes' => 'View Online File Types', 'settings_viewOnlineFileTypes_desc' => 'Soubory s jedním z následujících koncovek lze prohlížet online (POUŽÍVEJTE POUZE MALÁ PÍSMENA)', 'settings_webdav' => 'WebDAV', -'settings_workflowMode' => 'Režim pracovního postupu', -'settings_workflowMode_desc' => 'Pokročilý pracovní postup umožňuje zadat vaše vlastní pracovní postupy pro uvolňování verzí dokumentů.', +'settings_workflowMode' => 'Režím workflow', +'settings_workflowMode_desc' => 'Pokročilé workflow umožňuje definovat vlastní workflow pro uvolňování verzí dokumentů.', 'settings_workflowMode_valadvanced' => 'pokročilý', 'settings_workflowMode_valtraditional' => 'tradiční', 'settings_workflowMode_valtraditional_only_approval' => 'tradiční (bez recenzí)', @@ -1553,7 +1566,7 @@ Jméno: [username] 'set_owner' => 'Nastavit vlastníka', 'set_owner_error' => 'Chybné nastavení vlastníka', 'set_password' => 'Nastavení hesla', -'set_workflow' => 'Nastavení pracovního postupu', +'set_workflow' => 'Nastavit workflow', 'show_extension_changelog' => 'Zobrazit Changelog', 'show_extension_version_list' => 'Zobrazit seznam verzí', 'signed_in_as' => 'Přihlášen jako', @@ -1585,6 +1598,7 @@ Jméno: [username] 'splash_edit_event' => 'Událost uložena', 'splash_edit_group' => 'Skupina uložena', 'splash_edit_role' => 'Role uložena', +'splash_edit_task' => '', 'splash_edit_user' => 'Uživatel uložen', 'splash_error_add_to_transmittal' => 'Chyba při přidávání dokumentu k přenosu', 'splash_error_rm_download_link' => 'Chyba při odstranění odkazu ke stažení', @@ -1615,6 +1629,9 @@ Jméno: [username] 'splash_rm_transmittal' => 'Přenos odstraněn', 'splash_rm_user' => 'Uživatel odstraněn', 'splash_rm_user_processes' => 'Uživatel odstraněn ze všech procesů', +'splash_rm_workflow' => 'Workflow odstraněno', +'splash_rm_workflow_action' => 'Akce workflow odstraněna', +'splash_rm_workflow_state' => 'Stav workflow odstraněn', 'splash_saved_file' => 'Verze byla uložena', 'splash_save_user_data' => 'Uživatelská data uložena', 'splash_send_download_link' => 'Odkaz ke stažení byl odeslán emailem.', @@ -1627,6 +1644,7 @@ Jméno: [username] 'splash_toogle_group_manager' => 'Manažer skupiny přepnut', 'splash_transfer_document' => 'Dokument přenesen', 'splash_transfer_objects' => 'Objekt přenesen', +'splash_trigger_workflow' => 'Spuštěn přechod workflow', 'state_and_next_state' => 'Stav / Další stav', 'statistic' => 'Statistika', 'status' => 'Stav', @@ -1704,7 +1722,7 @@ Jméno: [username] 'timeline_skip_status_change_0' => 'čeká na přezkum', 'timeline_skip_status_change_1' => 'čeká na schválení', 'timeline_skip_status_change_2' => 'uvolněno', -'timeline_skip_status_change_3' => 'v pracovním postupu', +'timeline_skip_status_change_3' => 've workflow', 'timeline_skip_status_change_4' => 'v revizi', 'timeline_skip_status_change_5' => 'návrh', 'timeline_status_change' => 'Verze [version]: [status]', @@ -1718,8 +1736,8 @@ Jméno: [username] 'transfer_objects' => 'Přenos objektů', 'transfer_objects_to_user' => 'Nový vlastník', 'transfer_to_user' => 'Přenos k uživateli', -'transition_triggered_email' => 'Transformace pracovního postupu spuštěna', -'transition_triggered_email_body' => 'Transformace pracovního postupu spuštěna +'transition_triggered_email' => 'Spuštěn přechod workflow', +'transition_triggered_email_body' => 'Spuštěn přechod workflow Dokument: [jméno] Verze: [verze] Komentář: [comment] @@ -1729,7 +1747,7 @@ Současný stav: [current_state] Nadřazená složky: [folder_path] Uživatel: [username] URL: [url]', -'transition_triggered_email_subject' => '[sitename]: [name] - Transformace pracovního postupu spuštěna', +'transition_triggered_email_subject' => '[sitename]: [name] - Spuštěn přechod workflow', 'transmittal' => 'Přenos', 'transmittalitem_removed' => 'Položka přenosu byla odstraněna', 'transmittalitem_updated' => 'Dokument byl aktualizován na nejnovější verzi', @@ -1737,7 +1755,7 @@ URL: [url]', 'transmittal_name' => 'Název', 'transmittal_size' => 'Velikost', 'tree_loading' => 'Čekejte, nahrává se strom dokumentů...', -'trigger_workflow' => 'Pracovní postup', +'trigger_workflow' => 'Workflow', 'tr_TR' => 'Turečtina', 'tuesday' => 'Úterý', 'tuesday_abbr' => 'Út', @@ -1814,30 +1832,30 @@ URL: [url]', 'wednesday_abbr' => 'St', 'weeks' => 'týdny', 'week_view' => 'Zobrazení týdne', -'workflow' => 'Pracovní postup', -'workflows_involded' => '', -'workflow_actions_management' => 'Správa akcí pracovního postupu', -'workflow_action_in_use' => 'Tato akce je v současnosti používana pracovním postupem.', +'workflow' => 'Workflow', +'workflows_involded' => 'Zahrnutý do workflow', +'workflow_actions_management' => 'Správa akcí workflow', +'workflow_action_in_use' => 'Tato akce je použíta ve workflow.', 'workflow_action_name' => 'Název', -'workflow_editor' => 'Editor pracovního postupu', +'workflow_editor' => 'Editor workflow', 'workflow_group_summary' => 'Přehled skupiny', -'workflow_has_cycle' => 'Pracovní postup má cyklus', +'workflow_has_cycle' => 'Workflow je zacykleno', 'workflow_initstate' => 'Počáteční stav', -'workflow_in_use' => 'Tento pracovní postup je momentálně používán dokumentem.', +'workflow_in_use' => 'Toto workflow je v současné době používáno v dokumentech.', 'workflow_layoutdata_saved' => 'Data rozvržení pracovního postupu uložena', -'workflow_management' => 'Správa pracovního postupu', -'workflow_name' => 'Název pracovního postupu', -'workflow_no_doc_rejected_state' => 'Dokument nebude odmítnut ve stavu pracovního postupu!', -'workflow_no_doc_released_state' => 'Dokument nebude vydán ve stavu pracovního postupu!', -'workflow_no_initial_state' => 'Žádný z přechodů nezačne počátečním stavem pracovního postupu!', -'workflow_no_states' => 'Před přidáním pracovního postupu musíte definovat stavy pracovního postupu.', +'workflow_management' => 'Správa workflow', +'workflow_name' => 'Název', +'workflow_no_doc_rejected_state' => 'Dokument nebude odmítnut ve stavu workflow!', +'workflow_no_doc_released_state' => 'Dokument nebude uvolněn ve stavu workflow!', +'workflow_no_initial_state' => 'Žádná změna stavu nazačína počátečním stavem workflow!', +'workflow_no_states' => 'Před přidámím worflow musíte definovat stavy workflow', 'workflow_save_layout' => 'Uložit rozvržení', -'workflow_state' => 'Stav pracovního postupu', -'workflow_states_management' => 'Správa stavů pracovních postupů', +'workflow_state' => 'stav workflow', +'workflow_states_management' => 'Správa stavů workflow', 'workflow_state_docstatus' => 'Stav dokumentu', -'workflow_state_in_use' => 'Tento stav je momentálně užíván pracovním postupem.', +'workflow_state_in_use' => 'Tento stav je použit ve workflow.', 'workflow_state_name' => 'Název stavu pracovního postupu', -'workflow_summary' => 'Přehled pracovního postupu', +'workflow_summary' => 'Souhrn workflow', 'workflow_transition_without_user_group' => 'Alespoň jedna z transformací pracovního postupu nemá uživatele ani skupinu!', 'workflow_user_summary' => 'Přehled uživatelů', 'x_more_objects' => 'Načíst další dokumenty ([number])', diff --git a/languages/de_DE/lang.inc b/languages/de_DE/lang.inc index c36819077..b5783ca27 100644 --- a/languages/de_DE/lang.inc +++ b/languages/de_DE/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (2633), dgrutsch (22) +// Translators: Admin (2652), dgrutsch (22) $text = array( '2_factor_auth' => '2-Faktor Authentifizierung', @@ -198,6 +198,7 @@ URL: [url]', 'at_least_n_users_of_group' => 'Mindestens [number_of_users] Benutzer der Gruppe [group]', 'august' => 'August', 'authentication' => 'Authentifizierung', +'authentication_failed' => 'Anmeldung fehlgeschlagen', 'author' => 'Autor', 'automatic_status_update' => 'Automatischer Statuswechsel', 'back' => 'Zurück', @@ -499,6 +500,7 @@ Der Link ist bis zum [valid] gültig. 'error_add_aro' => 'Fehler beim Hinzufügen des Zugriffsobjekt', 'error_add_permission' => 'Fehler beim Hinzufügen der Berechtigung', 'error_cleared_cache' => 'Fehler beim Löschen des Cache', +'error_edit_task' => 'Fehler beim Speichern der Task', 'error_extension_getlist' => 'Fehler beim Holen der Liste der Erweiterungen aus dem Repositorium', 'error_importfs' => 'Fehler beim Importieren aus dem Dateisystem', 'error_no_document_selected' => 'Kein Dokument ausgewählt', @@ -507,8 +509,12 @@ Der Link ist bis zum [valid] gültig. 'error_remove_document' => 'Fehler beim Löschen des Dokuments', 'error_remove_folder' => 'Fehler beim Löschen des Ordners', 'error_remove_permission' => 'Fehler beim Entfernen der Berechtigung', +'error_rm_workflow' => 'Fehler beim Löschen des Workflows', +'error_rm_workflow_action' => 'Fehler beim Löschen der Workflow-Aktion', +'error_rm_workflow_state' => 'Fehler beim Löschen des Workflows-Status', 'error_toogle_permission' => 'Fehler beim Ändern der Berechtigung', 'error_transfer_document' => 'Fehler beim Übertragen des Dokuments', +'error_trigger_workflow' => 'Fehler beim Auslösen der Transitions des Workflows', 'error_update_document' => 'Fehler beim Aktualisieren des Dokuments', 'error_uploading_reviewer_only' => 'Fehler beim Anlegen des Dokuments. Das Dokument besitzt einen Prufer, aber keinen Freigeber.', 'es_ES' => 'Spanisch', @@ -658,7 +664,6 @@ URL: [url]', 'index_waiting' => 'Warte', 'individuals' => 'Einzelpersonen', 'individuals_in_groups' => 'Mitglieder einer Gruppe', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => 'Die Bestätigung des Empfangs für diese Dokumentenversion ist nicht möglich, weil die Version nicht freigegeben ist.', 'inherited' => 'geerbt', 'inherits_access_copy_msg' => 'Berechtigungen kopieren', @@ -751,9 +756,11 @@ URL: [url]', 'login_error_title' => 'Fehler bei der Anmeldung', 'login_not_given' => 'Es wurde kein Benutzername eingegeben', 'login_ok' => 'Anmeldung erfolgreich', +'login_restrictions_apply' => 'Anmeldung wegen Beschränkungen fehlgeschlagen', 'logout' => 'Abmelden', 'log_management' => 'Management der Log-Dateien', 'lo_LA' => 'Laotisch', +'malformed_expiration_date' => 'Fehlerhaftes Ablaufdatum', 'manager' => 'Manager', 'manager_of_group' => 'Sie sind der Manager dieser Gruppe', 'mandatory_approvergroups' => 'Zwingende Gruppen von Freigebern', @@ -768,6 +775,7 @@ URL: [url]', 'max_upload_size' => 'Maximale Dateigröße', 'may' => 'Mai', 'menu_dropfolder' => 'Ablageordner', +'menu_upload_from_dropfolder' => 'Diese Datei importieren', 'mimetype' => 'Mime-Type', 'minutes' => 'Minuten', 'misc' => 'Sonstiges', @@ -1222,6 +1230,8 @@ Name: [username] 'settings_Advanced' => 'Erweitert', 'settings_advancedAcl' => 'Erweiterte Zugriffsrechte', 'settings_advancedAcl_desc' => 'Erweiterte Zugriffsrechte erlauben bestimmte Module der Software ein- und auszuschalten. Sie können nicht den Zugriff auf Dokumente und Ordner einschränken.', +'settings_allowChangeRevAppInProcess' => 'Erlaube das Ändern der Prüfer/Freigeber nachdem der Prozess gestartet wurde.', +'settings_allowChangeRevAppInProcess_desc' => 'Voreingestellt können Prüfer und Freigeber nicht mehr verändert werden, wenn eine Freigabe oder Prüfung ausgeführt wurde. Diese Option erlaubt es Administratoren auch nach der ersten Prüfung oder Freigabe die Prüfer und Freigeber zu verändern, bis das Dokument endgültig freigegeben oder abgelehnt ist.', 'settings_allowReviewerOnly' => 'Erlaube nur Prüfer zu setzen', 'settings_allowReviewerOnly_desc' => 'Anwählen, um zu erlauben, dass nur ein Prüfer aber kein Freigeber beim traditionellen Workflow gesetzt werden darf.', 'settings_apache_mod_rewrite' => 'Apache - Module Rewrite', @@ -1373,6 +1383,8 @@ Name: [username] 'settings_enableVersionModification_desc' => 'Setzen Sie diese Option, wenn Versionen eines Dokuments nach dem Hochladen noch durch reguläre Benutzer verändert werden dürfen. Administratoren dürfen dies immer.', 'settings_enableWebdavReplaceDoc' => 'Dokument beim Speichern ersetzen', 'settings_enableWebdavReplaceDoc_desc' => 'Wenn eingeschaltet, wird beim Speichern eine bestehende Dokumentenversion ersetzt und keine neue Version erzeugt. Dies erfolgt nur wenn der Benutzer, Mimetype und Dateiname unverändert zur letzten Version sind. Diese Einstellung kann hilfreich sein, wenn Programme das geöffnete Dokument in regelmäßigen Abständen speichern.', +'settings_enableXsendfile' => 'Apache xsendfile-Modul nutzen', +'settings_enableXsendfile_desc' => 'Wenn diese Option eingeschaltet ist und das Apache-Modul xsendfile installiert, wird dieses für die Auslieferung der Bilder verwendet.', 'settings_encryptionKey' => 'Verschlüsselungs-Sequenz', 'settings_encryptionKey_desc' => 'Diese Zeichenkette wird verwendet um eine eindeutige Kennung zu erzeugen, die als verstecktes Feld in einem Formular untergebracht wird. Sie dient zur Verhinderung von CSRF-Attacken.', 'settings_error' => 'Fehler', @@ -1534,8 +1546,8 @@ Name: [username] 'settings_tasksInMenu_approval' => 'Freigaben', 'settings_tasksInMenu_desc' => 'Setzt die Aufgaben, die gezählt werden sollen. Wenn keine Aufgaben ausgewählt werden, werden alle gezählt.', 'settings_tasksInMenu_needscorrection' => 'Korrektur erforderlich', -'settings_tasksInMenu_receipt' => 'Prüfungen', -'settings_tasksInMenu_review' => 'Empfangsbestätigungen', +'settings_tasksInMenu_receipt' => 'Empfangsbestätigungen', +'settings_tasksInMenu_review' => 'Prüfungen', 'settings_tasksInMenu_revision' => 'Wiederholungsprüfungen', 'settings_tasksInMenu_workflow' => 'Workflow', 'settings_theme' => 'Aussehen', @@ -1596,6 +1608,7 @@ Name: [username] 'splash_edit_event' => 'Ereignis gespeichert', 'splash_edit_group' => 'Gruppe gespeichert', 'splash_edit_role' => 'Rolle gespeichert', +'splash_edit_task' => 'Task gespeichert', 'splash_edit_user' => 'Benutzer gespeichert', 'splash_error_add_to_transmittal' => 'Fehler beim Hinzufügen zur Dokumentenliste', 'splash_error_rm_download_link' => 'Fehler beim Löschen des Download-Links', @@ -1626,6 +1639,9 @@ Name: [username] 'splash_rm_transmittal' => 'Dokumentenliste gelöscht', 'splash_rm_user' => 'Benutzer gelöscht', 'splash_rm_user_processes' => 'Benutzer aus allen Prozessen gelöscht', +'splash_rm_workflow' => 'Workflow gelöscht', +'splash_rm_workflow_action' => 'Workflow-Aktion gelöscht', +'splash_rm_workflow_state' => 'Workflow-Status gelöscht', 'splash_saved_file' => 'Version gespeichert', 'splash_save_user_data' => 'Benutzerdaten gespeichert', 'splash_send_download_link' => 'Download-Link per E-Mail verschickt.', @@ -1638,6 +1654,7 @@ Name: [username] 'splash_toogle_group_manager' => 'Gruppenverwalter gewechselt', 'splash_transfer_document' => 'Dokument übertragen', 'splash_transfer_objects' => 'Objekte übertragen', +'splash_trigger_workflow' => '', 'state_and_next_state' => 'Status/Nächster Status', 'statistic' => 'Statistik', 'status' => 'Status', diff --git a/languages/el_GR/lang.inc b/languages/el_GR/lang.inc index c1b4c46a8..593082dcf 100644 --- a/languages/el_GR/lang.inc +++ b/languages/el_GR/lang.inc @@ -169,6 +169,7 @@ $text = array( 'at_least_n_users_of_group' => '', 'august' => 'Αύγουστος', 'authentication' => '', +'authentication_failed' => '', 'author' => '', 'automatic_status_update' => '', 'back' => 'Πίσω', @@ -422,6 +423,7 @@ $text = array( 'error_add_aro' => '', 'error_add_permission' => '', 'error_cleared_cache' => '', +'error_edit_task' => '', 'error_extension_getlist' => '', 'error_importfs' => '', 'error_no_document_selected' => 'Δεν έχει επιλεγεί έγγραφο', @@ -430,8 +432,12 @@ $text = array( 'error_remove_document' => '', 'error_remove_folder' => '', 'error_remove_permission' => '', +'error_rm_workflow' => '', +'error_rm_workflow_action' => '', +'error_rm_workflow_state' => '', 'error_toogle_permission' => '', 'error_transfer_document' => '', +'error_trigger_workflow' => '', 'error_update_document' => '', 'error_uploading_reviewer_only' => '', 'es_ES' => 'Spanish/Ισπανικά', @@ -550,7 +556,6 @@ $text = array( 'index_waiting' => '', 'individuals' => 'Άτομα', 'individuals_in_groups' => '', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => '', 'inherited' => '', 'inherits_access_copy_msg' => '', @@ -643,9 +648,11 @@ $text = array( 'login_error_title' => 'Λάθος σύνδεσης', 'login_not_given' => '', 'login_ok' => 'Επιτυχημένη σύνδεση', +'login_restrictions_apply' => '', 'logout' => 'Εποσύνδεση', 'log_management' => 'Διαχείριση αρχείων καταγραφής', 'lo_LA' => 'Τοποθεσία', +'malformed_expiration_date' => '', 'manager' => 'Διαχειριστής', 'manager_of_group' => 'Είστε διαχειριστής της ομάδας', 'mandatory_approvergroups' => '', @@ -660,6 +667,7 @@ $text = array( 'max_upload_size' => '', 'may' => 'Μάϊος', 'menu_dropfolder' => '', +'menu_upload_from_dropfolder' => '', 'mimetype' => '', 'minutes' => 'λεπτά', 'misc' => 'Διάφορα', @@ -1007,6 +1015,8 @@ URL: [url]', 'settings_Advanced' => '', 'settings_advancedAcl' => '', 'settings_advancedAcl_desc' => '', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', 'settings_allowReviewerOnly' => '', 'settings_allowReviewerOnly_desc' => '', 'settings_apache_mod_rewrite' => '', @@ -1158,6 +1168,8 @@ URL: [url]', 'settings_enableVersionModification_desc' => '', 'settings_enableWebdavReplaceDoc' => '', 'settings_enableWebdavReplaceDoc_desc' => '', +'settings_enableXsendfile' => '', +'settings_enableXsendfile_desc' => '', 'settings_encryptionKey' => '', 'settings_encryptionKey_desc' => '', 'settings_error' => '', @@ -1381,6 +1393,7 @@ URL: [url]', 'splash_edit_event' => '', 'splash_edit_group' => '', 'splash_edit_role' => '', +'splash_edit_task' => '', 'splash_edit_user' => '', 'splash_error_add_to_transmittal' => '', 'splash_error_rm_download_link' => '', @@ -1411,6 +1424,9 @@ URL: [url]', 'splash_rm_transmittal' => '', 'splash_rm_user' => '', 'splash_rm_user_processes' => '', +'splash_rm_workflow' => '', +'splash_rm_workflow_action' => '', +'splash_rm_workflow_state' => '', 'splash_saved_file' => '', 'splash_save_user_data' => '', 'splash_send_download_link' => '', @@ -1423,6 +1439,7 @@ URL: [url]', 'splash_toogle_group_manager' => '', 'splash_transfer_document' => '', 'splash_transfer_objects' => '', +'splash_trigger_workflow' => '', 'state_and_next_state' => '', 'statistic' => '', 'status' => 'κατάσταση', diff --git a/languages/en_GB/lang.inc b/languages/en_GB/lang.inc index 3836da005..b86b1a918 100644 --- a/languages/en_GB/lang.inc +++ b/languages/en_GB/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (1748), archonwang (3), dgrutsch (9), netixw (14) +// Translators: Admin (1769), archonwang (3), dgrutsch (9), netixw (14) $text = array( '2_factor_auth' => '2-factor authentication', @@ -198,6 +198,7 @@ URL: [url]', 'at_least_n_users_of_group' => 'At least [number_of_users] users of [group]', 'august' => 'August', 'authentication' => 'Authentication', +'authentication_failed' => 'Authentication failed', 'author' => 'Author', 'automatic_status_update' => 'Automatic status change', 'back' => 'Go back', @@ -500,6 +501,7 @@ The link is valid until [valid]. 'error_add_aro' => 'Error while adding access request object', 'error_add_permission' => 'Error while add permission', 'error_cleared_cache' => 'Error while clearing cache', +'error_edit_task' => 'Error when saving task', 'error_extension_getlist' => 'Error getting extension list from repository', 'error_importfs' => 'Error while importing form file system', 'error_no_document_selected' => 'No document selected', @@ -508,8 +510,12 @@ The link is valid until [valid]. 'error_remove_document' => 'Error while deleting document', 'error_remove_folder' => 'Error while deleting folder', 'error_remove_permission' => 'Error while remove permission', +'error_rm_workflow' => 'Error when removing workflow', +'error_rm_workflow_action' => 'Error when removing workflow action', +'error_rm_workflow_state' => 'Error when removing workflow state', 'error_toogle_permission' => 'Error while changing permission', 'error_transfer_document' => 'Error while transfering document', +'error_trigger_workflow' => 'Error while triggering transition of workflow', 'error_update_document' => 'Error while updating document', 'error_uploading_reviewer_only' => 'Error when creating the document. The document has a reviewer, but no approver.', 'es_ES' => 'Spanish', @@ -659,7 +665,6 @@ URL: [url]', 'index_waiting' => 'Waiting', 'individuals' => 'Individuals', 'individuals_in_groups' => 'Members of a group', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => 'Acknowledgement of reception for this document version is not possible, because the version is not released.', 'inherited' => 'inherited', 'inherits_access_copy_msg' => 'Copy inherited access list', @@ -752,9 +757,11 @@ URL: [url]', 'login_error_title' => 'Sign in error', 'login_not_given' => 'No username has been supplied', 'login_ok' => 'Sign in successful', +'login_restrictions_apply' => 'Login failed due to restrictions', 'logout' => 'Logout', 'log_management' => 'Log files management', 'lo_LA' => 'Laotian', +'malformed_expiration_date' => 'Malformed expiration date', 'manager' => 'Manager', 'manager_of_group' => 'You are the manager of this group', 'mandatory_approvergroups' => 'Mandatory Groups of approvers', @@ -769,6 +776,7 @@ URL: [url]', 'max_upload_size' => 'Maximum upload size', 'may' => 'May', 'menu_dropfolder' => 'Drop folder', +'menu_upload_from_dropfolder' => 'Import this file', 'mimetype' => 'Mime type', 'minutes' => 'minutes', 'misc' => 'Misc', @@ -1208,7 +1216,7 @@ Name: [username] 'seq_start' => 'First position', 'sessions' => 'Users online', 'setDateFromFile' => 'Take over date from imported file', -'setDateFromFolder' => '', +'setDateFromFolder' => 'Take over date from imported folder', 'settings' => 'Settings', 'settings_activate_module' => 'Activate module', 'settings_activate_php_extension' => 'Activate PHP extension', @@ -1217,6 +1225,8 @@ Name: [username] 'settings_Advanced' => 'Advanced', 'settings_advancedAcl' => 'Advanced Access control', 'settings_advancedAcl_desc' => 'Advanced access controll will allow to turn on/off certain modules of the software. It can not be used for access rights on documents and folders.', +'settings_allowChangeRevAppInProcess' => 'Allow changing reviewer/approver after process started', +'settings_allowChangeRevAppInProcess_desc' => 'By default the reviewers and approvers cannot be changed anymore once a review or approval has been submitted. This option will allow administrators to do this as long as the document is not released or rejected.', 'settings_allowReviewerOnly' => 'Allow to set reviewer only', 'settings_allowReviewerOnly_desc' => 'Enable this, if it shall be allow to set just a reviewer but no approver in traditional workflow mode.', 'settings_apache_mod_rewrite' => 'Apache - Module Rewrite', @@ -1368,6 +1378,8 @@ Name: [username] 'settings_enableVersionModification_desc' => 'Enable/disable modification of a document versions by regular users after a version was uploaded. Admin may always modify the version after upload.', 'settings_enableWebdavReplaceDoc' => 'Replace document when saving', 'settings_enableWebdavReplaceDoc_desc' => 'If enabled, saving a new version of a document will replace the old document instead of creating a new version. This will only apply if the user, mimetype and filename are equal to the last version. This can be usefull when applications are auto saving a document in fixed intervals.', +'settings_enableXsendfile' => 'Use apache xsendfile module', +'settings_enableXsendfile_desc' => 'If this option is set and the apache module xsendfile is installed, it will be used for delivering images.', 'settings_encryptionKey' => 'Encryption key', 'settings_encryptionKey_desc' => 'This string is used for creating a unique identifier being added as a hidden field to a form in order to prevent CSRF attacks.', 'settings_error' => 'Error', @@ -1529,8 +1541,8 @@ Name: [username] 'settings_tasksInMenu_approval' => 'Approvals', 'settings_tasksInMenu_desc' => 'Select those tasks which are to be counted. If none is selected, then all tasks will be counted.', 'settings_tasksInMenu_needscorrection' => 'Correction needed', -'settings_tasksInMenu_receipt' => 'Reviews', -'settings_tasksInMenu_review' => 'Receipts', +'settings_tasksInMenu_receipt' => 'Receipts', +'settings_tasksInMenu_review' => 'Reviews', 'settings_tasksInMenu_revision' => 'Revisions', 'settings_tasksInMenu_workflow' => 'Workflow', 'settings_theme' => 'Default theme', @@ -1591,6 +1603,7 @@ Name: [username] 'splash_edit_event' => 'Event saved', 'splash_edit_group' => 'Group saved', 'splash_edit_role' => 'Role saved', +'splash_edit_task' => 'Task saved', 'splash_edit_user' => 'User saved', 'splash_error_add_to_transmittal' => 'Error while adding document to transmittal', 'splash_error_rm_download_link' => 'Error when removing download link', @@ -1621,6 +1634,9 @@ Name: [username] 'splash_rm_transmittal' => 'Transmittal deleted', 'splash_rm_user' => 'User removed', 'splash_rm_user_processes' => 'User removed from all processes', +'splash_rm_workflow' => 'Workflow removed', +'splash_rm_workflow_action' => 'Workflow action removed', +'splash_rm_workflow_state' => 'Workflow state removed', 'splash_saved_file' => 'Version saved', 'splash_save_user_data' => 'User data saved', 'splash_send_download_link' => 'Download link sent by email.', @@ -1633,6 +1649,7 @@ Name: [username] 'splash_toogle_group_manager' => 'Group manager toogled', 'splash_transfer_document' => 'Document transfered', 'splash_transfer_objects' => 'Objects transfered', +'splash_trigger_workflow' => 'Triggered transition of workflow', 'state_and_next_state' => 'State/Next state', 'statistic' => 'Statistic', 'status' => 'Status', diff --git a/languages/es_ES/lang.inc b/languages/es_ES/lang.inc index 0e8cc9095..fbad627fb 100644 --- a/languages/es_ES/lang.inc +++ b/languages/es_ES/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: acabello (20), Admin (1094), angel (123), francisco (2), jaimem (14) +// Translators: acabello (20), Admin (1111), angel (123), francisco (2), jaimem (14) $text = array( '2_factor_auth' => '', @@ -193,6 +193,7 @@ URL: [url]', 'at_least_n_users_of_group' => 'Al menos [number_of_users] usuarios de [group]', 'august' => 'Agosto', 'authentication' => 'Autenticación', +'authentication_failed' => '', 'author' => 'Autor', 'automatic_status_update' => 'Cambio automático de estado', 'back' => 'Atrás', @@ -268,7 +269,7 @@ URL: [url]', 'comment' => 'Comentarios', 'comment_changed_email' => '', 'comment_for_current_version' => 'Comentario de la versión actual', -'configure_extension' => '', +'configure_extension' => 'Configurar extensión', 'confirm_clear_cache' => '', 'confirm_create_fulltext_index' => '¡Sí, quiero regenerar el índice te texto completo¡', 'confirm_move_document' => '', @@ -415,7 +416,7 @@ URL: [url]', 'does_not_expire' => 'No caduca', 'does_not_inherit_access_msg' => 'heredar el acceso', 'download' => 'Descargar', -'download_extension' => '', +'download_extension' => 'Descargar como archivo zip', 'download_links' => '', 'download_link_email_body' => '', 'download_link_email_subject' => '', @@ -476,6 +477,7 @@ URL: [url]', 'error_add_aro' => '', 'error_add_permission' => '', 'error_cleared_cache' => '', +'error_edit_task' => '', 'error_extension_getlist' => '', 'error_importfs' => '', 'error_no_document_selected' => 'Ningún documento seleccionado', @@ -484,8 +486,12 @@ URL: [url]', 'error_remove_document' => '', 'error_remove_folder' => 'Error al eliminar la carpeta', 'error_remove_permission' => '', +'error_rm_workflow' => '', +'error_rm_workflow_action' => '', +'error_rm_workflow_state' => '', 'error_toogle_permission' => '', 'error_transfer_document' => '', +'error_trigger_workflow' => '', 'error_update_document' => '', 'error_uploading_reviewer_only' => '', 'es_ES' => 'Castellano', @@ -628,7 +634,6 @@ URL: [url]', 'index_waiting' => 'Esperando', 'individuals' => 'Individuales', 'individuals_in_groups' => '', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => '', 'inherited' => 'heredado', 'inherits_access_copy_msg' => 'Copiar lista de acceso heredado', @@ -700,7 +705,7 @@ URL: [url]', 'librarydoc' => '', 'linked_documents' => 'Documentos relacionados', 'linked_files' => 'Adjuntos', -'linked_to_current_version' => '', +'linked_to_current_version' => 'Vinculado a la versión actual', 'linked_to_document' => 'Enlazado al documento', 'linked_to_this_version' => '', 'link_alt_updatedocument' => 'Si desea subir archivos mayores que el tamaño máximo actualmente permitido, por favor, utilice la página de subida alternativa.', @@ -721,9 +726,11 @@ URL: [url]', 'login_error_title' => 'Error de acceso', 'login_not_given' => 'Nombre de usuario no facilitado.', 'login_ok' => 'Acceso con éxito', +'login_restrictions_apply' => '', 'logout' => 'Desconectar', 'log_management' => 'Gestión de ficheros de registro', 'lo_LA' => 'Laotian', +'malformed_expiration_date' => '', 'manager' => 'Administrador', 'manager_of_group' => 'Usted es el administrador de este grupo', 'mandatory_approvergroups' => 'Grupo obligatorio de aprobadores', @@ -738,6 +745,7 @@ URL: [url]', 'max_upload_size' => 'Tamaño máximo de subida para cada fichero', 'may' => 'Mayo', 'menu_dropfolder' => '', +'menu_upload_from_dropfolder' => '', 'mimetype' => 'Tipo Mime', 'minutes' => 'minutos', 'misc' => 'Misc', @@ -1148,12 +1156,14 @@ URL: [url]', 'settings_Advanced' => 'Avanzado', 'settings_advancedAcl' => '', 'settings_advancedAcl_desc' => '', -'settings_allowReviewerOnly' => '', -'settings_allowReviewerOnly_desc' => '', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', +'settings_allowReviewerOnly' => 'Permitir habilitar la función de Revisor para un usuario', +'settings_allowReviewerOnly_desc' => 'Habilite esto si se requiere permitir que un usuario sea lector o revisor sin capacidad de aprobar un documento en un proceso de workflow tradicional', 'settings_apache_mod_rewrite' => 'Apache - Módulo Reescritura', 'settings_Authentication' => 'Configuración de autenticación', 'settings_autoLoginUser' => 'Acceso automatico', -'settings_autoLoginUser_desc' => '', +'settings_autoLoginUser_desc' => 'Utilice esta clave de usuario para accesos si el usuario no ha ingresado al sistema todavía. Este tipo de acceso no creará una sesión.', 'settings_available_languages' => 'Idiomas disponibles', 'settings_available_languages_desc' => 'Unicamente los lenguages seleccionados seran cargados y mostrados en el selector de lenguages. El lenguage por defecto siempre sera cargado', 'settings_backupDir' => 'Directorio de copia de seguridad', @@ -1167,7 +1177,7 @@ URL: [url]', 'settings_checkOutDir' => '', 'settings_checkOutDir_desc' => '', 'settings_cmdTimeout' => 'Tiempo limite para comandos externos', -'settings_cmdTimeout_desc' => '', +'settings_cmdTimeout_desc' => 'Esta duración definirá cuando debe interrumpirse la ejecución de un comando externo (i.e. para crear el índice de texto completo).', 'settings_contentDir' => 'Carpeta de contenidos', 'settings_contentDir_desc' => 'Donde se almacenan los archivos subidos (es preferible seleccionar una carpeta que no sea accesible a través del servidor web)', 'settings_contentOffsetDir' => 'Carpeta de contenidos de desplazamiento', @@ -1256,7 +1266,7 @@ URL: [url]', 'settings_enableMenuTasks' => 'Activar en el menú la lista de tareas', 'settings_enableMenuTasks_desc' => 'Habilita/Deshabillita la parte del menú que contiene todas las tareas para el usuario. Contiene documentos que necesitan ser revisados, aprobados, etc.', 'settings_enableMultiUpload' => 'Permitir subir múltiples archivos', -'settings_enableMultiUpload_desc' => '', +'settings_enableMultiUpload_desc' => 'Cuando se crea un documento, es posible subir varios archivos a la vez. Cada uno creará un nuevo documento.', 'settings_enableNotificationAppRev' => 'Habilitar notificación a revisor/aprobador', 'settings_enableNotificationAppRev_desc' => 'Habilitar para enviar notificación a revisor/aprobador cuando se añade una nueva versión de documento', 'settings_enableNotificationWorkflow' => 'Enviar notificación a los usuarios en la siguiente transacción del flujo.', @@ -1299,6 +1309,8 @@ URL: [url]', 'settings_enableVersionModification_desc' => 'Habilitar/Deshabilitar la modificación de versiones de documentos por parte de usuarios después de añadir una nueva versión. El administrador siempre podrá modificar la versión después de añadida.', 'settings_enableWebdavReplaceDoc' => 'Reemplaza documento al guardar', 'settings_enableWebdavReplaceDoc_desc' => 'Si se habilita, al guardar una nueva versión de un documento reemplaza al viejo documento en lugar de crear un nueva versión. Esto solo aplica si el usuario mimetype Yelp nombre del archivo son iguales a la última versión. Esto es útil cuando la aplicación guarda automáticamente un documento a intervalos fijos.', +'settings_enableXsendfile' => '', +'settings_enableXsendfile_desc' => '', 'settings_encryptionKey' => 'Clave de cifrado', 'settings_encryptionKey_desc' => 'Esta cadena se utiliza para crear un identificador único añadido como campo oculto a formularios para prevenir ataques CSRF.', 'settings_error' => 'Error', @@ -1361,14 +1373,14 @@ URL: [url]', 'settings_maxSizeForFullText' => 'Tamaño máximo del fichero para el indexado inmediato', 'settings_maxSizeForFullText_desc' => 'Todo documento nuevo menor que el tamaño configurado será indexado completamente después de su subida. En los demás casos se indexarán solo los metadatos.', 'settings_maxUploadSize' => 'Tamaño máximo de subida archivos', -'settings_maxUploadSize_desc' => '', +'settings_maxUploadSize_desc' => 'Tamaño máximo de archivos a cargar. Se tomará en cuenta para versiones de documentos y anexos de correo electrónico', 'settings_more_settings' => 'Configure más parámetros. Acceso por defecto: admin/admin', 'settings_notfound' => 'No encontrado', 'settings_Notification' => 'Parámetros de notificación', 'settings_notwritable' => 'La configuración no se puede guardar porque el fichero de configuración no es escribible.', 'settings_no_content_dir' => 'Carpeta de contenidos', 'settings_overrideMimeType' => 'Anular MimeType', -'settings_overrideMimeType_desc' => '', +'settings_overrideMimeType_desc' => 'Permitir que SeedDMS fije el tipo MIME sobreescribiendo el que haya definido el navegador durante el proceso de carga de un archivo.', 'settings_partitionSize' => 'Tamaño de fichero parcial', 'settings_partitionSize_desc' => 'Tamaño de ficheros parciales en bytes, subidos por jumploader. No configurar un valor mayor que el tamaño máximo de subida configurado en el servidor.', 'settings_passwordExpiration' => 'Caducidad de contraseña', @@ -1403,8 +1415,8 @@ URL: [url]', 'settings_quota' => 'Cuota de usuario', 'settings_quota_desc' => 'El número máximo de bytes que el usuario puede ocupar en disco. Asignar 0 para no limitar el espacio de disco. Este valor puede ser sobreescrito por cada uso en su perfil.', 'settings_removeFromDropFolder' => 'Elimina el archivo de la carpeta de subida despues de una subida exitosa', -'settings_removeFromDropFolder_desc' => '', -'settings_repositoryUrl' => '', +'settings_removeFromDropFolder_desc' => 'Habilite esto para que se elimine un archivo después de cargarse exitosamente.', +'settings_repositoryUrl' => 'URL del repositorio', 'settings_repositoryUrl_desc' => 'URL del repositorio de extensiones', 'settings_restricted' => 'Acceso restringido', 'settings_restricted_desc' => 'Solo permitir conectar a usuarios si tienen alguna entrada en la base de datos local (independientemente de la autenticación correcta con LDAP)', @@ -1432,8 +1444,8 @@ URL: [url]', 'settings_smtpPort_desc' => 'Puerto del servidor SMTP, por defecto 25', 'settings_smtpSendFrom' => 'Enviar desde', 'settings_smtpSendFrom_desc' => 'Enviar desde', -'settings_smtpSendTestMail' => '', -'settings_smtpSendTestMail_desc' => '', +'settings_smtpSendTestMail' => 'Enviar correo electrónico de prueba', +'settings_smtpSendTestMail_desc' => 'Envía un correo electrónico de prueba para validar la configuración actual de correo electrónico.', 'settings_smtpServer' => 'Nombre de servidor SMTP', 'settings_smtpServer_desc' => 'Nombre de servidor SMTP', 'settings_smtpUser' => 'Usuario del servidor SMTP', @@ -1479,7 +1491,7 @@ URL: [url]', 'settings_versiontolow' => 'Versión antigua', 'settings_viewOnlineFileTypes' => 'Ver en lineas las extensiones de fichero', 'settings_viewOnlineFileTypes_desc' => 'Archivos con una de las siguientes extensiones se pueden visualizar en linea (UTILICE SOLAMENTE CARACTERES EN MINÚSCULA)', -'settings_webdav' => '', +'settings_webdav' => 'WebDAV', 'settings_workflowMode' => 'Workflow mode', 'settings_workflowMode_desc' => 'El flujo de trabajo avanzado permite especificar su propia versión de flujo para las versiones de documento.', 'settings_workflowMode_valadvanced' => 'avanzado', @@ -1491,7 +1503,7 @@ URL: [url]', 'set_owner_error' => 'Error estableciendo propietario', 'set_password' => 'Establecer contraseña', 'set_workflow' => 'Establecer Flujo de Trabajo', -'show_extension_changelog' => '', +'show_extension_changelog' => 'Mostrar log de cambios', 'show_extension_version_list' => 'Lista corta de versiones', 'signed_in_as' => 'Conectado como', 'sign_in' => 'Conectar', @@ -1522,6 +1534,7 @@ URL: [url]', 'splash_edit_event' => '', 'splash_edit_group' => 'Grupo guardado', 'splash_edit_role' => '', +'splash_edit_task' => '', 'splash_edit_user' => 'Usuario guardado', 'splash_error_add_to_transmittal' => '', 'splash_error_rm_download_link' => '', @@ -1552,6 +1565,9 @@ URL: [url]', 'splash_rm_transmittal' => '', 'splash_rm_user' => 'Usuario eliminado', 'splash_rm_user_processes' => '', +'splash_rm_workflow' => '', +'splash_rm_workflow_action' => '', +'splash_rm_workflow_state' => '', 'splash_saved_file' => '', 'splash_save_user_data' => '', 'splash_send_download_link' => '', @@ -1564,6 +1580,7 @@ URL: [url]', 'splash_toogle_group_manager' => 'Administrador de grupo activado', 'splash_transfer_document' => '', 'splash_transfer_objects' => '', +'splash_trigger_workflow' => '', 'state_and_next_state' => 'Estado/Estado siguiente', 'statistic' => 'Estadística', 'status' => 'Estado', diff --git a/languages/fr_FR/lang.inc b/languages/fr_FR/lang.inc index faaf9d037..d6cfc2799 100644 --- a/languages/fr_FR/lang.inc +++ b/languages/fr_FR/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (1087), jeromerobert (50), lonnnew (9), Oudiceval (697) +// Translators: Admin (1091), jeromerobert (50), lonnnew (9), Oudiceval (725) $text = array( '2_factor_auth' => 'Authentification forte', @@ -70,7 +70,7 @@ URL: [url]', 'add_revision' => 'Confirmer l’approbation', 'add_role' => 'Ajouter un rôle', 'add_subfolder' => 'Ajouter un sous-dossier', -'add_task' => '', +'add_task' => 'Ajouter une nouvelle tâche pour cette classe', 'add_to_clipboard' => 'Ajouter au presse-papier', 'add_to_transmittal' => 'Ajouter à la transmission', 'add_transmittal' => 'Ajouter une transmission', @@ -133,7 +133,7 @@ URL : [url]', 'approver_already_assigned' => 'L’utilisateur est déjà affecté comme approbateur.', 'approver_already_removed' => 'L’approbateur a déjà été retiré du processus d’approbation ou a déjà soumis l’approbation.', 'april' => 'Avril', -'archive' => '', +'archive' => 'Archive', 'archive_creation' => 'Créer une archive', 'archive_creation_warning' => 'Avec cette fonction, vous pouvez créer une archive contenant les fichiers de tous les dossiers DMS. Après la création, l\'archive sera sauvegardée dans le dossier de données de votre serveur.
AVERTISSEMENT: Une archive créée ainsi sera inutilisable en tant que sauvegarde du serveur.', 'ar_EG' => 'Arabe – Égypte', @@ -198,6 +198,7 @@ URL: [url]', 'at_least_n_users_of_group' => 'Au moins [number_of_users] utilisateurs de [group]', 'august' => 'Août', 'authentication' => 'Authentification', +'authentication_failed' => 'Échec de l’authentification', 'author' => 'Auteur', 'automatic_status_update' => 'Changement de statut automatique', 'back' => 'Retour', @@ -263,7 +264,7 @@ URL: [url]', 'choose_workflow' => 'Choisir un workflow', 'choose_workflow_action' => 'Choisir une action de workflow', 'choose_workflow_state' => 'Choisir un état de workflow', -'class_name' => '', +'class_name' => 'Nom de classe', 'clear_cache' => 'Effacer le cache', 'clear_clipboard' => 'Vider le presse-papier', 'clear_password' => 'Sans mot de passe', @@ -314,7 +315,7 @@ URL: [url]', 'databasesearch' => 'Recherche dans la base de données', 'date' => 'Date', 'days' => 'jours', -'debug' => '', +'debug' => 'Débogage', 'december' => 'Décembre', 'default_access' => 'Droits d\'accès par défaut', 'default_keywords' => 'Mots-clés disponibles', @@ -337,7 +338,7 @@ URL: [url]', 'documents_locked_by_you' => 'Documents verrouillés', 'documents_only' => 'Documents uniquement', 'documents_to_approve' => 'Documents en attente d\'approbation', -'documents_to_correct' => '', +'documents_to_correct' => 'Documents à corriger', 'documents_to_process' => 'Documents à traiter', 'documents_to_receipt' => 'Documents en attente de confirmation de réception', 'documents_to_review' => 'Documents en attente de vérification', @@ -442,7 +443,7 @@ URL: [url]', Le lien est valide jusqu’au [valid]. [comment]', -'download_link_email_subject' => '', +'download_link_email_subject' => 'Lien de téléchargement', 'do_object_repair' => 'Réparer tous les dossiers et documents.', 'do_object_setchecksum' => 'Définir checksum', 'do_object_setfilesize' => 'Définir la taille du fichier', @@ -500,6 +501,7 @@ Le lien est valide jusqu’au [valid]. 'error_add_aro' => '', 'error_add_permission' => 'Erreur lors de l’ajout de permission', 'error_cleared_cache' => 'Erreur lors du vidage du cache', +'error_edit_task' => '', 'error_extension_getlist' => 'Erreur lors de l’obtention de la liste des extensions depuis le dépôt', 'error_importfs' => 'Erreur lors de l’import depuis le système de fichiers', 'error_no_document_selected' => 'Aucun document sélectionné', @@ -508,9 +510,13 @@ Le lien est valide jusqu’au [valid]. 'error_remove_document' => 'Erreur lors de la suppression du document', 'error_remove_folder' => 'Erreur lors de la suppression du dossier', 'error_remove_permission' => 'Erreur lors de la suppression de permission', +'error_rm_workflow' => 'Erreur lors de la suppression du workflow', +'error_rm_workflow_action' => 'Erreur lors de la suppression de l’action de workflow', +'error_rm_workflow_state' => 'Erreur lors de la suppression de l’état de workflow', 'error_toogle_permission' => 'Erreur lors de la modification de permission', 'error_transfer_document' => 'Erreur lors du transfert du document', -'error_update_document' => '', +'error_trigger_workflow' => 'Erreur lors du déclenchement de la transition du workflow', +'error_update_document' => 'Erreur lors de la mise à jour du document', 'error_uploading_reviewer_only' => 'Erreur lors de la création du document. Le document a un examinateur, mais pas d’approbateur.', 'es_ES' => 'Espagnol', 'event_details' => 'Détails de l\'événement', @@ -659,7 +665,6 @@ URL: [url]', 'index_waiting' => 'Chargement…', 'individuals' => 'Individuels', 'individuals_in_groups' => 'Membres d’un groupe', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => 'L’accusé de réception pour cette version du document n’est pas possible car la version n’est pas en état « publié ».', 'inherited' => 'hérité', 'inherits_access_copy_msg' => 'Recopier la liste des accès hérités', @@ -752,9 +757,11 @@ URL: [url]', 'login_error_title' => 'Erreur de connexion', 'login_not_given' => 'Nom utilisateur non fourni', 'login_ok' => 'Connexion établie', +'login_restrictions_apply' => 'Échec de la connexion en raison de restrictions', 'logout' => 'Déconnexion', 'log_management' => 'Gestion des fichiers journaux', 'lo_LA' => 'Laotien', +'malformed_expiration_date' => '', 'manager' => 'Responsable', 'manager_of_group' => 'Vous êtes le gestionnaire de ce groupe', 'mandatory_approvergroups' => 'Obligatoire : groupes de valideurs', @@ -769,6 +776,7 @@ URL: [url]', 'max_upload_size' => 'Taille maximum de fichier déposé', 'may' => 'Mai', 'menu_dropfolder' => 'Dossier de dépôt', +'menu_upload_from_dropfolder' => '', 'mimetype' => 'Type MIME', 'minutes' => 'minutes', 'misc' => 'Divers', @@ -1201,6 +1209,8 @@ Nom : [username] 'settings_Advanced' => 'Avancé', 'settings_advancedAcl' => 'Contrôle d’accès avancé', 'settings_advancedAcl_desc' => 'Le contrôle d’accès avancé permet d’activer/désactiver certains modules du logiciel. Il ne peut pas être utilisé pour les droits d’accès sur les documents et dossiers.', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', 'settings_allowReviewerOnly' => 'Permettre d’affecter l’examinateur uniquement', 'settings_allowReviewerOnly_desc' => 'Activer cette option pour permettre d’affecter un examinateur mais pas d’approbateur dans le mode de Workflow traditionnel.', 'settings_apache_mod_rewrite' => 'Apache - Module Rewrite', @@ -1228,7 +1238,7 @@ Nom : [username] 'settings_convertToPdf' => 'Convertir en PDF le document pour prévisualisation', 'settings_convertToPdf_desc' => 'Si le document ne peut pas être lu nativement par le navigateur, une version convertie en PDF sera affichée.', 'settings_cookieLifetime' => 'Durée de vie des Cookies', -'settings_cookieLifetime_desc' => 'La durée de vie d\'un cooke en secondes. Si réglée à 0, le cookie sera supprimé à la fermeture du navigateur.', +'settings_cookieLifetime_desc' => 'Durée de vie d’un cookie en secondes. Si cette valeur est définie à 0, le cookie sera supprimé à la fermeture du navigateur.', 'settings_coreDir' => 'Répertoire Core SeedDMS', 'settings_coreDir_desc' => 'Chemin vers SeedDMS_Core (optionnel)', 'settings_createCheckOutDir' => 'Dossier de blocage', @@ -1352,6 +1362,8 @@ Nom : [username] 'settings_enableVersionModification_desc' => 'Active/désactive la modification de version d’un document par les utilisateurs normaux après le dépôt. L’administrateur peut toujours modifier la version après le dépôt.', 'settings_enableWebdavReplaceDoc' => 'Remplacer le document lors de l’enregistrement', 'settings_enableWebdavReplaceDoc_desc' => 'Si activé, l’enregistrement d’une nouvelle version d’un document remplacera l’ancien document plutôt que de créer une nouvelle version. Cela s’appliquera uniquement si l’utilisateur, le type MIME et le nom du fichier sont identiques à la dernière version. Cela peut être utile quand les applications enregistrent automatiquement un document à intervalles fixes.', +'settings_enableXsendfile' => 'Utiliser le module apache xsendfile', +'settings_enableXsendfile_desc' => 'Si cette option est définie et que le module apache xsendfile est installé, il sera utilisé pour la livraison des images.', 'settings_encryptionKey' => 'Clé de cryptage', 'settings_encryptionKey_desc' => 'Cette chaîne est utilisée pour créer un identifiant unique étant ajouté comme champ masqué à un formulaire afin de prévenir des attaques CSRF.', 'settings_error' => 'Erreur', @@ -1361,8 +1373,8 @@ Nom : [username] 'settings_expandFolderTree_val1' => 'Démarrer avec le premier niveau déroulé', 'settings_expandFolderTree_val2' => 'Démarrer avec l\'arborescence déroulée', 'settings_Extensions' => 'Extensions', -'settings_extraPath' => 'Chemin ADOdb', -'settings_extraPath_desc' => 'Chemin vers adodb. Il s\'agit du répertoire contenant le répertoire adodb', +'settings_extraPath' => 'Chemin d’inclusion supplémentaire PHP', +'settings_extraPath_desc' => 'Chemin vers des logiciels supplémentaires. Il s’agit du répertoire contenant par exemple le répertoire ADOdb ou des paquets PEAR supplémentaires.', 'settings_firstDayOfWeek' => 'Premier jour de la semaine', 'settings_firstDayOfWeek_desc' => 'Premier jour de la semaine', 'settings_footNote' => 'Note de bas de page', @@ -1406,7 +1418,7 @@ Nom : [username] 'settings_maxDirID' => 'Nombre max. de sous-dossiers', 'settings_maxDirID_desc' => 'Nombre maximum de sous-répertoires par le répertoire parent. Par défaut: 0.', 'settings_maxExecutionTime' => 'Temps d\'exécution max (s)', -'settings_maxExecutionTime_desc' => 'Ceci définit la durée maximale en secondes q\'un script est autorisé à exécuter avant de se terminer par l\'analyse syntaxique', +'settings_maxExecutionTime_desc' => 'Ceci définit la durée maximale, en secondes, pendant laquelle un script est autorisé à s’exécuter avant d’être interrompu.', 'settings_maxItemsPerPage' => 'Nombre d’éléments max. sur une page', 'settings_maxItemsPerPage_desc' => 'Limite le nombre de dossiers et de documents affichés sur la page du dossier de visualisation. D\'autres objets seront chargés lors du défilement jusqu\'à la fin de la page. Réglez sur 0 pour toujours afficher tous les objets.', 'settings_maxRecursiveCount' => 'Nombre maximal de document/dossier récursif', @@ -1427,7 +1439,7 @@ Nom : [username] 'settings_passwordExpiration' => 'Expiration du mot de passe', 'settings_passwordExpiration_desc' => 'Le nombre de jours après lequel un mot de passe expire et doit être remis à zéro. 0 désactive l\'expiration du mot de passe.', 'settings_passwordHistory' => 'Historique mot de passe', -'settings_passwordHistory_desc' => 'Le nombre de mots de passe q\'un utilisateur doit avoir utilisé avant d\'être réutilisé. 0 désactive l\'historique du mot de passe.', +'settings_passwordHistory_desc' => 'Nombre de mots de passe qu’un utilisateur doit avoir utilisé avant d’être réutilisé. 0 désactive l’historique du mot de passe.', 'settings_passwordStrength' => 'Min. résistance mot de passe', 'settings_passwordStrengthAlgorithm' => 'Algorithme pour les mots de passe', 'settings_passwordStrengthAlgorithm_desc' => 'L\'algorithme utilisé pour le calcul de robustesse du mot de passe. L\'algorithme \'simple\' vérifie juste pour au moins huit caractères, une lettre minuscule, une lettre majuscule, un chiffre et un caractère spécial. Si ces conditions sont remplies, le résultat retourné est de 100, sinon 0.', @@ -1544,7 +1556,7 @@ Nom : [username] 'set_owner_error' => 'Erreur lors de la définition du propriétaire', 'set_password' => 'Définir mot de passe', 'set_workflow' => 'Définir le Workflow', -'show_extension_changelog' => '', +'show_extension_changelog' => 'Afficher le journal des modifications', 'show_extension_version_list' => 'Afficher la liste des versions', 'signed_in_as' => 'Connecté en tant que', 'sign_in' => 'Connexion', @@ -1575,6 +1587,7 @@ Nom : [username] 'splash_edit_event' => 'Événement modifié', 'splash_edit_group' => 'Groupe modifié', 'splash_edit_role' => 'Rôle modifié', +'splash_edit_task' => '', 'splash_edit_user' => 'Utilisateur modifié', 'splash_error_add_to_transmittal' => 'Erreur lors de l’ajout du document à la transmission', 'splash_error_rm_download_link' => 'Erreur lors de la suppression du lien de téléchargement', @@ -1605,6 +1618,9 @@ Nom : [username] 'splash_rm_transmittal' => 'Transmission supprimée', 'splash_rm_user' => 'Utilisateur supprimé', 'splash_rm_user_processes' => 'Utilisateur retiré de tous les processus', +'splash_rm_workflow' => 'Workflow supprimé', +'splash_rm_workflow_action' => 'Action de workflow supprimée', +'splash_rm_workflow_state' => 'État de workflow supprimé', 'splash_saved_file' => 'Version enregistrée', 'splash_save_user_data' => 'Données utilisateur enregistrées', 'splash_send_download_link' => 'Lien de téléchargement envoyé par e-mail', @@ -1617,6 +1633,7 @@ Nom : [username] 'splash_toogle_group_manager' => 'Responsable de groupe changé', 'splash_transfer_document' => 'Document transféré', 'splash_transfer_objects' => 'Objets transférés', +'splash_trigger_workflow' => 'Transition de workflow déclenchée', 'state_and_next_state' => 'État initial/suivant', 'statistic' => 'Statistiques', 'status' => 'Statut', @@ -1666,12 +1683,12 @@ Nom : [username] 'takeOverIndApprover' => 'Récupérer les approbateurs de la dernière version.', 'takeOverIndReviewer' => 'Récupérer les examinateurs de la dernière version.', 'tasks' => 'Tâches', -'task_description' => '', -'task_disabled' => '', -'task_frequency' => '', -'task_last_run' => '', -'task_name' => '', -'task_next_run' => '', +'task_description' => 'Description', +'task_disabled' => 'Désactivée', +'task_frequency' => 'Fréquence', +'task_last_run' => 'Dernière exécution', +'task_name' => 'Nom', +'task_next_run' => 'Prochaine exécution', 'temp_jscode' => 'Code javascript temporaire', 'testmail_body' => 'Ce message est un test pour vérifier la configuration mail de SeedDMS.', 'testmail_subject' => 'E-mail test', diff --git a/languages/hr_HR/lang.inc b/languages/hr_HR/lang.inc index c9920e8c3..1b379a1dc 100644 --- a/languages/hr_HR/lang.inc +++ b/languages/hr_HR/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (1217), marbanas (16) +// Translators: Admin (1221), marbanas (16) $text = array( '2_factor_auth' => '', @@ -198,6 +198,7 @@ Internet poveznica: [url]', 'at_least_n_users_of_group' => 'Najmanje [number_of_users] korisnika iz [group]', 'august' => 'Kolovoz', 'authentication' => 'Ovjera', +'authentication_failed' => '', 'author' => 'Autor', 'automatic_status_update' => 'Automatska promjena statusa', 'back' => 'Natrag', @@ -481,6 +482,7 @@ Internet poveznica: [url]', 'error_add_aro' => '', 'error_add_permission' => '', 'error_cleared_cache' => '', +'error_edit_task' => '', 'error_extension_getlist' => '', 'error_importfs' => '', 'error_no_document_selected' => 'Nije odabran dokument', @@ -489,8 +491,12 @@ Internet poveznica: [url]', 'error_remove_document' => '', 'error_remove_folder' => '', 'error_remove_permission' => '', +'error_rm_workflow' => '', +'error_rm_workflow_action' => '', +'error_rm_workflow_state' => '', 'error_toogle_permission' => '', 'error_transfer_document' => '', +'error_trigger_workflow' => '', 'error_update_document' => '', 'error_uploading_reviewer_only' => '', 'es_ES' => 'Španjolski', @@ -633,7 +639,6 @@ Internet poveznica: [url]', 'index_waiting' => '', 'individuals' => 'Pojedinci', 'individuals_in_groups' => '', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => '', 'inherited' => 'naslijeđeno', 'inherits_access_copy_msg' => 'Kopiraj listu naslijeđenih prava pristupa', @@ -726,9 +731,11 @@ Internet poveznica: [url]', 'login_error_title' => 'Greška kod prijave', 'login_not_given' => 'Nije isporučeno korisničko ime', 'login_ok' => 'Uspješna prijava', +'login_restrictions_apply' => '', 'logout' => 'Odjava', 'log_management' => 'Upravljanje datotekama zapisa', 'lo_LA' => 'Laocijanski', +'malformed_expiration_date' => '', 'manager' => 'Upravitelj', 'manager_of_group' => 'Vi ste upravitelj ove grupe', 'mandatory_approvergroups' => 'Obavezne grupe validatora', @@ -743,6 +750,7 @@ Internet poveznica: [url]', 'max_upload_size' => 'Max. veličina za prijenos', 'may' => 'Svibanj', 'menu_dropfolder' => '', +'menu_upload_from_dropfolder' => '', 'mimetype' => 'Mime type', 'minutes' => 'minute', 'misc' => 'Razno', @@ -904,7 +912,7 @@ Ako i dalje imate problema s prijavom, molimo kontaktirajte Vašeg administrator 'personal_default_keywords' => 'Osobni popis ključnih riječi', 'pl_PL' => 'Poljski', 'possible_substitutes' => 'Zamjene', -'preset_expires' => '', +'preset_expires' => 'Ističe', 'preview' => 'Predpregled', 'preview_converters' => 'Pretpregled konverzije dokumenta', 'preview_images' => '', @@ -1125,7 +1133,7 @@ Internet poveznica: [url]', 'select_attrdefgrp_show' => '', 'select_attribute_value' => '', 'select_category' => 'Kliknite za odabir kategorije', -'select_group' => '', +'select_group' => 'Izaberi grupu', 'select_groups' => 'Kliknite za odabir grupa', 'select_grp_approvers' => 'Kliknite za odabir validatora grupe', 'select_grp_ind_approvers' => '', @@ -1143,7 +1151,7 @@ Internet poveznica: [url]', 'select_ind_reviewers' => 'Kliknite za odabir pojedinačnog recezenta', 'select_ind_revisors' => 'Kliknite za odabir pojedinačnog revizora', 'select_one' => 'Odaberite jednog', -'select_user' => '', +'select_user' => 'Izaberi korisnika', 'select_users' => 'Kliknite za odabir korisnika', 'select_value' => 'Odaberite vrijednost', 'select_workflow' => 'Odaberite tok rada', @@ -1169,6 +1177,8 @@ Internet poveznica: [url]', 'settings_Advanced' => 'Napredno', 'settings_advancedAcl' => '', 'settings_advancedAcl_desc' => '', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', 'settings_allowReviewerOnly' => '', 'settings_allowReviewerOnly_desc' => '', 'settings_apache_mod_rewrite' => 'Apache - Modul prepisa', @@ -1320,6 +1330,8 @@ Internet poveznica: [url]', 'settings_enableVersionModification_desc' => 'Omogući/onemogući mijenjanje verzija dokumenta redovnim korisnicima nakon učitavanja verzije. Administrator uvijek može promijeniti verziju nakon učitavanja.', 'settings_enableWebdavReplaceDoc' => '', 'settings_enableWebdavReplaceDoc_desc' => '', +'settings_enableXsendfile' => '', +'settings_enableXsendfile_desc' => '', 'settings_encryptionKey' => 'Ključ za šifriranje', 'settings_encryptionKey_desc' => 'Ovaj string se koristi za izradu jedinstvenog identifikatora koji će biti dodan kao skriveno polje u formularu kako bi se spriječili CSRF napadi.', 'settings_error' => 'Greška', @@ -1543,6 +1555,7 @@ Internet poveznica: [url]', 'splash_edit_event' => '', 'splash_edit_group' => 'Groupa pohranjena', 'splash_edit_role' => '', +'splash_edit_task' => '', 'splash_edit_user' => 'Korisnik pohranjen', 'splash_error_add_to_transmittal' => '', 'splash_error_rm_download_link' => '', @@ -1573,6 +1586,9 @@ Internet poveznica: [url]', 'splash_rm_transmittal' => '', 'splash_rm_user' => 'Korisnik uklonjen', 'splash_rm_user_processes' => '', +'splash_rm_workflow' => '', +'splash_rm_workflow_action' => '', +'splash_rm_workflow_state' => '', 'splash_saved_file' => '', 'splash_save_user_data' => '', 'splash_send_download_link' => '', @@ -1585,6 +1601,7 @@ Internet poveznica: [url]', 'splash_toogle_group_manager' => 'Zamjenjen upravitelj grupe', 'splash_transfer_document' => '', 'splash_transfer_objects' => '', +'splash_trigger_workflow' => '', 'state_and_next_state' => 'Status/Slijedeći status', 'statistic' => 'Statistika', 'status' => 'Status', diff --git a/languages/hu_HU/lang.inc b/languages/hu_HU/lang.inc index 5288a3979..71e88d17b 100644 --- a/languages/hu_HU/lang.inc +++ b/languages/hu_HU/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (629), ribaz (1036) +// Translators: Admin (631), ribaz (1036) $text = array( '2_factor_auth' => 'Kétfaktoros azonosítás', @@ -193,6 +193,7 @@ URL: [url]', 'at_least_n_users_of_group' => 'Legalább [number_of_users] felhasználó a [group] csoportban', 'august' => 'Augusztus', 'authentication' => 'Hitelesítés', +'authentication_failed' => '', 'author' => 'szerző', 'automatic_status_update' => 'Automatikus állapot változás', 'back' => 'Vissza', @@ -476,6 +477,7 @@ URL: [url]', 'error_add_aro' => '', 'error_add_permission' => '', 'error_cleared_cache' => '', +'error_edit_task' => '', 'error_extension_getlist' => '', 'error_importfs' => '', 'error_no_document_selected' => 'Nincs kijelölt dokumentum', @@ -484,8 +486,12 @@ URL: [url]', 'error_remove_document' => '', 'error_remove_folder' => '', 'error_remove_permission' => '', +'error_rm_workflow' => '', +'error_rm_workflow_action' => '', +'error_rm_workflow_state' => '', 'error_toogle_permission' => '', 'error_transfer_document' => '', +'error_trigger_workflow' => '', 'error_update_document' => '', 'error_uploading_reviewer_only' => '', 'es_ES' => 'Spanyol', @@ -628,7 +634,6 @@ URL: [url]', 'index_waiting' => '', 'individuals' => 'Egyedek', 'individuals_in_groups' => '', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => '', 'inherited' => 'örökölt', 'inherits_access_copy_msg' => 'Örökített hozzáférési lista másolása', @@ -721,9 +726,11 @@ URL: [url]', 'login_error_title' => 'Bejelentkezési hiba', 'login_not_given' => 'Felhasználónév nincs megadva', 'login_ok' => 'Sikeres bejelentkezés', +'login_restrictions_apply' => '', 'logout' => 'Kijelentkezés', 'log_management' => 'Napló állományok kezelése', 'lo_LA' => 'Laoszi', +'malformed_expiration_date' => '', 'manager' => 'Kezelő', 'manager_of_group' => 'Ön a vezető ebben a csoportban', 'mandatory_approvergroups' => 'Kötelező csoportjai a jóváhagyóknak', @@ -738,6 +745,7 @@ URL: [url]', 'max_upload_size' => 'Legnagyobb feltölthető méret', 'may' => 'Május', 'menu_dropfolder' => '', +'menu_upload_from_dropfolder' => '', 'mimetype' => 'Mime típus', 'minutes' => 'perc', 'misc' => 'Vegyes', @@ -1103,7 +1111,7 @@ URL: [url]', 'select_attrdefgrp_show' => '', 'select_attribute_value' => '', 'select_category' => 'Kattintson a kategória kiválasztásához', -'select_group' => '', +'select_group' => 'Csoport kiválasztása', 'select_groups' => 'Kattintson a csoportok kijelöléséhez', 'select_grp_approvers' => 'Kattintson a csoport jóváhagyó kijelöléséhez', 'select_grp_ind_approvers' => '', @@ -1121,7 +1129,7 @@ URL: [url]', 'select_ind_reviewers' => 'Kattintson az önálló felülvizsgáló kijelöléséhez', 'select_ind_revisors' => '', 'select_one' => 'Vßlasszon egyet', -'select_user' => '', +'select_user' => 'Felhasználó kiválasztása', 'select_users' => 'Kattintson a felhasználó kiválasztásához', 'select_value' => '', 'select_workflow' => 'Munkafolyamat választás', @@ -1147,6 +1155,8 @@ URL: [url]', 'settings_Advanced' => 'Részletek', 'settings_advancedAcl' => '', 'settings_advancedAcl_desc' => '', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', 'settings_allowReviewerOnly' => '', 'settings_allowReviewerOnly_desc' => '', 'settings_apache_mod_rewrite' => 'Apache - Rewrite modul', @@ -1298,6 +1308,8 @@ URL: [url]', 'settings_enableVersionModification_desc' => 'Engedélyezi/tiltja a dokumentum verziók módosítását az általános felhasználóknak miután a verzió feltöltésre került. Adminisztrátor mindig módosíthatja a verziót feltöltés után.', 'settings_enableWebdavReplaceDoc' => '', 'settings_enableWebdavReplaceDoc_desc' => '', +'settings_enableXsendfile' => '', +'settings_enableXsendfile_desc' => '', 'settings_encryptionKey' => 'Titkosító kulcs', 'settings_encryptionKey_desc' => 'Ez a karaktersorozat használható egyedi azonosító létrehozásához amely rejtett mezőként lesz hozzáadva az űrlapokhoz a CSRF támadások megelőzésére.', 'settings_error' => 'Hiba', @@ -1521,6 +1533,7 @@ URL: [url]', 'splash_edit_event' => '', 'splash_edit_group' => 'Csoport mentve', 'splash_edit_role' => '', +'splash_edit_task' => '', 'splash_edit_user' => 'Felhasználó mentve', 'splash_error_add_to_transmittal' => '', 'splash_error_rm_download_link' => '', @@ -1551,6 +1564,9 @@ URL: [url]', 'splash_rm_transmittal' => '', 'splash_rm_user' => 'Felhasználó eltávolítva', 'splash_rm_user_processes' => '', +'splash_rm_workflow' => '', +'splash_rm_workflow_action' => '', +'splash_rm_workflow_state' => '', 'splash_saved_file' => '', 'splash_save_user_data' => '', 'splash_send_download_link' => '', @@ -1563,6 +1579,7 @@ URL: [url]', 'splash_toogle_group_manager' => 'Csoport kezelő kiválasztva', 'splash_transfer_document' => '', 'splash_transfer_objects' => '', +'splash_trigger_workflow' => '', 'state_and_next_state' => 'Állapot/Következő állapot', 'statistic' => 'Statisztika', 'status' => 'Állapot', diff --git a/languages/it_IT/lang.inc b/languages/it_IT/lang.inc index a609a14d1..2b939c5d3 100644 --- a/languages/it_IT/lang.inc +++ b/languages/it_IT/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (1619), rickr (144), s.pnt (26) +// Translators: Admin (1622), rickr (144), s.pnt (26) $text = array( '2_factor_auth' => 'Autorizzazione a due fattori', @@ -199,6 +199,7 @@ URL: [url]', 'at_least_n_users_of_group' => 'Minimo [number_of_users] utenti del gruppo [group]', 'august' => 'Agosto', 'authentication' => 'Autenticazione', +'authentication_failed' => '', 'author' => 'Autore', 'automatic_status_update' => 'Modifica automatica dello stato', 'back' => 'Ritorna', @@ -482,6 +483,7 @@ URL: [url]', 'error_add_aro' => 'Errore durante l\'accesso aggiungendo richiesta oggetto', 'error_add_permission' => 'Errore durante l\'aggiunta di permesso', 'error_cleared_cache' => 'Errore durante svuotare la cache', +'error_edit_task' => '', 'error_extension_getlist' => '', 'error_importfs' => 'Errore durante l\'importazione dal file system', 'error_no_document_selected' => 'Nessun documento selezionato', @@ -490,8 +492,12 @@ URL: [url]', 'error_remove_document' => '', 'error_remove_folder' => '', 'error_remove_permission' => 'Errore durante la rimozione delle autorizzazioni', +'error_rm_workflow' => '', +'error_rm_workflow_action' => '', +'error_rm_workflow_state' => '', 'error_toogle_permission' => 'Errore durante la modifica permessi', 'error_transfer_document' => '', +'error_trigger_workflow' => '', 'error_update_document' => '', 'error_uploading_reviewer_only' => '', 'es_ES' => 'Spagnolo', @@ -634,7 +640,6 @@ URL: [url]', 'index_waiting' => 'Attendi', 'individuals' => 'Singoli', 'individuals_in_groups' => 'I membri de la gruppo', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => '', 'inherited' => 'ereditato', 'inherits_access_copy_msg' => 'Copia la lista degli accessi ereditati', @@ -727,9 +732,11 @@ URL: [url]', 'login_error_title' => 'Errore di login', 'login_not_given' => 'Non è stato inserito il nome utente', 'login_ok' => 'Login eseguito', +'login_restrictions_apply' => '', 'logout' => 'Logout', 'log_management' => 'Amministrazione file di log', 'lo_LA' => 'Laotiano', +'malformed_expiration_date' => '', 'manager' => 'Manager', 'manager_of_group' => 'Tu sei l\'Amministratore di questo gruppo', 'mandatory_approvergroups' => 'Gruppi di Approvatori necessari', @@ -744,6 +751,7 @@ URL: [url]', 'max_upload_size' => 'Dimensione massima caricabile per ogni file', 'may' => 'Maggio', 'menu_dropfolder' => '', +'menu_upload_from_dropfolder' => '', 'mimetype' => 'Tipo (MIME)', 'minutes' => 'minuti', 'misc' => 'Varie', @@ -1181,6 +1189,8 @@ URL: [url]', 'settings_Advanced' => 'Avanzate', 'settings_advancedAcl' => 'Avanzate controlo accesso', 'settings_advancedAcl_desc' => 'Avanzatoa controlo di accesso consente di attivare / diattivare alcuni moduli di software. Non può essere utilizzato per i diritti di accesso su documenti e cartelle.', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', 'settings_allowReviewerOnly' => 'Abilita l\'impostazione del solo revisore', 'settings_allowReviewerOnly_desc' => 'Abilita se si vuole concedere di impostare solo un revisore ma non un apporvatore nel workflow tradizionale', 'settings_apache_mod_rewrite' => 'Apache - Mod Rewrite', @@ -1332,6 +1342,8 @@ URL: [url]', 'settings_enableVersionModification_desc' => 'Abilita/disabilita il permesso di modificare le versioni di un documento da parte di un qualsiasi utente. Gli Amministratori hanno sempre e comunque tale facoltà.', 'settings_enableWebdavReplaceDoc' => 'Sostituisci il documento durante il salvataggio', 'settings_enableWebdavReplaceDoc_desc' => 'Se abilitato, durante il salvataggio il documento verrà sostituito invece di crearne uno nuovo. Si applica solo se l\'utente, estensione e nome del file sono uguali all\'ultima versione. E\' utile per applicazioni che ad intervalli regolari salvano un documento.', +'settings_enableXsendfile' => 'Usa il modulo apache xsendfile', +'settings_enableXsendfile_desc' => 'Se selezionato ed e\' installato il modulo apache xsendfile, questo puo\' essere usato per inviare immagini', 'settings_encryptionKey' => 'Chiave di criptazione', 'settings_encryptionKey_desc' => 'La chiave viene usata per creare un identificatore unico da aggiungere come campo nascosto ad un formulario per protezione da attacchi CSRF.', 'settings_error' => 'Errore', @@ -1512,7 +1524,7 @@ URL: [url]', 'settings_versiontolow' => 'Versione obsoleta', 'settings_viewOnlineFileTypes' => 'Tipi di files visualizzabili', 'settings_viewOnlineFileTypes_desc' => 'Solo i files che terminano nella maniera seguente verranno visualizzati (UTILIZZARE SOLO IL MINUSCOLO)', -'settings_webdav' => '', +'settings_webdav' => 'WebDAV', 'settings_workflowMode' => 'Modalità flusso di lavoro', 'settings_workflowMode_desc' => 'Il flusso di lavoro \'avanzato\' permette di rilasciare un proprio flusso di lavoro per le versioni dei documenti', 'settings_workflowMode_valadvanced' => 'Avanzato', @@ -1555,6 +1567,7 @@ URL: [url]', 'splash_edit_event' => '', 'splash_edit_group' => 'Gruppo modificato', 'splash_edit_role' => 'Ruolo memorizzata', +'splash_edit_task' => '', 'splash_edit_user' => 'Utente modificato', 'splash_error_add_to_transmittal' => 'Errore durante l\'aggiunta di documento per la trasmissione', 'splash_error_rm_download_link' => '', @@ -1585,6 +1598,9 @@ URL: [url]', 'splash_rm_transmittal' => 'Trasmissione cancellato', 'splash_rm_user' => 'Utente eliminato', 'splash_rm_user_processes' => '', +'splash_rm_workflow' => '', +'splash_rm_workflow_action' => '', +'splash_rm_workflow_state' => '', 'splash_saved_file' => '', 'splash_save_user_data' => '', 'splash_send_download_link' => '', @@ -1597,6 +1613,7 @@ URL: [url]', 'splash_toogle_group_manager' => 'Amministratore di gruppo invertito', 'splash_transfer_document' => '', 'splash_transfer_objects' => '', +'splash_trigger_workflow' => '', 'state_and_next_state' => 'Stato/Prossimo stato', 'statistic' => 'Statistiche', 'status' => 'Stato', diff --git a/languages/ko_KR/lang.inc b/languages/ko_KR/lang.inc index f8169f5d3..c5733f683 100644 --- a/languages/ko_KR/lang.inc +++ b/languages/ko_KR/lang.inc @@ -200,6 +200,7 @@ URL: [url]', 적어도 [number_of_users]의 사용자 [group]', 'august' => '8월', 'authentication' => '인증', +'authentication_failed' => '', 'author' => '저자', 'automatic_status_update' => '자동 상태 변경', 'back' => '뒤로 가기', @@ -482,6 +483,7 @@ URL: [url]', 'error_add_aro' => '', 'error_add_permission' => '', 'error_cleared_cache' => '', +'error_edit_task' => '', 'error_extension_getlist' => '', 'error_importfs' => '', 'error_no_document_selected' => '선택되지 문서는', @@ -490,8 +492,12 @@ URL: [url]', 'error_remove_document' => '', 'error_remove_folder' => '', 'error_remove_permission' => '', +'error_rm_workflow' => '', +'error_rm_workflow_action' => '', +'error_rm_workflow_state' => '', 'error_toogle_permission' => '', 'error_transfer_document' => '', +'error_trigger_workflow' => '', 'error_update_document' => '', 'error_uploading_reviewer_only' => '', 'es_ES' => '스페인어', @@ -634,7 +640,6 @@ URL: [url]', 'index_waiting' => '기다리는 중', 'individuals' => '개인', 'individuals_in_groups' => '개별 그룹', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => '', 'inherited' => '상속', 'inherits_access_copy_msg' => '상속 액세스 목록 복사', @@ -727,9 +732,11 @@ URL: [url]', 'login_error_title' => '로그인 오류', 'login_not_given' => '사용자명이 제공되지 않았습니다.', 'login_ok' => '성공적인 로그인', +'login_restrictions_apply' => '', 'logout' => '로그 아웃', 'log_management' => '파일 관리 로그', 'lo_LA' => '', +'malformed_expiration_date' => '', 'manager' => '관리자', 'manager_of_group' => '당신은 이 그룹의 관리자 입니다.', 'mandatory_approvergroups' => '필수 승인 그룹', @@ -744,6 +751,7 @@ URL: [url]', 'max_upload_size' => '최대 업로드 크기', 'may' => '월', 'menu_dropfolder' => '', +'menu_upload_from_dropfolder' => '', 'mimetype' => 'MIME 유형', 'minutes' => '분', 'misc' => '기타', @@ -1163,6 +1171,8 @@ URL : [url]', 'settings_Advanced' => '고급', 'settings_advancedAcl' => '', 'settings_advancedAcl_desc' => '', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', 'settings_allowReviewerOnly' => '', 'settings_allowReviewerOnly_desc' => '', 'settings_apache_mod_rewrite' => '아파치 - 모듈 다시 쓰기', @@ -1314,6 +1324,8 @@ URL : [url]', 'settings_enableVersionModification_desc' => '버전이 업로드 된 후 일반 사용자가 문서 버전의 활성화 / 비활성화 수정을 사용합니다. 관리자는 항상 업로드 후 버전을 수정할 수 있습니다.', 'settings_enableWebdavReplaceDoc' => '', 'settings_enableWebdavReplaceDoc_desc' => '', +'settings_enableXsendfile' => '', +'settings_enableXsendfile_desc' => '', 'settings_encryptionKey' => '암호화 키', 'settings_encryptionKey_desc' => '이 문자열은 CSRF 공격을 방지하기 위해 formular에 숨겨진 필드로 추가되는 고유 식별자를 만드는 데 사용된다.', 'settings_error' => '오류', @@ -1537,6 +1549,7 @@ URL : [url]', 'splash_edit_event' => '', 'splash_edit_group' => '그룹 저장', 'splash_edit_role' => '', +'splash_edit_task' => '', 'splash_edit_user' => '사용자 저장', 'splash_error_add_to_transmittal' => '', 'splash_error_rm_download_link' => '', @@ -1567,6 +1580,9 @@ URL : [url]', 'splash_rm_transmittal' => '', 'splash_rm_user' => '사용자 제거', 'splash_rm_user_processes' => '', +'splash_rm_workflow' => '', +'splash_rm_workflow_action' => '', +'splash_rm_workflow_state' => '', 'splash_saved_file' => '', 'splash_save_user_data' => '', 'splash_send_download_link' => '', @@ -1579,6 +1595,7 @@ URL : [url]', 'splash_toogle_group_manager' => '그룹 관리자 전환', 'splash_transfer_document' => '', 'splash_transfer_objects' => '', +'splash_trigger_workflow' => '', 'state_and_next_state' => '상태 / 다음 상태', 'statistic' => '통계', 'status' => '상태', diff --git a/languages/lo_LA/lang.inc b/languages/lo_LA/lang.inc index 0c5c7e16e..d2a6be267 100644 --- a/languages/lo_LA/lang.inc +++ b/languages/lo_LA/lang.inc @@ -196,6 +196,7 @@ URL: [url]', 'at_least_n_users_of_group' => 'ຈໍານວນຜູ້ໃຊ້ [number_of_users] ຜູ້ໃຊ້ [group]', 'august' => 'ເດືອນສິງຫາ', 'authentication' => 'ການກວດສອບຄວາມຖືກຕ້ອງ', +'authentication_failed' => '', 'author' => 'ຜູ້ຂຽນ', 'automatic_status_update' => 'ປ່ຽນສະຖານະໂດຍອັດຕະໂນມັດ', 'back' => 'ກັບຄືນ', @@ -486,6 +487,7 @@ URL: [url]', 'error_add_aro' => 'ເກີດຂໍຜິດພາດຂະນະເພີ່ມການເພີ່ມຄຳຂໍການເຂົາເຖິງ', 'error_add_permission' => 'ເກີດຂໍ້ຜິດພາດໃນຂະນະເພີ່ມສິດ', 'error_cleared_cache' => 'ເກີດຂໍ້ຜິດພາດໃນຂະນະລ້າງແຄຣ', +'error_edit_task' => '', 'error_extension_getlist' => '', 'error_importfs' => 'ເກີດຂໍ້ຜິດພາດໃນຂະນະເຂົ້າລະບົບໄຟລຟອມ', 'error_no_document_selected' => 'ບໍ່ມີເອກະສານທີເລືອກ', @@ -494,8 +496,12 @@ URL: [url]', 'error_remove_document' => 'ເກີດຂໍ້ຜິດພາດຂະນະລົບເອກະສານ', 'error_remove_folder' => 'ເກີດຂໍ້ຜິດພາດຂະນະລົບໂຟລເດີ', 'error_remove_permission' => 'ເກີດຂໍ້ຜິດພາດໃນຂະນະລົບສິດ', +'error_rm_workflow' => '', +'error_rm_workflow_action' => '', +'error_rm_workflow_state' => '', 'error_toogle_permission' => 'ເກິດຂໍ້ຜິດພາດໃນຂະນະປ່ຽນສິດ', 'error_transfer_document' => '', +'error_trigger_workflow' => '', 'error_update_document' => '', 'error_uploading_reviewer_only' => '', 'es_ES' => 'ສະເປນ', @@ -638,7 +644,6 @@ URL: [url]', 'index_waiting' => 'ຖ້າ', 'individuals' => 'ບຸກຄົນ', 'individuals_in_groups' => 'ສະມາຊິກຂອງກຸ່ມ', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => '', 'inherited' => 'ຮັບການຖ່າຍທອດ', 'inherits_access_copy_msg' => 'ຄັດລັອກລາຍການເຂົາເຖິງທີສືບທອດ', @@ -731,9 +736,11 @@ URL: [url]', 'login_error_title' => 'ຂໍ້ຜິດພາດໃນການເຂົ້າລະບົບ', 'login_not_given' => 'ບໍ່ໄດ້ລະບຸຊື່ຜູ້ໄຊ້', 'login_ok' => 'ລົງຊື່ເຂົາໄຊ້ສຳເລັດ', +'login_restrictions_apply' => '', 'logout' => 'ອອກຈາກລະບົບ', 'log_management' => 'ການຈັດການຟາຍບັນທຶກ', 'lo_LA' => '', +'malformed_expiration_date' => '', 'manager' => 'ຜູ້ຈັດການ', 'manager_of_group' => 'ເຈົ້າເປັນຜູ້ດູແລກຸ່ມນີ້', 'mandatory_approvergroups' => 'ກຸ່ມຜູ້ອະນຸມັດທີ່ຈຳເປັນ', @@ -748,6 +755,7 @@ URL: [url]', 'max_upload_size' => 'ຂະຫນາດການອັບໂຫລດສູງສຸດ', 'may' => 'ເດືອນພຶດສະພາ', 'menu_dropfolder' => 'ວາງໂຟລເດີ', +'menu_upload_from_dropfolder' => '', 'mimetype' => 'ປະເພດ Mime', 'minutes' => '', 'misc' => 'ອື່ນໆ', @@ -1196,6 +1204,8 @@ URL: [url]', 'settings_Advanced' => 'ຂັນສູງ', 'settings_advancedAcl' => 'ການຄວບຄຸມການເຂົ້າເຖິງລະບົບຂັນສູງ', 'settings_advancedAcl_desc' => 'ການຄວບຄຸມການເຂົ້າເຖິງລະບົບຂັນສູງຈະຊ່ວຍໃຫ້ສາມາດເປີດ/ປິດ ໂມດູນບາງໂຕຂອງຊັອບແວ ໄດ້ບໍ່ສາມາດໄຊ້ສຳຫຼັບສິດທິການເຂົ້າເຖິງເອກະສານແລະໂຟລເດີ', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', 'settings_allowReviewerOnly' => '', 'settings_allowReviewerOnly_desc' => '', 'settings_apache_mod_rewrite' => 'ອາປາເຊ -ຂຽນໄຫມ່', @@ -1347,6 +1357,8 @@ URL: [url]', 'settings_enableVersionModification_desc' => 'ເປີດໄຊ້ງານ/ປິດໄຊ້ງານ', 'settings_enableWebdavReplaceDoc' => '', 'settings_enableWebdavReplaceDoc_desc' => '', +'settings_enableXsendfile' => '', +'settings_enableXsendfile_desc' => '', 'settings_encryptionKey' => 'ກະແຈການເຂົ້າລະຫັດລັບ', 'settings_encryptionKey_desc' => 'ສະຕິງນີ້ໄຊ້ສຳຫຼັບສ້າງຕົວ', 'settings_error' => 'ຄວາມຜິດພາດ', @@ -1570,6 +1582,7 @@ URL: [url]', 'splash_edit_event' => 'ບັນທຶກກິດຈະກຳແລ້ວ', 'splash_edit_group' => 'ບັນທຶກກຸ່ມແລ້ວ', 'splash_edit_role' => 'ບັນທຶກບົດບາດແລ້ວ', +'splash_edit_task' => '', 'splash_edit_user' => 'ບັນທຶກຜູ້ໄຊ້ແລ້ວ', 'splash_error_add_to_transmittal' => 'ເກີດຂໍ້ຜິດພາດໃນຂະນະທີ່ເພີ່ມເອກະສານເພື່ອຕິດຕໍ່', 'splash_error_rm_download_link' => 'ຂໍ້ຜິດພາດໃນການລົບລິງການດາວໂຫລດ', @@ -1600,6 +1613,9 @@ URL: [url]', 'splash_rm_transmittal' => 'ຍົກເລີກການລົບແລ້ວ', 'splash_rm_user' => 'ລົບຜູ້ໄຊ້ແລ້ວ', 'splash_rm_user_processes' => 'ຜູ້ໄຊ້ລົບອອກຈາກລະບົບທັງໝົດ', +'splash_rm_workflow' => '', +'splash_rm_workflow_action' => '', +'splash_rm_workflow_state' => '', 'splash_saved_file' => 'ບັນທຶກເວີຊັນແລ້ວ', 'splash_save_user_data' => 'ບັນທຶກຂໍ້ມູນຜູ້ໄຊ້ແລ້ວ', 'splash_send_download_link' => 'ດາວໂຫລດລິງທີ່ສົ່ງດ້ວຍອີເມວ', @@ -1612,6 +1628,7 @@ URL: [url]', 'splash_toogle_group_manager' => 'ການດູແລກຸ່ມ', 'splash_transfer_document' => '', 'splash_transfer_objects' => 'ຖ່າຍໂອນວັດຖຸຮຽບຮ້ອຍແລ້ວ', +'splash_trigger_workflow' => '', 'state_and_next_state' => 'ລັດ/ລັດຖັດໄປ', 'statistic' => 'ສະຖິຕິ', 'status' => 'ສະຖານະ', diff --git a/languages/nl_NL/lang.inc b/languages/nl_NL/lang.inc index 867e8616e..ce443f923 100644 --- a/languages/nl_NL/lang.inc +++ b/languages/nl_NL/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (759), gijsbertush (610), pepijn (45), reinoutdijkstra@hotmail.com (270) +// Translators: Admin (766), gijsbertush (651), pepijn (45), reinoutdijkstra@hotmail.com (270) $text = array( '2_factor_auth' => '2-factor-authenticatie', @@ -70,7 +70,7 @@ URL: [url]', 'add_revision' => 'Voeg goedkeuring toe', 'add_role' => 'Voeg een rol toe', 'add_subfolder' => 'Submap toevoegen', -'add_task' => '', +'add_task' => 'Voeg een taak toe', 'add_to_clipboard' => 'Toevoegen aan klembord', 'add_to_transmittal' => 'Toevoegen aan verzending', 'add_transmittal' => 'Verzending toevoegen', @@ -126,12 +126,12 @@ URL: [url]', 'approver_already_assigned' => 'autoriseerder al aangewezen', 'approver_already_removed' => 'autoriseerder reeds verwijderd', 'april' => 'april', -'archive' => '', +'archive' => 'Archief', 'archive_creation' => 'Archief aanmaken', 'archive_creation_warning' => 'Met deze handeling maakt U een Archief aan van alle bestanden in het DMS. Na het aanmaken van het Archief, wordt deze opgeslagen in de data-map van uw server.
Waarschuwing: een leesbaar Archief kan niet worden gebruikt voor server back-up doeleinde.', 'ar_EG' => 'Arabisch', 'assign_approvers' => 'Aangewezen [Goedkeurders]', -'assign_recipients' => '', +'assign_recipients' => 'Wijs ontvangers aan', 'assign_reviewers' => 'Aangewezen [Controleurs]', 'assign_user_property_to' => 'Wijs gebruikers machtigingen toe aan', 'assumed_released' => 'vermoedelijke status: Gepubliceerd', @@ -140,10 +140,10 @@ URL: [url]', 'attrdefgrp_show_list' => 'Lijst van attribuut-definiities', 'attrdefgrp_show_search' => 'Zoeken naar attribuut-definiities', 'attrdefgrp_show_searchlist' => 'Lijst van gezochte attribuut-definiities', -'attrdef_exists' => 'Kenmerk definitie bestaat al', +'attrdef_exists' => 'Kenmerkdefinitie bestaat al', 'attrdef_info' => 'Kenmerk info', -'attrdef_in_use' => 'Kenmerk definitie nog in gebruikt', -'attrdef_management' => 'Kenmerk definitie beheer', +'attrdef_in_use' => 'Kenmerkdefinitie nog in gebruikt', +'attrdef_management' => 'Kenmerkdefinitie-beheer', 'attrdef_maxvalues' => 'Max. aantal waarden', 'attrdef_minvalues' => 'Min. aantal waarden', 'attrdef_min_greater_max' => 'Het minimum aantal is groter dan het maximum aantal', @@ -164,14 +164,14 @@ URL: [url]', 'attrdef_type_url' => 'attribuut: url', 'attrdef_valueset' => 'Verzameling waarden', 'attributes' => 'Attributen', -'attribute_changed_email_body' => 'Attribuut gewijzigd -Document: [name] -Versie: [version] -Attribuut: [attribute_name] -Old value: [attribute_old_value] -New value: [attribute_new_value] -Bovenliggende map: [folder_path] -Gebruiker: [username] +'attribute_changed_email_body' => 'Attribuut gewijzigd +Document: [name] +Versie: [version] +Attribuut: [attribute_name] +Old value: [attribute_old_value] +New value: [attribute_new_value] +Bovenliggende map: [folder_path] +Gebruiker: [username] URL: [url]', 'attribute_changed_email_subject' => '[sitename]: [name] - Attribuut gewijzigd', 'attribute_count' => 'Aantal maal gebruikt', @@ -191,6 +191,7 @@ URL: [url]', 'at_least_n_users_of_group' => 'Minimaal [number_of_users] gebruikers van [group]', 'august' => 'augustus', 'authentication' => 'Authentificatie', +'authentication_failed' => 'Authenticatie mislukte', 'author' => 'Auteur', 'automatic_status_update' => 'Automatische Status wijziging', 'back' => 'Terug', @@ -236,7 +237,7 @@ URL: [url]', 'chart_docsperuser_title' => 'Documenten per gebruiker', 'chart_selection' => 'Kies grafiek', 'chart_sizeperuser_title' => 'Schijfruimte per gebruiker', -'checkedout_file_has_different_version' => 'Checkout-document is andere versie', +'checkedout_file_has_different_version' => 'Checkout-document is een andere versie', 'checkedout_file_has_disappeared' => 'File is onvindbaar', 'checkedout_file_is_unchanged' => 'Checkout-document ongewijzigd', 'checkin_document' => 'Veranderd document', @@ -244,7 +245,7 @@ URL: [url]', 'checkout_document' => 'Checkout-document', 'checkout_is_disabled' => 'Checkout is niet mogelijk', 'choose_attrdef' => 'Kies een kenmerkdefinitie', -'choose_attrdefgroup' => 'Kies een kenmerkdefinite-groep', +'choose_attrdefgroup' => 'Kies een kenmerkdefinitie-groep', 'choose_category' => 'Selecteer a.u.b.', 'choose_group' => 'Selecteer Groep', 'choose_role' => 'Selecteer een rol', @@ -266,13 +267,13 @@ URL: [url]', 'comment' => 'Commentaar', 'comment_changed_email' => 'Gewijzigde email', 'comment_for_current_version' => 'Versie van het commentaar', -'configure_extension' => '', +'configure_extension' => 'Configureer extensie', 'confirm_clear_cache' => 'Ja, ik wil de cache opschonen!', 'confirm_create_fulltext_index' => 'Ja, Ik wil de volledigetekst index opnieuw maken!', 'confirm_move_document' => 'Bevestig verplaatsing van document', 'confirm_move_folder' => 'Bevestig de verplaatsing van de map', 'confirm_pwd' => 'Bevestig wachtwoord', -'confirm_rm_attr_value' => '', +'confirm_rm_attr_value' => 'Bevestigen...', 'confirm_rm_backup' => 'Weet U zeker dat U het bestand "[arkname]" wilt verwijderen?
Let op: deze handeling kan niet ongedaan worden gemaakt.', 'confirm_rm_document' => 'Weet U zeker dat U het document \'[documentname]\' wilt verwijderen?
Pas op: deze handeling kan niet ongedaan worden gemaakt.', 'confirm_rm_dump' => 'Weet U zeker dat U het bestand "[dumpname]" wilt verwijderen?
Let op: deze handeling kan niet ongedaan worden gemaakt.', @@ -330,7 +331,7 @@ URL: [url]', 'documents_locked_by_you' => 'Documenten door U geblokkeerd', 'documents_only' => 'Alleen documenten', 'documents_to_approve' => 'Documenten die wachten op uw goedkeuring', -'documents_to_correct' => '', +'documents_to_correct' => 'Te corrigeren documenten', 'documents_to_process' => 'Te verwerken documenten', 'documents_to_receipt' => 'documenten te ontvangen', 'documents_to_review' => 'Documenten die wachten op uw controle', @@ -413,7 +414,7 @@ URL: [url]', 'does_not_expire' => 'Verloopt niet', 'does_not_inherit_access_msg' => 'Erft toegang', 'download' => 'Download', -'download_extension' => '', +'download_extension' => 'Download extensie als zip file', 'download_links' => 'Download-links', 'download_link_email_body' => 'Klik op de link hieronder, dan begint de download vanvversie [version] van het document \'[docname]\'. @@ -460,7 +461,7 @@ De link is geldig tot [valid]. 'edit_folder_props' => 'Wijzig Map eigenschappen', 'edit_group' => 'Wijzig Groep', 'edit_online' => 'Online bewerken', -'edit_task' => '', +'edit_task' => 'Taak bewerken', 'edit_transmittal_props' => 'Opmerkingen bij verzending', 'edit_user' => 'Wijzig gebruiker', 'edit_user_details' => 'Wijzig gebruiker Details', @@ -473,7 +474,7 @@ De link is geldig tot [valid]. 'email_not_given' => 'Voer aub een geldig email adres in.', 'empty_attribute_group_list' => 'Lege lijst van attributen', 'empty_folder_list' => 'Geen documenten of mappen', -'empty_list' => '', +'empty_list' => 'Lijst is leeg', 'empty_notify_list' => 'Geen gegevens', 'en_GB' => 'Engels (GB)', 'equal_transition_states' => 'Begin- en eind-status zijn hetzelfde', @@ -481,6 +482,7 @@ De link is geldig tot [valid]. 'error_add_aro' => 'Verzoek om toegang toegevoegd', 'error_add_permission' => 'Voeg permissie toe', 'error_cleared_cache' => 'Fout bij het leegmaken van de cache', +'error_edit_task' => '', 'error_extension_getlist' => '', 'error_importfs' => 'Fout bij het importeren van form file systeem', 'error_no_document_selected' => 'Geen document geselecteerd', @@ -489,8 +491,12 @@ De link is geldig tot [valid]. 'error_remove_document' => 'Fout bij het verwijderen van document', 'error_remove_folder' => 'Fout bij het verwijderen van map', 'error_remove_permission' => 'Verwijder permissie', +'error_rm_workflow' => '', +'error_rm_workflow_action' => '', +'error_rm_workflow_state' => '', 'error_toogle_permission' => 'Wijzig permissie', 'error_transfer_document' => '', +'error_trigger_workflow' => '', 'error_update_document' => '', 'error_uploading_reviewer_only' => '', 'es_ES' => 'Spaans', @@ -587,7 +593,7 @@ URL: [url]', 'fulltext_converters' => 'Index document conversie', 'fulltext_info' => 'Volledige tekst index info', 'global_attributedefinitiongroups' => 'Kennmerk-definitie groepen', -'global_attributedefinitions' => 'Kenmerk definities', +'global_attributedefinitions' => 'Kenmerkdefinities', 'global_default_keywords' => 'Algemene sleutelwoorden', 'global_document_categories' => 'Categorieën', 'global_workflows' => 'Workflows', @@ -598,7 +604,7 @@ URL: [url]', 'group_approval_summary' => 'Groep [Goedkeuring] samenvatting', 'group_exists' => 'Groep bestaat reeds.', 'group_info' => 'Info over de groep', -'group_management' => 'Groepen beheer', +'group_management' => 'Groepenbeheer', 'group_members' => 'Groepsleden', 'group_receipt_summary' => 'Overzicht van ontvangst per groep', 'group_review_summary' => 'Groep Beoordeling samenvatting', @@ -633,7 +639,6 @@ URL: [url]', 'index_waiting' => 'Indexering wacht', 'individuals' => 'Individuen', 'individuals_in_groups' => 'Individuen in groepen', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => '', 'inherited' => 'overgeerfd', 'inherits_access_copy_msg' => 'Kopie lijst overerfde toegang', @@ -726,9 +731,11 @@ URL: [url]', 'login_error_title' => 'Login fout', 'login_not_given' => 'Er is geen Gebruikersnaam ingevoerd', 'login_ok' => 'Login geslaagd', +'login_restrictions_apply' => '', 'logout' => 'Log uit', 'log_management' => 'Logbestanden beheer', 'lo_LA' => 'Laotiaans', +'malformed_expiration_date' => '', 'manager' => 'Beheerder', 'manager_of_group' => 'U bent beheerder van deze groep', 'mandatory_approvergroups' => 'Verplichte groep \'[group]\'', @@ -743,6 +750,7 @@ URL: [url]', 'max_upload_size' => 'Maximale upload omvang voor ieder bestand', 'may' => 'mei', 'menu_dropfolder' => 'Dropfolder', +'menu_upload_from_dropfolder' => '', 'mimetype' => 'MIME Type', 'minutes' => 'minuten', 'misc' => 'Diversen', @@ -770,7 +778,7 @@ URL: [url]', 'network_drive' => 'Networkdrive', 'never' => 'Nooit', 'new' => 'Nieuw', -'new_attrdef' => 'Voeg kenmerk definitie toe', +'new_attrdef' => 'Voeg een kenmerkdefinitie toe', 'new_default_keywords' => 'Sleutelwoorden toevoegen', 'new_default_keyword_category' => 'Categorie Toevoegen', 'new_document_category' => 'Categorie toevoegen', @@ -896,7 +904,7 @@ Mocht u de komende minuten geen email ontvangen, probeer het dan nogmaals en con 'password_strength' => 'Sterkte wachtwoord', 'password_strength_insuffient' => 'Onvoldoende sterk wachtwoord', 'password_wrong' => 'Verkeerd wachtwoord', -'pdf_converters' => '', +'pdf_converters' => 'PDF converters', 'pending_approvals' => 'Wachten op goedkeuring', 'pending_receipt' => 'Wachten op ontvangs', 'pending_reviews' => 'Wachten op beoordeling', @@ -910,7 +918,7 @@ Mocht u de komende minuten geen email ontvangen, probeer het dan nogmaals en con 'preview_converters' => 'Converters', 'preview_images' => 'Voorbeelden', 'preview_markdown' => 'Voorbeeld in Markdown', -'preview_pdf' => '', +'preview_pdf' => 'Beeld vd PDF', 'preview_plain' => 'Voorbeeld in platte tekst', 'previous_state' => 'Vorige staat', 'previous_versions' => 'Vorige versies', @@ -1189,8 +1197,10 @@ Name: [username] 'settings_Advanced' => 'Uitgebreid', 'settings_advancedAcl' => 'Advanced Access control', 'settings_advancedAcl_desc' => 'Advanced Access control staat het uit- en inschakelen van bepaalde modules toe. Het kan niet gebruikt worden voor het beheer van toegangsrechten van documenten en mappen.', -'settings_allowReviewerOnly' => '', -'settings_allowReviewerOnly_desc' => '', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', +'settings_allowReviewerOnly' => 'Alleen reviewer toestaan', +'settings_allowReviewerOnly_desc' => 'Aanzetten als wel de reviewe, maar niet de goedkeurder toegewezen kan worden.', 'settings_apache_mod_rewrite' => 'Apache - Module Rewrite', 'settings_Authentication' => 'Authenticatie instellingen', 'settings_autoLoginUser' => 'Automatische login', @@ -1342,8 +1352,10 @@ Name: [username] 'settings_enableVersionDeletion_desc' => 'Inschakelen/uitschakelen verwijderen van voorgaande documentversies door normale gebruikers. Beheerder mag altijd oude versies verwijderen.', 'settings_enableVersionModification' => 'Inschakelen van versiebewerking', 'settings_enableVersionModification_desc' => 'Inschakelen/uitschakelen van bewerkingen op documentversies door normale gebruikers na een versie upload. Beheerder mag altijd de versie wijzigen na upload.', -'settings_enableWebdavReplaceDoc' => '', +'settings_enableWebdavReplaceDoc' => 'Oud document vervangen bij opslaan', 'settings_enableWebdavReplaceDoc_desc' => '', +'settings_enableXsendfile' => '', +'settings_enableXsendfile_desc' => '', 'settings_encryptionKey' => 'Encryptie sleutel', 'settings_encryptionKey_desc' => 'Deze string wordt gebruikt om een unieke identificatie als onzichtbaar veld aan een formulier toe te voegen om CSRF aanvallen tegen te gaan.', 'settings_error' => 'Fout', @@ -1367,7 +1379,7 @@ Name: [username] 'settings_guestID_desc' => 'ID van gastgebruiker gebruikt indien ingelogd als gast (meestal geen wijziging nodig)', 'settings_httpRoot' => 'Http Basis', 'settings_httpRoot_desc' => 'Het relatieve pad in de URL, na het domeindeel. Voeg geen http:// toe aan het begin of de websysteemnaam. Bijv: Als de volledige URL http://www.example.com/letodms/ is, voer \'/letodms/\' in. Als de URL http://www.example.com/ is, voer \'/\' in', -'settings_incItemsPerPage' => '', +'settings_incItemsPerPage' => 'Aantal items ,geladen aan einde pagina', 'settings_incItemsPerPage_desc' => '', 'settings_initialDocumentStatus' => 'Beginstatus document', 'settings_initialDocumentStatus_desc' => 'De beginstatus van een document wordt ingesteld wanneer het document wordt toegevoegd.', @@ -1399,7 +1411,7 @@ Name: [username] 'settings_maxDirID_desc' => 'Maximaal toegestane aantal submappen per bovenliggende map. Standaard: 0.', 'settings_maxExecutionTime' => 'Max Uitvoertijd (s)', 'settings_maxExecutionTime_desc' => 'Dit bepaald de maximale tijd in seconden waarin een script mag worden uitgevoerd, voordat het afgebroken wordt', -'settings_maxItemsPerPage' => '', +'settings_maxItemsPerPage' => 'Max aantal items per pagina', 'settings_maxItemsPerPage_desc' => '', 'settings_maxRecursiveCount' => 'Max. nummers of recursieve document/map telling', 'settings_maxRecursiveCount_desc' => 'Dit is het maximum aantal documenten of mappen dat zal worden gecontroleerd voor toegangsrechten bij recursieve objecten telling. Als dit aantal is overschreden, zal het aantal documenten en mappen in de het map overzicht worden geschat.', @@ -1420,9 +1432,9 @@ Name: [username] 'settings_passwordExpiration_desc' => 'Het aantal dagen waarna een wachtwoord verloopt? en gereset moet worden. 0 zet het verlopen van het wachtwoord uit.', 'settings_passwordHistory' => 'Wachtwoord geschiedenis', 'settings_passwordHistory_desc' => 'Het aantal wachtwoorden dat een gebruiker moet hebben gebruikt voordat eenzelfde wachtwoord weer gebruikt mag worden. 0 zet wachtwoordgeschiedenis uit.', -'settings_passwordStrength' => 'Min. wachtwoord sterkte', -'settings_passwordStrengthAlgorithm' => 'Algoritme voor wachtwoord sterkte', -'settings_passwordStrengthAlgorithm_desc' => 'Het algoritme gebruikt om de wachtwoord sterkte te berekenen. Het \'simpele\' algoritme controleert alleen op minimaal 8 karakters, een kleine letter, een nummer en een speciaal karakter. Als aan deze condities wordt voldaan is er een resultaat van 100 anders 0.', +'settings_passwordStrength' => 'Min. wachtwoordsterkte', +'settings_passwordStrengthAlgorithm' => 'Algoritme voor wachtwoordsterkte', +'settings_passwordStrengthAlgorithm_desc' => 'Het algoritme gebruikt om de wachtwoordsterkte te berekenen. Het \'simpele\' algoritme controleert alleen op minimaal 8 karakters, een kleine letter, een nummer en een speciaal karakter. Als aan deze condities wordt voldaan is er een resultaat van 100 anders 0.', 'settings_passwordStrengthAlgorithm_valadvanced' => 'uitgebreid', 'settings_passwordStrengthAlgorithm_valsimple' => 'simpel', 'settings_passwordStrength_desc' => 'De sterkte van het wachtwoord is valide van 0 tot 100. Het op 0 zetten zal de controle voor de minimale wachtwoordsterkte uitschakelen.', @@ -1436,20 +1448,20 @@ Name: [username] 'settings_presetExpirationDate' => 'Verloopdatum', 'settings_presetExpirationDate_desc' => 'Alle nieuw geüploade documenten krijgen een verloopdatum toegekend. U kunt ook een datum invoeren overeenkomstig PHP\'s strtotime() function, e.g. +5 weeks.', 'settings_previewWidthDetail' => 'Breedte van het voorbeeld (detail)', -'settings_previewWidthDetail_desc' => 'Breedte van het voorbeeld weergegeven op de detail pagina', -'settings_previewWidthDropFolderList' => '', +'settings_previewWidthDetail_desc' => 'weergegeven op de detail pagina', +'settings_previewWidthDropFolderList' => 'Breedte van het voorbeeld in de dropfolder-lijst', 'settings_previewWidthDropFolderList_desc' => '', 'settings_previewWidthList' => 'Breedte van het voorbeeld (lijst)', 'settings_previewWidthList_desc' => 'Breedte van het voorbeeld weergegeven in lijsten', -'settings_previewWidthMenuList' => '', -'settings_previewWidthMenuList_desc' => '', +'settings_previewWidthMenuList' => 'Breedte van het voorbeeld (menu-lijst)', +'settings_previewWidthMenuList_desc' => 'Breedte van het voorbeeld als dropfolder', 'settings_printDisclaimer' => 'Vrijwaring afdrukken', 'settings_printDisclaimer_desc' => 'Indien ingeschakeld zal het vrijwaringsbericht bestanden worden getoond onderaan de pagina', 'settings_quota' => 'Gebruikersquotum', 'settings_quota_desc' => 'Het maximum aantal bytes een gebruiker op de schijf mag schrijven. Stel deze in op 0 voor een onbeperkte schijfruimte. Deze waarde kan worden overschreven voor elk gebruik in zijn profiel.', 'settings_removeFromDropFolder' => 'Verwijder het bestand uit de dropfolder na een succesvolle upload', 'settings_removeFromDropFolder_desc' => 'Verwijder het bestand uit de dropfolder na een succesvolle upload', -'settings_repositoryUrl' => '', +'settings_repositoryUrl' => 'URL van repository', 'settings_repositoryUrl_desc' => '', 'settings_restricted' => 'Beperkte toegang', 'settings_restricted_desc' => 'Sta alleen gebruiker toe om in te loggen die in de database zijn opgenomen (ongeacht succesvolle authenticatie met LDAP)', @@ -1465,19 +1477,19 @@ Name: [username] 'settings_showMissingTranslations_desc' => 'Geef alle ontbrekende vertalingen onder aan de pagina weer. De gebruiker kan een verzoek tot vertaling indienen dat wordt opgeslagen als csv bestand. Let op! Zet deze functie niet aan in productieomgevingen!', 'settings_showSingleSearchHit' => 'Spring rechtstreeks naar het enkele zoekresultaat', 'settings_showSingleSearchHit_desc' => 'Als er maar één zoekresultaat is, wordt dat in detail getoond.', -'settings_Site' => 'Web Locatie', +'settings_Site' => 'WebLocatie', 'settings_siteDefaultPage' => 'Locatie standaardpagina', 'settings_siteDefaultPage_desc' => 'Standaardpagina bij inloggen. Indien leeg is out/out.ViewFolder.php de standaard', 'settings_siteName' => 'Naam van de site', 'settings_siteName_desc' => 'Naam van de Locatie dat wordt gebruikt in de titel van de paginas. Standaard: letoDMS', 'settings_SMTP' => 'SMTP Server instellingen', -'settings_smtpPassword' => 'SMTP Server paswoord', -'settings_smtpPassword_desc' => 'SMTP Server paswoord', +'settings_smtpPassword' => 'SMTP Server wachtwoord', +'settings_smtpPassword_desc' => 'SMTP Server wachtwoord', 'settings_smtpPort' => 'SMTP Server poort', 'settings_smtpPort_desc' => 'SMTP Server poort, standaard 25', 'settings_smtpSendFrom' => 'Send from', 'settings_smtpSendFrom_desc' => 'Send from', -'settings_smtpSendTestMail' => '', +'settings_smtpSendTestMail' => 'Testmail versturen', 'settings_smtpSendTestMail_desc' => '', 'settings_smtpServer' => 'SMTP Server hostname', 'settings_smtpServer_desc' => 'SMTP Server hostname', @@ -1495,7 +1507,7 @@ Name: [username] 'settings_stagingDir' => 'Map voor gedeeltelijke uploads', 'settings_stagingDir_desc' => 'De directory waar jumploader de delen van een bestand upload voordat het weer in elkaar wordt gezet.', 'settings_start_install' => 'Begin installatie', -'settings_stopWordsFile' => 'Pad naar bestand met nietindex woorden', +'settings_stopWordsFile' => 'Pad naar bestand met niet-index woorden', 'settings_stopWordsFile_desc' => 'Als volledigetekst zoekopdracht is ingeschakeld, bevat dit bestand woorden die niet geindexeerd zullen worden.', 'settings_strictFormCheck' => 'Strikte formaatcontrole', 'settings_strictFormCheck_desc' => 'Strikte controle op het juiste formaat. Indien ingeschakeld, worden alle velden in het formulier gecontroleer op een waarde. Indien uitgeschakeld, worden de meeste commentaar en invoervelden opgevat als optioneel. Commentaren zijn altijd nodig bij een review of modificatie van een documentstatus', @@ -1519,12 +1531,12 @@ Name: [username] 'settings_updateNotifyTime' => 'Update Notificatie Tijd', 'settings_updateNotifyTime_desc' => 'Gebruikers worden niet genotificeerd over documentwijzigingen die plaats vinden binnen de laatste \'Update Notificatie Tijd\' seconden', 'settings_upgrade_php' => 'Upgrade PHP minimaal naar versie 5.2.0', -'settings_versioningFileName' => 'Versieinformatie Bestandsnaam', +'settings_versioningFileName' => 'Versie-informatie Bestandsnaam', 'settings_versioningFileName_desc' => 'De naam van het versie informatie bestand gemaakt door het backupgereedschap', 'settings_versiontolow' => 'Versie te laag', 'settings_viewOnlineFileTypes' => 'De volgende bestandstypen online bekijken', 'settings_viewOnlineFileTypes_desc' => 'Bestanden met een van de volgende extensies kunnen online bekeken worden (GEBRUIK ALLEEN KLEINE LETTERS)', -'settings_webdav' => '', +'settings_webdav' => 'Instellingen WebDav', 'settings_workflowMode' => 'Workflow mode', 'settings_workflowMode_desc' => 'De uitgebreide workflow maakt het mogelijk om uw eigen workflow op te geven voor documentversies.', 'settings_workflowMode_valadvanced' => 'geavanceerd', @@ -1536,7 +1548,7 @@ Name: [username] 'set_owner_error' => 'Fout bij instellen eigenaar', 'set_password' => 'Stel wachtwoord in', 'set_workflow' => 'Stel workflow in', -'show_extension_changelog' => '', +'show_extension_changelog' => 'Toon wijzigingslog', 'show_extension_version_list' => 'Toon lijst met versies', 'signed_in_as' => 'Ingelogd als:', 'sign_in' => 'Log in', @@ -1567,6 +1579,7 @@ Name: [username] 'splash_edit_event' => 'Gebeurtenis opgeslagen', 'splash_edit_group' => 'Groep opgeslagen', 'splash_edit_role' => 'Rol opgeslagen', +'splash_edit_task' => '', 'splash_edit_user' => 'Gebruiker opgeslagen', 'splash_error_add_to_transmittal' => 'Fout: toevoeging aan verzending', 'splash_error_rm_download_link' => 'Fout bij verwijderen download-link', @@ -1597,6 +1610,9 @@ Name: [username] 'splash_rm_transmittal' => 'Verzending verwijderd', 'splash_rm_user' => 'Gebruiker verwijderd', 'splash_rm_user_processes' => 'Gebruiker uit alle processen verwijderd', +'splash_rm_workflow' => '', +'splash_rm_workflow_action' => '', +'splash_rm_workflow_state' => '', 'splash_saved_file' => 'Bestand opgeslagen', 'splash_save_user_data' => 'Gebruikersgegevens opgeslagen', 'splash_send_download_link' => 'Download-link verzonden', @@ -1609,6 +1625,7 @@ Name: [username] 'splash_toogle_group_manager' => 'Group manager toogled', 'splash_transfer_document' => '', 'splash_transfer_objects' => 'Objecten overgedragen', +'splash_trigger_workflow' => '', 'state_and_next_state' => 'staat/ volgende staat', 'statistic' => 'Statistieken', 'status' => 'Status', @@ -1696,10 +1713,10 @@ Name: [username] 'to_before_from' => 'De einddatum mag niet voor de startdatum liggen', 'transfer_document' => 'Document overdragen', 'transfer_no_read_access' => '', -'transfer_no_write_access' => '', +'transfer_no_write_access' => 'De gebruiker heeft geen schrijfrechten in deze map', 'transfer_objects' => 'Objecten overdragen', 'transfer_objects_to_user' => 'Objecten overdragen aan gebruiker', -'transfer_to_user' => '', +'transfer_to_user' => 'Overdragen aan gebruiker', 'transition_triggered_email' => 'Workflow-overgang geactiveerd', 'transition_triggered_email_body' => 'Workflow Overgang Document: [name] @@ -1764,12 +1781,12 @@ URL: [url]', 'users_done_work' => 'Uitgevoerd werk gebruikers', 'user_exists' => 'Gebruiker bestaat reeds.', 'user_group' => 'Gebruiker / Groep', -'user_group_management' => 'Gebruikers / Groepen beheer', +'user_group_management' => 'Gebruikers / Groepenbeheer', 'user_image' => 'Afbeelding', 'user_info' => 'Gebruikers informatie', 'user_list' => 'Lijst van Gebruikers', 'user_login' => 'Gebruikersnaam', -'user_management' => 'Gebruikers beheer', +'user_management' => 'Gebruikersbeheer', 'user_name' => 'Voornaam en naam', 'use_comment_of_document' => 'Gebruik reactie van document', 'use_default_categories' => 'Gebruik voorgedefinieerde categorieen', @@ -1793,7 +1810,7 @@ URL: [url]', 'view_online' => 'Bekijk online', 'warning' => 'Waarschuwing', 'wednesday' => 'Woensdag', -'wednesday_abbr' => 'We', +'wednesday_abbr' => 'Woe', 'weeks' => 'Weken', 'week_view' => 'Week Overzicht', 'workflow' => 'Workflow', diff --git a/languages/pl_PL/lang.inc b/languages/pl_PL/lang.inc index 90d91c319..31cad25b9 100644 --- a/languages/pl_PL/lang.inc +++ b/languages/pl_PL/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (820), netixw (84), romi (93), uGn (112) +// Translators: Admin (830), netixw (84), romi (93), uGn (112) $text = array( '2_factor_auth' => '', @@ -186,6 +186,7 @@ URL: [url]', 'at_least_n_users_of_group' => 'Przynajmniej [number_of_users] użytkowników grupy [group]', 'august' => 'Sierpień', 'authentication' => 'Autoryzacja', +'authentication_failed' => '', 'author' => 'Autor', 'automatic_status_update' => 'Automatyczna zmiana statusu', 'back' => 'Powrót', @@ -261,7 +262,7 @@ URL: [url]', 'comment' => 'Opis', 'comment_changed_email' => '', 'comment_for_current_version' => 'Komentarz do wersji', -'configure_extension' => '', +'configure_extension' => 'Konfiguruj rozszerzenie', 'confirm_clear_cache' => '', 'confirm_create_fulltext_index' => 'Tak, chcę ponownie utworzyć indeks pełnotekstowy!', 'confirm_move_document' => '', @@ -408,7 +409,7 @@ URL: [url]', 'does_not_expire' => 'Nigdy nie wygasa', 'does_not_inherit_access_msg' => 'Dziedzicz dostęp', 'download' => 'Pobierz', -'download_extension' => '', +'download_extension' => 'Pobierz rozszerzenie w pliku zip', 'download_links' => '', 'download_link_email_body' => '', 'download_link_email_subject' => '', @@ -469,6 +470,7 @@ URL: [url]', 'error_add_aro' => '', 'error_add_permission' => '', 'error_cleared_cache' => '', +'error_edit_task' => '', 'error_extension_getlist' => '', 'error_importfs' => '', 'error_no_document_selected' => 'Brak wybranych dokumentów', @@ -477,13 +479,17 @@ URL: [url]', 'error_remove_document' => '', 'error_remove_folder' => '', 'error_remove_permission' => '', +'error_rm_workflow' => '', +'error_rm_workflow_action' => '', +'error_rm_workflow_state' => '', 'error_toogle_permission' => '', 'error_transfer_document' => '', +'error_trigger_workflow' => '', 'error_update_document' => '', 'error_uploading_reviewer_only' => '', 'es_ES' => 'Hiszpański', 'event_details' => 'Szczegóły zdarzenia', -'exclude_items' => '', +'exclude_items' => 'Pozycje wykluczone', 'expired' => 'Wygasłe', 'expired_at_date' => '', 'expired_documents' => '', @@ -621,7 +627,6 @@ URL: [url]', 'index_waiting' => 'Oczekiwanie', 'individuals' => 'Indywidualni', 'individuals_in_groups' => '', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => '', 'inherited' => 'dziedziczony', 'inherits_access_copy_msg' => 'Kopiuj odziedziczoną listę dostępu', @@ -693,8 +698,8 @@ URL: [url]', 'librarydoc' => '', 'linked_documents' => 'Powiązane dokumenty', 'linked_files' => 'Załączniki', -'linked_to_current_version' => '', -'linked_to_document' => '', +'linked_to_current_version' => 'Link do obecnej wersji', +'linked_to_document' => 'Połączony z dokumentem', 'linked_to_this_version' => '', 'link_alt_updatedocument' => 'Jeśli chcesz wczytać pliki większe niż bieżące maksimum, użyj alternatywnej strony wczytywania.', 'link_to_version' => '', @@ -714,9 +719,11 @@ URL: [url]', 'login_error_title' => 'Błąd logowania', 'login_not_given' => 'Nie podano nazwy użytkownika', 'login_ok' => 'Zalogowano', +'login_restrictions_apply' => '', 'logout' => 'Wyloguj', 'log_management' => 'Zarządzanie plikami dziennika', 'lo_LA' => 'Laotański', +'malformed_expiration_date' => '', 'manager' => 'Zarządca', 'manager_of_group' => '', 'mandatory_approvergroups' => '', @@ -731,6 +738,7 @@ URL: [url]', 'max_upload_size' => 'Maksymalny rozmiar pliku', 'may' => 'Maj', 'menu_dropfolder' => '', +'menu_upload_from_dropfolder' => '', 'mimetype' => 'Typ mime', 'minutes' => 'minut', 'misc' => 'Różne', @@ -1127,6 +1135,8 @@ URL: [url]', 'settings_Advanced' => 'Zaawansowane', 'settings_advancedAcl' => '', 'settings_advancedAcl_desc' => '', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', 'settings_allowReviewerOnly' => '', 'settings_allowReviewerOnly_desc' => '', 'settings_apache_mod_rewrite' => 'Apache - Moduł Rewrite', @@ -1278,6 +1288,8 @@ URL: [url]', 'settings_enableVersionModification_desc' => 'Włącz/Wyłącz możliwość modyfikacji wersji dokumentów przez zwykłych użytkowników po wczytaniu pliku. Administrator może w każdej chwili zmienić wersję wczytanego pliku.', 'settings_enableWebdavReplaceDoc' => '', 'settings_enableWebdavReplaceDoc_desc' => '', +'settings_enableXsendfile' => '', +'settings_enableXsendfile_desc' => '', 'settings_encryptionKey' => 'Klucz szyfrujący', 'settings_encryptionKey_desc' => 'Ten ciąg znaków jest używany do tworzenia unikatowego identyfikatora dodawanego jako ukryte pole do formularza aby zapobiec atakom CSRF.', 'settings_error' => 'Błąd', @@ -1470,7 +1482,7 @@ URL: [url]', 'set_owner_error' => 'Błąd podczas ustawiania właściciela', 'set_password' => 'Zmień hasło', 'set_workflow' => 'Ustaw proces', -'show_extension_changelog' => '', +'show_extension_changelog' => 'Pokaż Changelog', 'show_extension_version_list' => 'Pokaż listę wersji', 'signed_in_as' => 'Zalogowany jako', 'sign_in' => 'Zaloguj się', @@ -1501,6 +1513,7 @@ URL: [url]', 'splash_edit_event' => '', 'splash_edit_group' => 'Grupa zapisana', 'splash_edit_role' => '', +'splash_edit_task' => '', 'splash_edit_user' => 'Zapisano użytkownika', 'splash_error_add_to_transmittal' => '', 'splash_error_rm_download_link' => '', @@ -1531,6 +1544,9 @@ URL: [url]', 'splash_rm_transmittal' => '', 'splash_rm_user' => 'Użytkownika usunięto', 'splash_rm_user_processes' => '', +'splash_rm_workflow' => '', +'splash_rm_workflow_action' => '', +'splash_rm_workflow_state' => '', 'splash_saved_file' => '', 'splash_save_user_data' => '', 'splash_send_download_link' => '', @@ -1543,6 +1559,7 @@ URL: [url]', 'splash_toogle_group_manager' => 'Przełączono grupę menadżerów', 'splash_transfer_document' => '', 'splash_transfer_objects' => '', +'splash_trigger_workflow' => '', 'state_and_next_state' => 'Status/Następny status', 'statistic' => 'Statystyka', 'status' => 'Status', @@ -1619,7 +1636,7 @@ URL: [url]', 'timeline_skip_status_change_-3' => 'przedawniony', 'timeline_skip_status_change_0' => 'oczekuje na opinię', 'timeline_skip_status_change_1' => 'oczekuje na zatwierdzenie', -'timeline_skip_status_change_2' => '', +'timeline_skip_status_change_2' => 'wydany', 'timeline_skip_status_change_3' => 'w obiegu', 'timeline_skip_status_change_4' => '', 'timeline_skip_status_change_5' => '', @@ -1629,11 +1646,11 @@ URL: [url]', 'toggle_qrcode' => '', 'to_before_from' => '', 'transfer_document' => 'Transfer dokumentu', -'transfer_no_read_access' => '', -'transfer_no_write_access' => '', +'transfer_no_read_access' => 'Użytkownik nie ma prawa do odczytu w tym folderze', +'transfer_no_write_access' => 'Użytkownik nie ma prawa do zapisu w tym folderze', 'transfer_objects' => '', 'transfer_objects_to_user' => '', -'transfer_to_user' => '', +'transfer_to_user' => 'Przekaż użytkownikowi', 'transition_triggered_email' => 'Uruchomiono proces przepływu', 'transition_triggered_email_body' => 'Uruchomiono proces przepływu Dokument: [name] diff --git a/languages/pt_BR/lang.inc b/languages/pt_BR/lang.inc index 94c06b4d5..2d020901e 100644 --- a/languages/pt_BR/lang.inc +++ b/languages/pt_BR/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (1001), flaviove (627), lfcristofoli (352) +// Translators: Admin (1006), flaviove (627), lfcristofoli (352) $text = array( '2_factor_auth' => '', @@ -193,6 +193,7 @@ URL: [url]', 'at_least_n_users_of_group' => 'Pelo menos [nuber_of_users] usuários de [group]', 'august' => 'August', 'authentication' => 'Autenticação', +'authentication_failed' => '', 'author' => 'Autor', 'automatic_status_update' => 'Mudança de status automático', 'back' => 'Voltar', @@ -268,7 +269,7 @@ URL: [url]', 'comment' => 'Comentário', 'comment_changed_email' => '', 'comment_for_current_version' => 'Comentário para versão atual', -'configure_extension' => '', +'configure_extension' => 'Configurar extensão', 'confirm_clear_cache' => 'Você realmente gostaria de limpar o cache? Isso removerá todas as imagens de pré-visualização.', 'confirm_create_fulltext_index' => 'Sim, eu gostaria de recriar o índice de texto completo!', 'confirm_move_document' => '', @@ -414,7 +415,7 @@ URL: [url]', 'does_not_expire' => 'não Expira', 'does_not_inherit_access_msg' => 'Inherit access', 'download' => 'Download', -'download_extension' => '', +'download_extension' => 'Baixar extensão como arquivo zip', 'download_links' => '', 'download_link_email_body' => '', 'download_link_email_subject' => '', @@ -475,6 +476,7 @@ URL: [url]', 'error_add_aro' => '', 'error_add_permission' => '', 'error_cleared_cache' => '', +'error_edit_task' => '', 'error_extension_getlist' => '', 'error_importfs' => '', 'error_no_document_selected' => 'Nenhum documento selecionado', @@ -483,10 +485,14 @@ URL: [url]', 'error_remove_document' => '', 'error_remove_folder' => 'Erro na exclusão da pasta', 'error_remove_permission' => '', +'error_rm_workflow' => '', +'error_rm_workflow_action' => '', +'error_rm_workflow_state' => '', 'error_toogle_permission' => '', 'error_transfer_document' => '', +'error_trigger_workflow' => '', 'error_update_document' => '', -'error_uploading_reviewer_only' => '', +'error_uploading_reviewer_only' => 'Erro ao criar o documento. O documento tem um revisor, mas não tem um aprovador', 'es_ES' => 'Espanhol', 'event_details' => 'Event details', 'exclude_items' => 'Excluir ítens', @@ -627,7 +633,6 @@ URL: [url]', 'index_waiting' => 'Aguarde...', 'individuals' => 'Individuals', 'individuals_in_groups' => '', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => '', 'inherited' => 'herdado', 'inherits_access_copy_msg' => 'Copy inherited access list', @@ -720,9 +725,11 @@ URL: [url]', 'login_error_title' => 'Erro de Login', 'login_not_given' => 'No username has been supplied', 'login_ok' => 'Logado com sucesso', +'login_restrictions_apply' => '', 'logout' => 'Sair', 'log_management' => 'Gerenciamento de Logs', 'lo_LA' => 'Laoiano', +'malformed_expiration_date' => '', 'manager' => 'Manager', 'manager_of_group' => 'Você é o gerente deste grupo', 'mandatory_approvergroups' => 'Grupos obrigatórios de aprovadores', @@ -737,6 +744,7 @@ URL: [url]', 'max_upload_size' => 'Tamanho máximo de arquivo para upload', 'may' => 'May', 'menu_dropfolder' => '', +'menu_upload_from_dropfolder' => '', 'mimetype' => 'Tipo mime', 'minutes' => 'minutos', 'misc' => 'Miscelânia', @@ -889,7 +897,7 @@ Se você ainda tiver problemas para fazer o login, por favor, contate o administ 'password_strength' => 'Força da senha', 'password_strength_insuffient' => 'A força da senha é insuficiente', 'password_wrong' => 'Senha errada', -'pdf_converters' => '', +'pdf_converters' => 'Conversores de PDF', 'pending_approvals' => '', 'pending_receipt' => '', 'pending_reviews' => '', @@ -1145,6 +1153,8 @@ URL: [url]', 'settings_Advanced' => 'Avançado', 'settings_advancedAcl' => '', 'settings_advancedAcl_desc' => '', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', 'settings_allowReviewerOnly' => '', 'settings_allowReviewerOnly_desc' => '', 'settings_apache_mod_rewrite' => 'Apache - Módulo Rewrite', @@ -1296,6 +1306,8 @@ URL: [url]', 'settings_enableVersionModification_desc' => 'Ativar/desativar a modificação de versões de documentos por usuários comuns, depois que uma versão foi enviada. Administrador pode sempre modificar a versão após o upload.', 'settings_enableWebdavReplaceDoc' => '', 'settings_enableWebdavReplaceDoc_desc' => '', +'settings_enableXsendfile' => '', +'settings_enableXsendfile_desc' => '', 'settings_encryptionKey' => 'Chave de criptografia', 'settings_encryptionKey_desc' => 'Esta cadeia é usada para a criação de um identificador único a ser adicionado como um campo oculto para formular, a fim de evitar ataques CSRF.', 'settings_error' => 'Erro', @@ -1488,7 +1500,7 @@ URL: [url]', 'set_owner_error' => 'Proprietário configuração de erro', 'set_password' => 'Definir Senha', 'set_workflow' => 'Definir fluxo de trabalho', -'show_extension_changelog' => '', +'show_extension_changelog' => 'Mostrar Changelog', 'show_extension_version_list' => 'Exibir Lista de Versões', 'signed_in_as' => 'Logado como', 'sign_in' => 'Entrar', @@ -1519,6 +1531,7 @@ URL: [url]', 'splash_edit_event' => '', 'splash_edit_group' => 'Grupo salvo', 'splash_edit_role' => '', +'splash_edit_task' => '', 'splash_edit_user' => 'Usuário salvo', 'splash_error_add_to_transmittal' => '', 'splash_error_rm_download_link' => '', @@ -1549,6 +1562,9 @@ URL: [url]', 'splash_rm_transmittal' => '', 'splash_rm_user' => 'Usuário removido', 'splash_rm_user_processes' => '', +'splash_rm_workflow' => '', +'splash_rm_workflow_action' => '', +'splash_rm_workflow_state' => '', 'splash_saved_file' => '', 'splash_save_user_data' => '', 'splash_send_download_link' => '', @@ -1561,6 +1577,7 @@ URL: [url]', 'splash_toogle_group_manager' => 'Gerente Grupo alternado', 'splash_transfer_document' => '', 'splash_transfer_objects' => '', +'splash_trigger_workflow' => '', 'state_and_next_state' => 'Estado/Próximo estado', 'statistic' => 'Estatística', 'status' => 'Status', diff --git a/languages/ro_RO/lang.inc b/languages/ro_RO/lang.inc index 04e8e00bb..44c80298b 100644 --- a/languages/ro_RO/lang.inc +++ b/languages/ro_RO/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (1073), balan (87) +// Translators: Admin (1082), balan (87) $text = array( '2_factor_auth' => '', @@ -198,6 +198,7 @@ URL: [url]', 'at_least_n_users_of_group' => 'Cel puțin [number_of_users] utilizatori in [group]', 'august' => 'August', 'authentication' => 'Autentificare', +'authentication_failed' => '', 'author' => 'Autor', 'automatic_status_update' => 'Schimbarea automata a statusului', 'back' => 'Inapoi', @@ -420,7 +421,7 @@ URL: [url]', 'does_not_expire' => 'Nu expiră', 'does_not_inherit_access_msg' => 'Acces moștenit', 'download' => 'Descarca', -'download_extension' => '', +'download_extension' => 'Descarca extensia ca fisier zip', 'download_links' => '', 'download_link_email_body' => '', 'download_link_email_subject' => '', @@ -481,6 +482,7 @@ URL: [url]', 'error_add_aro' => '', 'error_add_permission' => '', 'error_cleared_cache' => '', +'error_edit_task' => '', 'error_extension_getlist' => '', 'error_importfs' => '', 'error_no_document_selected' => 'Nici un document selectat', @@ -489,8 +491,12 @@ URL: [url]', 'error_remove_document' => '', 'error_remove_folder' => '', 'error_remove_permission' => '', +'error_rm_workflow' => '', +'error_rm_workflow_action' => '', +'error_rm_workflow_state' => '', 'error_toogle_permission' => '', 'error_transfer_document' => '', +'error_trigger_workflow' => '', 'error_update_document' => '', 'error_uploading_reviewer_only' => '', 'es_ES' => 'Spaniola', @@ -520,12 +526,12 @@ URL: [url]', 'export' => '', 'extension_archive' => '', 'extension_changelog' => '', -'extension_loading' => '', +'extension_loading' => 'Se incarca extensiile', 'extension_manager' => 'Gestionați extensiile', -'extension_mgr_installed' => '', -'extension_mgr_no_upload' => '', -'extension_mgr_repository' => '', -'extension_version_list' => '', +'extension_mgr_installed' => 'Instalata', +'extension_mgr_no_upload' => 'Nu se poate incarca o extensie noua pentru ca directorul nu are drepturi de scriere', +'extension_mgr_repository' => 'Disponibila', +'extension_version_list' => 'Versiuni', 'february' => 'Februarie', 'file' => 'Fișier', 'files' => 'Fișiere', @@ -576,7 +582,7 @@ Utilizator: [username] URL: [url]', 'folder_renamed_email_subject' => '[sitename]: [name] - Folder redenumit', 'folder_title' => 'Folder \'[foldername]\'', -'force_update' => '', +'force_update' => 'Actualizeaza', 'friday' => 'Vineri', 'friday_abbr' => 'Vi', 'from' => 'De la', @@ -633,7 +639,6 @@ URL: [url]', 'index_waiting' => '', 'individuals' => 'Individuals', 'individuals_in_groups' => '', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => '', 'inherited' => 'moștenit', 'inherits_access_copy_msg' => 'Copie lista de acces moștenită', @@ -726,9 +731,11 @@ URL: [url]', 'login_error_title' => 'Eroare de logare', 'login_not_given' => 'Nici un numele de utilizator nu au fost furnizat', 'login_ok' => 'Login cu succes', +'login_restrictions_apply' => '', 'logout' => 'Logout', 'log_management' => 'Log management de fișiere', -'lo_LA' => '', +'lo_LA' => 'Laoțiană', +'malformed_expiration_date' => '', 'manager' => 'Manager', 'manager_of_group' => 'Sunteți managerul acestui grup', 'mandatory_approvergroups' => 'Grupuri obligatorii de aprobatori', @@ -743,6 +750,7 @@ URL: [url]', 'max_upload_size' => 'Dimensiunea maximă de încărcare', 'may' => 'Mai', 'menu_dropfolder' => '', +'menu_upload_from_dropfolder' => '', 'mimetype' => 'Mime type', 'minutes' => 'minute', 'misc' => 'Diverse', @@ -1170,6 +1178,8 @@ URL: [url]', 'settings_Advanced' => 'Avansat', 'settings_advancedAcl' => '', 'settings_advancedAcl_desc' => '', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', 'settings_allowReviewerOnly' => '', 'settings_allowReviewerOnly_desc' => '', 'settings_apache_mod_rewrite' => 'Apache - Module Rewrite', @@ -1321,6 +1331,8 @@ URL: [url]', 'settings_enableVersionModification_desc' => 'Activarea/dezactivarea modificarii unei versiuni de documente de către utilizatorii obisnuiti, după ce o versiune a fost încărcată. Adminul poate modifica oricând versiunea după încărcare.', 'settings_enableWebdavReplaceDoc' => '', 'settings_enableWebdavReplaceDoc_desc' => '', +'settings_enableXsendfile' => '', +'settings_enableXsendfile_desc' => '', 'settings_encryptionKey' => 'Cheia de criptare', 'settings_encryptionKey_desc' => 'Acest șir este utilizat pentru crearea unui identificator unic ce este adăugat ca un câmp ascuns pentru un formular, cu scopul de a preveni atacurile CSRF.', 'settings_error' => 'Eroare', @@ -1514,7 +1526,7 @@ URL: [url]', 'set_password' => 'Setare Parolă', 'set_workflow' => 'Setare Workflow', 'show_extension_changelog' => '', -'show_extension_version_list' => '', +'show_extension_version_list' => 'Arata o lista a versiunilor', 'signed_in_as' => 'Autentificat ca', 'sign_in' => 'Sign in', 'sign_out' => 'Sign out', @@ -1544,6 +1556,7 @@ URL: [url]', 'splash_edit_event' => '', 'splash_edit_group' => 'Grup salvat', 'splash_edit_role' => '', +'splash_edit_task' => '', 'splash_edit_user' => 'Utilizator salvat', 'splash_error_add_to_transmittal' => '', 'splash_error_rm_download_link' => '', @@ -1574,6 +1587,9 @@ URL: [url]', 'splash_rm_transmittal' => '', 'splash_rm_user' => 'Uilizator eliminat', 'splash_rm_user_processes' => '', +'splash_rm_workflow' => '', +'splash_rm_workflow_action' => '', +'splash_rm_workflow_state' => '', 'splash_saved_file' => '', 'splash_save_user_data' => '', 'splash_send_download_link' => '', @@ -1586,6 +1602,7 @@ URL: [url]', 'splash_toogle_group_manager' => 'Comută Managerul de grup', 'splash_transfer_document' => '', 'splash_transfer_objects' => '', +'splash_trigger_workflow' => '', 'state_and_next_state' => 'Stare/Stare urmatoare', 'statistic' => 'Statistic', 'status' => 'Status', diff --git a/languages/ru_RU/lang.inc b/languages/ru_RU/lang.inc index 8a6f7751a..fcc6bfc10 100644 --- a/languages/ru_RU/lang.inc +++ b/languages/ru_RU/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (1663) +// Translators: Admin (1667) $text = array( '2_factor_auth' => 'Двухфакторная аутентификация', @@ -198,6 +198,7 @@ URL: [url]', 'at_least_n_users_of_group' => '[number_of_users] польз. группы [group]', 'august' => 'Август', 'authentication' => 'Авторизация', +'authentication_failed' => '', 'author' => 'Автор', 'automatic_status_update' => 'Автоматическое изменение статуса', 'back' => 'Назад', @@ -481,6 +482,7 @@ URL: [url]', 'error_add_aro' => '', 'error_add_permission' => 'Ошибка добавления разрешения', 'error_cleared_cache' => 'Ошибка очиски кеша', +'error_edit_task' => '', 'error_extension_getlist' => '', 'error_importfs' => 'Ошибка импорта из файловой системы', 'error_no_document_selected' => 'Нет выбранных документов', @@ -489,8 +491,12 @@ URL: [url]', 'error_remove_document' => '', 'error_remove_folder' => '', 'error_remove_permission' => 'Ошибка снятия разрешения', +'error_rm_workflow' => '', +'error_rm_workflow_action' => '', +'error_rm_workflow_state' => '', 'error_toogle_permission' => 'Ошибка смены разрешения', 'error_transfer_document' => '', +'error_trigger_workflow' => '', 'error_update_document' => '', 'error_uploading_reviewer_only' => '', 'es_ES' => 'Spanish', @@ -633,7 +639,6 @@ URL: [url]', 'index_waiting' => 'Ожидание', 'individuals' => 'Пользователи', 'individuals_in_groups' => 'Пользователи группы', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => '', 'inherited' => 'унаследованный', 'inherits_access_copy_msg' => 'Скопировать наследованный список', @@ -726,9 +731,11 @@ URL: [url]', 'login_error_title' => 'Ошибка входа', 'login_not_given' => 'Не указан пользователь', 'login_ok' => 'Вход успешен', +'login_restrictions_apply' => '', 'logout' => 'Выход', 'log_management' => 'Управление журналами', -'lo_LA' => '', +'lo_LA' => 'Лаос', +'malformed_expiration_date' => '', 'manager' => 'Менеджер', 'manager_of_group' => 'Вы являетесь менеджером данной группы', 'mandatory_approvergroups' => 'Обязательные группы утверждающих', @@ -743,6 +750,7 @@ URL: [url]', 'max_upload_size' => 'Ограничение размера файла', 'may' => 'Май', 'menu_dropfolder' => '', +'menu_upload_from_dropfolder' => '', 'mimetype' => 'MIME-тип', 'minutes' => 'минуты', 'misc' => 'Прочее', @@ -1177,6 +1185,8 @@ URL: [url]', 'settings_Advanced' => 'Дополнительно', 'settings_advancedAcl' => '', 'settings_advancedAcl_desc' => '', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', 'settings_allowReviewerOnly' => '', 'settings_allowReviewerOnly_desc' => '', 'settings_apache_mod_rewrite' => 'Apache — модуль Rewrite', @@ -1328,6 +1338,8 @@ URL: [url]', 'settings_enableVersionModification_desc' => 'Разрешить или запретить обычным пользователям изменение версий документов после их загрузки на сервер. Администратор всегда сможет изменить версии документов после их загрузки на сервер.', 'settings_enableWebdavReplaceDoc' => '', 'settings_enableWebdavReplaceDoc_desc' => '', +'settings_enableXsendfile' => '', +'settings_enableXsendfile_desc' => '', 'settings_encryptionKey' => 'Ключ шифрования', 'settings_encryptionKey_desc' => 'Строка используется для создания уникального идентификатора, добавляемого как скрытые поля к формулярам, для предотвращения CSRF-атак.', 'settings_error' => 'Ошибка', @@ -1551,6 +1563,7 @@ URL: [url]', 'splash_edit_event' => '', 'splash_edit_group' => 'Группа сохранена', 'splash_edit_role' => '', +'splash_edit_task' => '', 'splash_edit_user' => 'Пользователь сохранён', 'splash_error_add_to_transmittal' => '', 'splash_error_rm_download_link' => '', @@ -1581,6 +1594,9 @@ URL: [url]', 'splash_rm_transmittal' => '', 'splash_rm_user' => 'Пользователь удалён', 'splash_rm_user_processes' => '', +'splash_rm_workflow' => '', +'splash_rm_workflow_action' => '', +'splash_rm_workflow_state' => '', 'splash_saved_file' => '', 'splash_save_user_data' => '', 'splash_send_download_link' => '', @@ -1593,6 +1609,7 @@ URL: [url]', 'splash_toogle_group_manager' => 'Изменён менеджер группы', 'splash_transfer_document' => '', 'splash_transfer_objects' => '', +'splash_trigger_workflow' => '', 'state_and_next_state' => 'Статус / следующий статус', 'statistic' => 'Статистика', 'status' => 'Статус', @@ -1679,11 +1696,11 @@ URL: [url]', 'toggle_qrcode' => '', 'to_before_from' => 'Конечная дата не может быть меньше начальной даты', 'transfer_document' => 'Передать документ', -'transfer_no_read_access' => '', -'transfer_no_write_access' => '', +'transfer_no_read_access' => 'Пользователь не имеет доступа на чтение в этой папке', +'transfer_no_write_access' => 'Пользователь не имеет доступа на запись в этой папке', 'transfer_objects' => '', 'transfer_objects_to_user' => '', -'transfer_to_user' => '', +'transfer_to_user' => 'Передать пользователю', 'transition_triggered_email' => 'Изменено состояние процесса', 'transition_triggered_email_body' => 'Изменено состояние процесса Документ: [name] diff --git a/languages/sk_SK/lang.inc b/languages/sk_SK/lang.inc index 2cbcd0601..f2e84f61d 100644 --- a/languages/sk_SK/lang.inc +++ b/languages/sk_SK/lang.inc @@ -19,19 +19,19 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (567), destinqo (19), pS2017 (508) +// Translators: Admin (1224), destinqo (19), pS2017 (508), ssebech (4) $text = array( '2_factor_auth' => '2-faktorové overovanie', -'2_factor_auth_info' => '', +'2_factor_auth_info' => 'This system enforces 2 factor authentication. You will need the Google Authenticator on your mobile phone. Below you see two QR codes. The right one is your current secret. On the left you can set a new secret. If you set a new secret make sure to rescan it with Google Authenticator.', '2_fact_auth_secret' => 'Tajný', 'accept' => 'Prijať', 'access_control' => 'Kontrola prístupu', -'access_control_is_off' => '', +'access_control_is_off' => 'Pokročilá kontrola prístupu je vypnutá', 'access_denied' => 'Prístup zamietnutý.', 'access_inheritance' => 'Dedičnosť prístupu', 'access_mode' => 'Režim prístupu', -'access_mode_all' => 'Každý', +'access_mode_all' => 'Plný prístup', 'access_mode_none' => 'Žiadny prístup', 'access_mode_read' => 'Na čítanie', 'access_mode_readwrite' => 'Na čítanie aj zápis', @@ -54,26 +54,26 @@ URL: [url]', 'action_revise' => 'Revidovať', 'add' => 'Pridať', 'add_approval' => 'Poslať schválenie', -'add_attrdefgroup' => '', +'add_attrdefgroup' => 'Pridať novú skupinu atribútov', 'add_document' => 'Pridať dokument', 'add_document_link' => 'Pridať odkaz', 'add_document_notify' => 'Pridať notifikáciu', -'add_doc_reviewer_approver_warning' => 'Pozn.: Dokumenty sa automaticky označia ako vydané ak nie je pridelený žiadny kontrolór alebo schvaľovateľ.', -'add_doc_workflow_warning' => '', +'add_doc_reviewer_approver_warning' => 'Pozn.: Dokumenty sa automaticky označia ako vydané ak nie je pridelený žiadny recenzent alebo schvaľovateľ.', +'add_doc_workflow_warning' => 'N.B. Documents are automatically marked as released if no workflow is assigned.', 'add_event' => 'Pridať udalosť', 'add_group' => 'Pridať novú skupinu', 'add_member' => 'Pridať člena', 'add_multiple_documents' => 'Pridaj viac dokumentov', 'add_multiple_files' => 'Pridať viacero súborov (názov súboru sa použije ako názov dokumentu)', 'add_receipt' => 'Potvrďte príjem', -'add_review' => 'Poslať kontrolu', +'add_review' => 'Pridať recenziu', 'add_revision' => 'Pridať schválenie', 'add_role' => 'Pridať novú rolu', 'add_subfolder' => 'Pridať podzložku', -'add_task' => '', +'add_task' => 'Pridať novú úlohu pre túto triedu', 'add_to_clipboard' => 'Pridaj do schránky', -'add_to_transmittal' => '', -'add_transmittal' => '', +'add_to_transmittal' => 'Add to transmittal', +'add_transmittal' => 'Add transmittal', 'add_user' => 'Pridať nového používatela', 'add_user_to_group' => 'Pridať používateľa do skupiny', 'add_workflow' => 'Pridať nový pracovný postup', @@ -89,56 +89,73 @@ URL: [url]', 'already_subscribed' => 'Už ste sa prihlásili na odber', 'and' => 'a', 'apply' => 'Použiť', -'approvals_accepted' => '', -'approvals_and_reviews_accepted' => '', -'approvals_and_reviews_not_touched' => '', -'approvals_and_reviews_rejected' => '', -'approvals_not_touched' => '', -'approvals_rejected' => '', -'approvals_without_group' => '', -'approvals_without_user' => '', -'approval_deletion_email' => 'Poziadavka na schvalenie zmazana', -'approval_deletion_email_body' => '', -'approval_deletion_email_subject' => '', +'approvals_accepted' => '[no_approvals] approvals already accepted', +'approvals_and_reviews_accepted' => '[no_approvals] approvals and [no_reviews] reviews already accepted', +'approvals_and_reviews_not_touched' => '[no_approvals] approvals and [no_reviews] reviews not being touched', +'approvals_and_reviews_rejected' => '[no_approvals] approvals and [no_reviews] reviews already rejected', +'approvals_not_touched' => '[no_approvals] approvals not being touched', +'approvals_rejected' => '[no_approvals] approvals already rejected', +'approvals_without_group' => 'Approvals without group', +'approvals_without_user' => 'Approvals without user', +'approval_deletion_email' => 'Požiadavka na schválenie zmazaná', +'approval_deletion_email_body' => 'Požiadavka na schválenie zmazaná +Dokument: [name] +Verzia: [version] +Nadradený adresár: [folder_path] +Užívateľ: [username] +URL: [url]', +'approval_deletion_email_subject' => '[sitename]: [name] - Požiadavka na schválenie zmazaná', 'approval_file' => 'Súbor', 'approval_group' => 'Skupina schválenia', 'approval_log' => 'Denník schvaľovania', -'approval_request_email' => 'Poziadavka na schvalenie', -'approval_request_email_body' => '', -'approval_request_email_subject' => '', +'approval_request_email' => 'Požiadavka na schválenie', +'approval_request_email_body' => 'Požiadavka na schválenie +Dokument: [name] +Verzia: [version] +Nadradený adresár: [folder_path] +Užívateľ: [username] +URL: [url]', +'approval_request_email_subject' => '[sitename]: [name] - Požiadavka na schválenie', 'approval_status' => 'Stav schválenia', 'approval_submit_email' => '', -'approval_submit_email_body' => '', -'approval_submit_email_subject' => '[sitename]: [name] - Poslane schvalenie', +'approval_submit_email_body' => 'Schválenie dokumentu +Dokument: [name] +Verzia: [version] +Nadradený adresár: [folder_path] +Stav: [status] +Komentár: [comment] +Užívateľ: [username] +URL: [url]', +'approval_submit_email_subject' => '[sitename]: [name] - Odoslané schválenie', 'approval_summary' => 'Zhrnutie schválenia', 'approval_update_failed' => 'Chyba pri aktualizácii stavu schválenia. Aktualizácia zlyhala.', 'approvers' => 'Schvaľovatelia', -'approver_already_assigned' => '', -'approver_already_removed' => '', -'april' => 'Apríl', -'archive' => '', +'approver_already_assigned' => 'User is already assigned as an approver.', +'approver_already_removed' => 'Approver has already been removed from approval process or has already submitted an approval.', +'april' => 'apríl', +'archive' => 'archív', 'archive_creation' => 'Vytvorenie archívu', 'archive_creation_warning' => 'Touto akciou môžete vytvoriť archív obsahujúci celú DMS zložku. Po vytvorení bude každý súbor uložený do dátovej zložky súborov na vašom serveri.
UPOZORNENIE: uživateľsky prístupný archív nie je možné použiť ako zálohu servera.', 'ar_EG' => 'Arabština', 'assign_approvers' => 'Určiť schvaľovateľov', -'assign_recipients' => '', +'assign_recipients' => 'Určiť príjemcov', 'assign_reviewers' => 'Určiť recenzentov', 'assign_user_property_to' => 'Assign user\'s properties to', 'assumed_released' => 'Pokladá sa za zverejnené', -'attrdefgroup_management' => '', +'attrdefgroup_management' => 'Manažment skupín atribútov', 'attrdefgrp_show_detail' => 'Detaily', 'attrdefgrp_show_list' => 'Zoznam', 'attrdefgrp_show_search' => 'Hľadať', 'attrdefgrp_show_searchlist' => 'Výsledok hľadania', -'attrdef_exists' => '', +'attrdef_exists' => 'Definícia atribútu už existuje', 'attrdef_info' => 'Informácia', -'attrdef_in_use' => '', -'attrdef_management' => '', +'attrdef_in_use' => 'Definícia atribútu sa stále používa', +'attrdef_management' => 'Správa definície atribútu', 'attrdef_maxvalues' => 'Max. počet hodnôt', 'attrdef_minvalues' => 'Min. počet hodnôt', -'attrdef_min_greater_max' => '', -'attrdef_multiple' => '', -'attrdef_multiple_needs_valueset' => '', +'attrdef_min_greater_max' => 'Minimum number of values is larger than maximum number of values', +'attrdef_multiple' => 'Allow multiple values', +'attrdef_multiple_needs_valueset' => 'Attribute definition with multiple values needs value set.', 'attrdef_must_be_multiple' => 'Atribút musí mať viac ako jednu hodnotu, ale nie je nastavená viacnásobná hodnota', 'attrdef_name' => 'Meno', 'attrdef_noname' => 'Chýba názov definície atribútu', @@ -154,14 +171,14 @@ URL: [url]', 'attrdef_type_url' => 'URL', 'attrdef_valueset' => 'Nastaviť hodnoty', 'attributes' => 'Atribúty', -'attribute_changed_email_body' => 'Zmenené atribúty -Dokumentu: [name] -Vezia: [version] -Atribút: [attribute_name] -Old value: [attribute_old_value] -New value: [attribute_new_value] -Nadradená zložka: [folder_path] -Používateľ: [username] +'attribute_changed_email_body' => 'Zmenené atribúty +Dokumentu: [name] +Vezia: [version] +Atribút: [attribute_name] +Old value: [attribute_old_value] +New value: [attribute_new_value] +Nadradená zložka: [folder_path] +Používateľ: [username] URL: [url]', 'attribute_changed_email_subject' => '[sitename]: [name] - Atribút sa zmenil', 'attribute_count' => 'Počet použití', @@ -174,13 +191,14 @@ URL: [url]', 'attr_malformed_int' => 'Hodnota atribútu \'[value]\' v atribúte \'[attrname]\' nie je platný integer.', 'attr_malformed_url' => 'Hodnota atribútu \'[value]\' v atribúte \'[attrname]\' nie je platná URL.', 'attr_max_values' => 'Je prekročený maximálny počet požadovaných hodnôt pre atribút [attrname].', -'attr_min_values' => '', -'attr_not_in_valueset' => '', -'attr_no_regex_match' => '', -'attr_validation_error' => '', -'at_least_n_users_of_group' => '', +'attr_min_values' => 'Nie je dosiahnutý minimálny počet požadovaných hodnôt pre atribút [attrname].', +'attr_not_in_valueset' => 'The attribute value \'[value]\' for attribute \'[attrname]\' is not contained in the valueset.', +'attr_no_regex_match' => 'The attribute value \'[value]\' for attribute \'[attrname]\' does not match the regular expression \'[regex]\'', +'attr_validation_error' => 'The value \'[value]\' of attribute \'[attrname]\' is invalid.', +'at_least_n_users_of_group' => 'At least [number_of_users] users of [group]', 'august' => 'August', -'authentication' => 'Overenie pravosti', +'authentication' => 'Autentizácia', +'authentication_failed' => '', 'author' => 'Autor', 'automatic_status_update' => 'Automaticka zmena stavu', 'back' => 'Prejsť späť', @@ -194,13 +212,13 @@ URL: [url]', 'calendar' => 'Kalendár', 'calendar_week' => 'Kalendárny týždeň', 'cancel' => 'Zrušiť', -'cannot_assign_invalid_state' => 'Nie je možné prideliť schvaľovateľov dokumentu, ktorý nečaká na kontrolu alebo schválenie.', -'cannot_change_final_states' => 'Upozornenie: Nebolo možné zmeniť stav dokumentov, ktoré boli odmietnuté, označené ako zastaralé alebo platnosť vypršala.', +'cannot_assign_invalid_state' => 'Cannot modify an obsolete or rejected document', +'cannot_change_final_states' => 'Warning: You cannot alter status for document rejected, expired or with pending review or approval', 'cannot_delete_user' => 'Nie je možné odstrániť používateľa', -'cannot_delete_yourself' => 'Vás nie je možné odstrániť', +'cannot_delete_yourself' => 'Nemôžete odstrániť sám seba', 'cannot_move_root' => 'Chyba: Nie je možné presunúť koreňovú zložku.', 'cannot_retrieve_approval_snapshot' => 'Nie je možné získať informáciu o stave schválenia tejto verzie dokumentu.', -'cannot_retrieve_review_snapshot' => 'Nie je možné získať informáciu o stave kontroly tejto verzie dokumentu.', +'cannot_retrieve_review_snapshot' => 'Nie je možné získať informáciu o stave recenzie tejto verzie dokumentu.', 'cannot_rm_root' => 'Chyba: Nie je možné zmazať koreňovú zložku.', 'categories' => 'Kategórie', 'categories_loading' => 'Počkajte, kým nebude načítaný zoznam kategórií ...', @@ -226,11 +244,11 @@ URL: [url]', 'chart_docsperuser_title' => 'Dokumenty podľa používateľa', 'chart_selection' => 'Vyber graf', 'chart_sizeperuser_title' => 'Diskový priestor na používateľa', -'checkedout_file_has_different_version' => '', -'checkedout_file_has_disappeared' => '', -'checkedout_file_is_unchanged' => '', -'checkin_document' => '', -'checkoutpath_does_not_exist' => '', +'checkedout_file_has_different_version' => 'The checked out version is not identical to the current version. Check in will not update the document.', +'checkedout_file_has_disappeared' => 'The file of the checked out document has disappeared. Check in will not be possible.', +'checkedout_file_is_unchanged' => 'The file of the checked out document is still unchanged. Check in will not be possible. If do not plan any modifications, you can reset the check out status.', +'checkin_document' => 'Check In', +'checkoutpath_does_not_exist' => 'Checkout path does not exists', 'checkout_document' => 'Pozrieť sa na dokument', 'checkout_is_disabled' => 'Kontrola dokumentov je zakázaná v konfigurácii.', 'choose_attrdef' => 'Vyberte prosím definíciu atribútu', @@ -256,40 +274,40 @@ URL: [url]', 'comment' => 'Komentár', 'comment_changed_email' => 'Nepreložené', 'comment_for_current_version' => 'Version comment', -'configure_extension' => '', +'configure_extension' => 'Configure extension', 'confirm_clear_cache' => 'Chcete naozaj vyčistiť vyrovnávaciu pamäť? Tým sa odstránia všetky predbežne náhľady obrázkov.', 'confirm_create_fulltext_index' => 'Áno, chcel by som obnoviť fullttext index!', 'confirm_move_document' => 'Potvrďte presunutie dokumentu.', 'confirm_move_folder' => 'Potvrďte presunutie zložky.', 'confirm_pwd' => 'Potvrdenie hesla', -'confirm_rm_attr_value' => '', +'confirm_rm_attr_value' => 'Naozaj chcete vymazať hodnotu atribútu?', 'confirm_rm_backup' => 'Skutočne si prajete odstrániť zálohu "[arkname]"?
Buďte opatrní, táto akcia je nezvratná.', -'confirm_rm_document' => 'Naozaj chcete odstrániť dokument \'[documentname]\'?
Buďte opatrní: Túto činnosť nemožno vrátiť späť.', +'confirm_rm_document' => 'Naozaj chcete odstrániť dokument \'[documentname]\'?
Buďte opatrní: Túto operáciu nemožno vrátiť späť.', 'confirm_rm_dump' => 'Skutočne si prajete odstrániť "[dumpname]"?
Buďte opatrní, táto akcia je nezvratná.', 'confirm_rm_event' => 'Skutočne si prajete odstrániť udalosť "[name]"?
Buďte opatrní, táto akcia je nezvratná.', 'confirm_rm_file' => 'Skutočne si prajete odstrániť súbor "[name]" z dokumentu "[documentname]"?
Buďte opatrní, táto akcia je nezvratná.', -'confirm_rm_folder' => 'Naozaj chcete odstrániť \'[foldername]\' a jeho obsah?
Buďte opatrní: Túto činnosť nemožno vrátiť späť.', +'confirm_rm_folder' => 'Naozaj chcete odstrániť \'[foldername]\' a jeho obsah?
Buďte opatrní: Túto operáciu nemožno vrátiť späť.', 'confirm_rm_folder_files' => 'Skutočne si prajete odstrániť všetky súbory zložky "[foldername]" a všetkých jej podzložiek?
Buďte opatrní, táto akcia je nezvratná.', 'confirm_rm_group' => 'Skutočne si prajete odstrániť skupinu "[groupname]"?
Buďte opatrní, táto akcia je nezvratná.', 'confirm_rm_log' => 'Skutočne si prajete zmazať protokol "[logname]"?
Buďte opatrní, táto akcia je nezvratná.', -'confirm_rm_transmittal' => '', +'confirm_rm_transmittal' => 'Please confirm the deletion of the transmittal.', 'confirm_rm_transmittalitem' => 'Potvrďte odstránenie', 'confirm_rm_user' => 'Skutočne si prajete odstrániť používateľa "[username]"?
Buďte opatrní, táto akcia je nezvratná.', -'confirm_rm_user_from_processes' => '', -'confirm_rm_version' => 'Naozaj chcete odstrániť verziu [version] dokumentu "[documentname]"?
Buďte opatrní: Túto činnosť nemožno vrátiť späť.', -'confirm_transfer_objects' => '', +'confirm_rm_user_from_processes' => 'Do you really want to remove the user "[username]" from all processes?
Be careful: This action can lead to the release of documents if the user was the only or last approver.', +'confirm_rm_version' => 'Naozaj chcete odstrániť verziu [version] dokumentu "[documentname]"?
Buďte opatrní: Túto operáciu nemožno vrátiť späť.', +'confirm_transfer_objects' => 'Do you really want to transfer the documents, folders, etc. of the user "[username]"?
Be careful: This action cannot be undone.', 'confirm_update_transmittalitem' => 'Potvrdiť aktualizáciu', 'content' => 'Obsah', 'continue' => 'Pokračovať', 'converter_new_cmd' => 'Príkaz', 'converter_new_mimetype' => 'Nový mime-type', -'copied_to_checkout_as' => '', +'copied_to_checkout_as' => 'File copied to checkout space as \'[filename]\' on [date]', 'create_download_link' => 'Vytvoriť odkaz na stiahnutie', 'create_fulltext_index' => 'Vytvoriť fulltext index', 'create_fulltext_index_warning' => 'Chystáte sa obnoviť fulltext index, čo môže dlho trvať a môže znížiť výkon systému. Ak chcete pokračovať, potvrďte svoju voľbu.', 'creation_date' => 'Vytvorené', 'cs_CZ' => 'Čestina', -'current_password' => '', +'current_password' => 'Aktuálne heslo', 'current_quota' => 'Súčasná kvóta systému je nastavená na [quota].', 'current_state' => 'Aktuálny stav', 'current_version' => 'Aktuálna verzia', @@ -308,74 +326,123 @@ URL: [url]', 'de_DE' => 'Nemčina', 'disclaimer' => 'Toto je zabezpečená zóna. Prístup je povolený len autorizovaným osobám.', 'discspace' => 'Priestor na disku', -'docs_in_reception_no_access' => '', -'docs_in_revision_no_access' => '', +'docs_in_reception_no_access' => 'Documents with reception without access by recipient', +'docs_in_revision_no_access' => 'Documents in revision without access by revisor', 'document' => 'Dokument', 'documentcontent' => 'Obsah dokumentu', 'documents' => 'Dokumenty', -'documents_checked_out_by_you' => '', +'documents_checked_out_by_you' => 'Documents checked out by you', 'documents_expired' => 'Dokumenty, ktorým skončila platnosť', 'documents_in_process' => 'Dokumenty v spracovaní', 'documents_locked' => 'Zamknuté dokumenty', 'documents_locked_by_you' => 'Vami uzamknuté dokumenty', 'documents_only' => 'Iba dokumenty', 'documents_to_approve' => 'Dokumenty čakajúce na schválenie používateľa', -'documents_to_correct' => '', +'documents_to_correct' => 'Dokumenty, ktoré treba opraviť', 'documents_to_process' => 'Dokumenty, ktoré potrebujú spracovanie', -'documents_to_receipt' => '', -'documents_to_review' => 'Dokumenty čakajúce na kontrolu používateľa', +'documents_to_receipt' => 'Dokumenty čakajúce na potvrdenie prijatia', +'documents_to_review' => 'Dokumenty čakajúce na recenziu používateľa', 'documents_to_revise' => 'Dokumenty čakajúce na vašu revíziu', -'documents_to_trigger_workflow' => '', -'documents_user_draft' => '', -'documents_user_expiration' => '', -'documents_user_needs_correction' => '', -'documents_user_no_reception' => '', -'documents_user_obsolete' => '', +'documents_to_trigger_workflow' => 'Documents in workflow', +'documents_user_draft' => 'Drafts', +'documents_user_expiration' => 'Dokumenty, ktorým skončila platnosť', +'documents_user_needs_correction' => 'Dokumenty, ktoré treba opraviť', +'documents_user_no_reception' => 'Dokumenty bez prijatia', +'documents_user_obsolete' => 'Obsoletné, neaktuálne dokumenty', 'documents_user_reception' => 'Dokumenty čakajúce na prijatie', 'documents_user_rejected' => 'Zamietnuté dokumenty', 'documents_user_requiring_attention' => 'Dokumenty, ktoré používateľ vlastní a vyžadujú pozornosť', -'documents_with_notification' => 'Dokumenty s upozornením', -'document_already_checkedout' => '', +'documents_with_notification' => 'Dokumenty s notifikáciou', +'document_already_checkedout' => 'This document is already checked out', 'document_already_locked' => 'Tento dokument je už zamknutý', -'document_attribute_changed_email_body' => '', -'document_attribute_changed_email_subject' => '', +'document_attribute_changed_email_body' => 'Atribút bol zmenený +Dokument: [name] +Atribút: [attribute_name] +Predošlá hodnota: [attribute_old_value] +Nová hodnota: [attribute_new_value] +Nadradená zložka: [folder_path] +Používateľ: [username] +URL: [url]', +'document_attribute_changed_email_subject' => '[sitename]: [name] - Atribút bol zmenený', 'document_comment_changed_email' => 'Komentár sa zmenil', -'document_comment_changed_email_body' => '', +'document_comment_changed_email_body' => 'Komentár sa zmenil +Dokument: [name] +Predošlý komentár: [old_comment] +Nový komentár: [new_comment] +Nadradená zložka: [folder_path] +Užívateľ: [username] +URL: [url]', 'document_comment_changed_email_subject' => '[sitename]: [name] - Komentár sa zmenil', 'document_count' => 'Počet dokumentov', 'document_deleted' => 'Dokument zmazaný', -'document_deleted_email' => 'Dokument zmazany', -'document_deleted_email_body' => 'Dokument bol odstránený: [name] Nadradená zložka: [folder_path] Používateľ: [username]', +'document_deleted_email' => 'Dokument zmazaný', +'document_deleted_email_body' => 'Dokument bol odstránený +Dokument: [name] +Nadradená zložka: [folder_path] +Používateľ: [username]', 'document_deleted_email_subject' => '[sitename]: [name] - Dokument bol zmazaný', 'document_duplicate_name' => 'Duplicitný názov dokumentu', 'document_has_no_workflow' => 'Dokument nemá pracovný postup', 'document_infos' => 'Informácie o dokumente', -'document_is_checked_out' => '', +'document_is_checked_out' => 'Document is currently checked out. If you upload a new version, then the checked out version cannot be checked back in anymore.', 'document_is_not_locked' => 'Tento dokument nie je zamknutý', 'document_link_by' => 'Odkazuje sem', 'document_link_public' => 'Verejný', -'document_moved_email' => 'Dokument presunuty', -'document_moved_email_body' => '', +'document_moved_email' => 'Dokument presunutý', +'document_moved_email_body' => 'Dokument presunutý +Dokument: [name] +Predošlá zložka: [old_folder_path] +Nová zložka: [new_folder_path] +Užívateľ: [username] +URL: [url]', 'document_moved_email_subject' => '[sitename]: [name] - Dokument bol presunutý', -'document_not_checkedout' => '', +'document_not_checkedout' => 'Document is not checked out.', 'document_renamed_email' => 'Dokument premenovany', -'document_renamed_email_body' => 'Názov dokumentu zmenený Dokument: [name] Nadradená zložka: [folder_path] Starý názov: [old_name] Používateľ: [username] URL: [url]', +'document_renamed_email_body' => 'Názov dokumentu zmenený +Dokument: [name] +Nadradená zložka: [folder_path] +Starý názov: [old_name] +Používateľ: [username] +URL: [url]', 'document_renamed_email_subject' => '[sitename]: [name] - Dokument bol premenovaný', -'document_status_changed_email' => 'Stav dokumentu zmeneny', -'document_status_changed_email_body' => '', -'document_status_changed_email_subject' => '', +'document_status_changed_email' => 'Stav dokumentu zmenený', +'document_status_changed_email_body' => 'Stav dokumentu zmenený +Dokument: [name] +Stav: [status] +Nadradená zložka: [folder_path] +Používateľ: [username] +URL: [url]', +'document_status_changed_email_subject' => '[sitename]: [name] - Stav dokumentu zmenený', 'document_title' => 'Dokument \'[documentname]\'', -'document_transfered_email_body' => '', -'document_transfered_email_subject' => '', +'document_transfered_email_body' => 'Transfer dokumentu inému používateľovi +Dokument: [name] +Nový vlastník: [newuser] +Nadradená zložka: [folder_path] +Používateľ: [username] +URL: [url]', +'document_transfered_email_subject' => '[sitename]: [name] - Transfer dokumentu', 'document_updated_email' => 'Dokument aktualizovany', -'document_updated_email_body' => '', +'document_updated_email_body' => 'Dokument aktualizovaný +Dokument: [name] +Nadradená zložka: [folder_path] +Užívateľ: [username] +Komentár: [comment] +Komentár verzie: [version_comment] +URL: [url]', 'document_updated_email_subject' => '[sitename]: [name] - Dokument bol aktualizovaný', 'does_not_expire' => 'Platnosť nikdy nevyprší', 'does_not_inherit_access_msg' => 'Zdediť prístup', 'download' => 'Stiahnuť', -'download_extension' => '', +'download_extension' => 'Download extension as zip file', 'download_links' => 'Odkazy na stiahnutie', -'download_link_email_body' => '', +'download_link_email_body' => 'Kliknite na doleuvedený odkaz a stiahnite verziu [version] dokumentu +\'[docname]\'. + +[url] + +Odkaz je platný do [valid]. + +[comment]', 'download_link_email_subject' => 'Odkaz na stiahnutie', 'do_object_repair' => 'Opraviť všetky zložky a dokumenty.', 'do_object_setchecksum' => 'Nastaviť kontrolný súčet', @@ -383,9 +450,9 @@ URL: [url]', 'do_object_unlink' => 'Zmazať verziu dokumentu', 'draft' => 'Návrh', 'draft_pending_approval' => 'Návrh - čaká na schválenie', -'draft_pending_review' => 'Návrh - čaká na kontrolu', -'drag_icon_here' => 'Sem myšou pretiahnite ikonu, zložku alebo dokument', -'dropfolderdir_missing' => '', +'draft_pending_review' => 'Návrh - čaká na recenziu', +'drag_icon_here' => 'Sem myšou pretiahnite ikonu zložky alebo dokument', +'dropfolderdir_missing' => 'Your personal drop folder does not exist on the server! Please ask your administrator to create it.', 'dropfolder_file' => 'Súbor z drop zložky', 'dropfolder_folder' => 'Zložka z drop zložky', 'dropupload' => 'Rýchlo nahraj', @@ -401,20 +468,20 @@ URL: [url]', 'edit_comment' => 'Upraviť komentár', 'edit_default_keywords' => 'Uprav kľúčové slová', 'edit_document_access' => 'Upraviť prístup', -'edit_document_notify' => 'Zoznam upozornení', +'edit_document_notify' => 'Zoznam notifikácií', 'edit_document_props' => 'Upraviť dokument', 'edit_event' => 'Upraviť udalosť', 'edit_existing_access' => 'Upraviť zoznam riadenia prístupu', -'edit_existing_attribute_groups' => '', -'edit_existing_notify' => 'Upraviť zoznam upozornení', +'edit_existing_attribute_groups' => 'Edit attribute groups', +'edit_existing_notify' => 'Upraviť zoznam notifikácií', 'edit_folder_access' => 'Upraviť prístup', -'edit_folder_attrdefgrp' => '', -'edit_folder_notify' => 'Zoznam upozornení', -'edit_folder_props' => 'Uprav priečinok', +'edit_folder_attrdefgrp' => 'Edit attribute groups', +'edit_folder_notify' => 'Zoznam notifikácií', +'edit_folder_props' => 'Upraviť zložku', 'edit_group' => 'Upraviť skupinu', 'edit_online' => 'Upraviť online', -'edit_task' => '', -'edit_transmittal_props' => '', +'edit_task' => 'Upraviť úlohu', +'edit_transmittal_props' => 'Edit transmittal properties', 'edit_user' => 'Upraviť používateľa', 'edit_user_details' => 'Upraviť podrobnosti používateľa', 'edit_version' => 'Upraviť verziu', @@ -422,30 +489,35 @@ URL: [url]', 'email' => 'Email', 'email_error_title' => 'Nebol zadaný žiadny E-mail', 'email_footer' => 'Nastavenia e-mailu si kedykoľvek môžete zmeniť cez \'Môj účet\'', -'email_header' => 'Toto je automatická správa od DMS servera.', +'email_header' => 'Toto je automatická správa od Dokument servera.', 'email_not_given' => 'Prosím, zadajte platnú emailovú adresu.', -'empty_attribute_group_list' => '', -'empty_folder_list' => 'Žiadne dokumenty alebo priečinky', -'empty_list' => '', +'empty_attribute_group_list' => 'No attribute groups', +'empty_folder_list' => 'Žiadne dokumenty alebo zložky', +'empty_list' => 'Žiadne položky', 'empty_notify_list' => 'Žiadne položky', 'en_GB' => 'Angličtina (UK)', 'equal_transition_states' => 'Začiatok a koniec sú rovnaké', 'error' => 'Chyba', -'error_add_aro' => '', -'error_add_permission' => '', +'error_add_aro' => 'Error while adding access request object', +'error_add_permission' => 'Error while add permission', 'error_cleared_cache' => 'Chyba pri vymazaní vyrovnávacej pamäte', -'error_extension_getlist' => '', -'error_importfs' => '', +'error_edit_task' => '', +'error_extension_getlist' => 'Error getting extension list from repository', +'error_importfs' => 'Chyba pri importe zo súborového systému', 'error_no_document_selected' => 'Nie je vybratý žiadny dokument', 'error_no_folder_selected' => 'Nie je vybratá žiadna zložka', 'error_occured' => 'Vyskytla sa chyba', 'error_remove_document' => 'Pri odstraňovaní dokumentu sa vyskytla chyba', 'error_remove_folder' => 'Pri odstraňovaní zložky sa vyskytla chyba', 'error_remove_permission' => 'Chyba pri odstránení povolenia', +'error_rm_workflow' => '', +'error_rm_workflow_action' => '', +'error_rm_workflow_state' => '', 'error_toogle_permission' => 'Chyba pri zmene povolenia', -'error_transfer_document' => '', -'error_update_document' => '', -'error_uploading_reviewer_only' => '', +'error_transfer_document' => 'Chyba pri transfere dokumentu', +'error_trigger_workflow' => '', +'error_update_document' => 'Chyba pri aktualizácii dokumentu', +'error_uploading_reviewer_only' => 'Chyba pri vytváraní dokumentu. Dokument má recenzenta, ale nemá schvaľovateľa.', 'es_ES' => 'Španielčina', 'event_details' => 'Detail udalosti', 'exclude_items' => 'Vylúčiť položky', @@ -463,65 +535,96 @@ URL: [url]', 'expire_in_2y' => 'Platnosť vyprší za 2 roky', 'expire_today' => 'Platnosť vyprší dnes', 'expire_tomorrow' => 'Platnosť vyprší zajtra', -'expiry_changed_email' => 'Datum platnosti zmeneny', -'expiry_changed_email_body' => '', +'expiry_changed_email' => 'Dátum vypršania platnosti zmenený', +'expiry_changed_email_body' => 'Dátum vypršania platnosti zmenený +Dokument: [name] +Nadradená zložka: [folder_path] +Užívateľ: [username] +URL: [url]', 'expiry_changed_email_subject' => '[sitename]: [name] - Dátum vypršania platnosti bol zmenený', 'export' => 'Exportovať', -'extension_archive' => '', -'extension_changelog' => '', -'extension_loading' => '', -'extension_manager' => 'Správa rozšírení', -'extension_mgr_installed' => '', -'extension_mgr_no_upload' => '', -'extension_mgr_repository' => '', -'extension_version_list' => '', +'extension_archive' => 'Rozšírenie', +'extension_changelog' => 'Denník zmien', +'extension_loading' => 'Nahrávajú sa rozšírenia ...', +'extension_manager' => 'Spravovať rozšírenia', +'extension_mgr_installed' => 'Inštalované', +'extension_mgr_no_upload' => 'Uploading new extensions is not possible because the extentension directory is not writable.', +'extension_mgr_repository' => 'Available', +'extension_version_list' => 'Versions', 'february' => 'Február', 'file' => 'Súbor', 'files' => 'Súbory', 'files_deletion' => 'Odstránenie súboru', -'files_deletion_warning' => 'Touto akciou môžete odstrániť celú DMS zložku. Verziovacie informácie zostanú viditeľné.', +'files_deletion_warning' => 'Touto akciou môžete odstrániť všetky súbory celých DMS zložiek. Verziovacie informácie zostanú viditeľné.', 'files_loading' => 'Prosím počkajte, kým sa načíta zoznam súborov ...', 'file_size' => 'Veľkosť súboru', 'filter_for_documents' => 'Ďalší filter pre dokumenty', 'filter_for_folders' => 'Ďalší filter pre zložky', -'folder' => 'Zlozka', +'folder' => 'Zložka', 'folders' => 'Zložky', 'folders_and_documents_statistic' => 'Prehľad zložiek a dokumentov', -'folders_with_notification' => 'Zložky s upozornením', -'folder_attribute_changed_email_body' => '', -'folder_attribute_changed_email_subject' => '', +'folders_with_notification' => 'Zložky s notifikáciou', +'folder_attribute_changed_email_body' => 'Atribút zmenený +Zložka: [name] +Atribút: [attribute_name] +Predošlá hodnota: [attribute_old_value] +Nová hodnota: [attribute_new_value] +Nadradená zložka: [folder_path] +Užívateľ: [username] +URL: [url]', +'folder_attribute_changed_email_subject' => '[sitename]: [name] - Atribút zmenený', 'folder_comment_changed_email' => 'Komentár sa zmenil', -'folder_comment_changed_email_body' => 'Komentár zmenený pre Zložku: [name] Starý komentár: [old_comment] Komentár: [new_comment] Nadradená zložka: [folder_path] Používateľ: [username] URL: [url]', +'folder_comment_changed_email_body' => 'Komentár zmenený +Zložka: [name] +Predošlý komentár: [old_comment] +Nový komentár: [new_comment] +Nadradená zložka: [folder_path] +Používateľ: [username] +URL: [url]', 'folder_comment_changed_email_subject' => '[sitename]: [name] - Komentár zmenený', 'folder_contents' => 'Obsah zložky', -'folder_deleted_email' => 'Zlozka zmazana', -'folder_deleted_email_body' => '', +'folder_deleted_email' => 'Zložka zmazaná', +'folder_deleted_email_body' => 'Zložka zmazaná +Zložka: [name] +Nadradená zložka: [folder_path] +Užívateľ: [username] +URL: [url]', 'folder_deleted_email_subject' => '[sitename]: [name] - Zložka bola odstránená', 'folder_infos' => 'Informácie o zložke', -'folder_moved_email' => 'Zlozka presunuta', -'folder_moved_email_body' => '', +'folder_moved_email' => 'Zložka presunutá', +'folder_moved_email_body' => 'Zložka bola presunutá +Zložka: [name] +Predošlá zložka: [old_folder_path] +Nová zložka: [new_folder_path] +Používateľ: [username] +URL: [url]', 'folder_moved_email_subject' => '[sitename]: [name] - Zložka bola presunutá', -'folder_renamed_email' => 'Zlozka premenovana', -'folder_renamed_email_body' => 'Zložka bola premenovaná Zložka: [name] Nadradená zložka: [folder_path] Starý názov: [old_name] Používateľ: [username] URL: [url]', +'folder_renamed_email' => 'Zložka premenovaná', +'folder_renamed_email_body' => 'Zložka bola premenovaná +Zložka: [name] +Nadradená zložka: [folder_path] +Predošlý názov: [old_name] +Používateľ: [username] +URL: [url]', 'folder_renamed_email_subject' => '[sitename]: [name] - Zložka bola premenovaná', 'folder_title' => 'Zložka \'[foldername]\'', -'force_update' => '', +'force_update' => 'Aktualizovať', 'friday' => 'Piatok', 'friday_abbr' => 'Pia', 'from' => 'Od', 'fr_FR' => 'Francúzština', 'fullsearch' => 'Fulltext index vyhľadávanie', 'fullsearch_hint' => 'Použiť fulltext index', -'fulltextsearch_disabled' => 'Fulltext index ze zakázaný', -'fulltext_converters' => '', +'fulltextsearch_disabled' => 'Fulltext index je zakázaný', +'fulltext_converters' => 'Index document conversion', 'fulltext_info' => 'Informácie o fulltext indexe', -'global_attributedefinitiongroups' => '', +'global_attributedefinitiongroups' => 'Skupiny atribútov', 'global_attributedefinitions' => 'Atribúty', 'global_default_keywords' => 'Globálne kľúčové slová', 'global_document_categories' => 'Kategórie', -'global_workflows' => 'Pracovný postup', -'global_workflow_actions' => '', -'global_workflow_states' => '', +'global_workflows' => 'Pracovné postupy', +'global_workflow_actions' => 'Workflow Actions', +'global_workflow_states' => 'Workflow States', 'group' => 'Skupina', 'groups' => 'Skupiny', 'group_approval_summary' => 'Zhrnutie skupinového schválenia', @@ -529,26 +632,26 @@ URL: [url]', 'group_info' => 'Informácie o skupine', 'group_management' => 'Skupiny', 'group_members' => 'Členovia skupiny', -'group_receipt_summary' => '', +'group_receipt_summary' => 'Group receipt summary', 'group_review_summary' => 'Zhrnutie skupinovej recenzie', 'guest_login' => 'Prihlásiť sa ako hosť', 'guest_login_disabled' => 'Prihlásenie ako hosť je vypnuté.', -'hash' => '', +'hash' => 'Hash', 'help' => 'Pomoc', 'home_folder' => 'Domovská zložka', -'hook_name' => '', -'hourly' => 'Hodiny', +'hook_name' => 'Name of hook', +'hourly' => 'Každú hodinu', 'hours' => 'hodiny', 'hr_HR' => 'Chorváčtina', -'human_readable' => 'Použivateľský archív', +'human_readable' => 'Čitateľný archív', 'hu_HU' => 'Maďarčina', 'id' => 'ID', -'identical_version' => '', +'identical_version' => 'Nová verzia je identická s terajšou.', 'import' => 'Importovať', 'importfs' => 'Importovať zo súborového systému', -'import_extension' => '', +'import_extension' => 'Import extension', 'import_fs' => 'Importovanie zo súborového systému', -'import_fs_warning' => '', +'import_fs_warning' => 'This will only work for folders in the drop folder. The operation recursively imports all folders and files. Files will be released immediately.', 'include_content' => 'Zahrnúť obsah', 'include_documents' => 'Vrátane súborov', 'include_subdirectories' => 'Vrátane podzložiek', @@ -557,13 +660,12 @@ URL: [url]', 'index_done' => 'Hotovo', 'index_error' => 'Chyba', 'index_folder' => 'Indexovať zložku', -'index_no_content' => '', -'index_pending' => '', +'index_no_content' => 'Did not index content', +'index_pending' => 'Pending', 'index_waiting' => 'Čakajte', 'individuals' => 'Jednotlivci', 'individuals_in_groups' => 'Členovia skupiny', -'indivіduals_in_groups' => '', -'info_recipients_tab_not_released' => '', +'info_recipients_tab_not_released' => 'Acknowledgement of reception for this document version is not possible, because the version is not released.', 'inherited' => 'zdedené', 'inherits_access_copy_msg' => 'Skopírovať zdedený zoznam riadenia prístupu', 'inherits_access_empty_msg' => 'Založiť nový zoznam riadenia prístupu', @@ -576,15 +678,15 @@ URL: [url]', 'invalid_create_date_end' => 'Neplatný koncový dátum vytvorenia.', 'invalid_create_date_start' => 'Neplatný počiatočný dátum vytvorenia.', 'invalid_doc_id' => 'Neplatný ID dokumentu', -'invalid_dropfolder_folder' => '', -'invalid_expiration_date_end' => '', -'invalid_expiration_date_start' => '', +'invalid_dropfolder_folder' => 'Invalid folder in drop folder', +'invalid_expiration_date_end' => 'Invalid end date for expiration date range.', +'invalid_expiration_date_start' => 'Invalid start date for expiration date range.', 'invalid_file_id' => 'Nesprávne ID súboru', 'invalid_folder_id' => 'Neplatný ID zložky', 'invalid_group_id' => 'Neplatný ID skupiny', 'invalid_link_id' => 'Neplatný ID odkazu', 'invalid_request_token' => 'Invalid Request Token', -'invalid_review_status' => 'Neplatný stav kontroly', +'invalid_review_status' => 'Neplatný stav recenzie', 'invalid_sequence' => 'Neplatná hodnota postupnosti', 'invalid_status' => 'Neplatný stav dokumentu', 'invalid_target_doc_id' => 'Neplatné cieľové ID dokumentu', @@ -598,8 +700,8 @@ URL: [url]', 'is_hidden' => 'Nezobrazovať v zozname používateľov', 'it_IT' => 'Taliančina', 'january' => 'Január', -'js_form_error' => '', -'js_form_errors' => '', +'js_form_error' => 'The form still contains # error.', +'js_form_errors' => 'The form still contains # errors.', 'js_invalid_email' => 'E-mailová adresa je neplatná', 'js_no_approval_group' => 'Prosím, vyberte skupinu pre schválenie', 'js_no_approval_status' => 'Prosím, vyberte stav schválenia', @@ -613,12 +715,12 @@ URL: [url]', 'js_no_override_status' => 'Prosím, vyberte nový stav [prepíše sa]', 'js_no_pwd' => 'Budete musieť napísať svoje heslo', 'js_no_query' => 'Napíšte požiadavku', -'js_no_review_group' => 'Prosím, vyberte skupinu pre kontrolu', -'js_no_review_status' => 'Prosím, vyberte stav kontroly', +'js_no_review_group' => 'Prosím, vyberte skupinu pre recenziu', +'js_no_review_status' => 'Prosím, vyberte stav recenzie', 'js_pwd_not_conf' => 'Heslo a potvrdenie hesla sa nezhodujú', 'js_select_user' => 'Prosím, vyberte používateľa', 'js_select_user_or_group' => 'Vyberte aspoň používateľa alebo skupinu', -'js_unequal_passwords' => '', +'js_unequal_passwords' => 'Heslá nie sú zhodné', 'july' => 'Júl', 'june' => 'Jún', 'keep' => 'Nemeňte', @@ -637,64 +739,67 @@ URL: [url]', 'linked_to_current_version' => 'Prepojené s aktuálnou verziou', 'linked_to_document' => 'Prepojené s dokumentom', 'linked_to_this_version' => 'Prepojené s touto verziou', -'link_alt_updatedocument' => '', +'link_alt_updatedocument' => 'If you would like to upload files bigger than the current maximum upload size, please use the alternative upload page.', 'link_to_version' => 'Pripojiť k verzii', -'list_access_rights' => 'Uveďte všetky prístupové práva', -'list_contains_no_access_docs' => '', -'list_hooks' => '', -'list_tasks' => '', +'list_access_rights' => 'Zobraziť všetky prístupové práva', +'list_contains_no_access_docs' => 'Zoznam obsahuje viac dokumentov, ku ktorým nemáte prístup a nie sú zobrazené.', +'list_hooks' => 'List hooks', +'list_tasks' => 'List tasks', 'local_file' => 'Lokálny súbor', 'locked_by' => 'Uzamkol', 'lock_document' => 'Zamknúť', -'lock_message' => 'Tento dokument zamkol [username]. Iba oprávnení používatelia ho môžu odomknúť (pozri koniec stránky).', +'lock_message' => 'Tento dokument zamkol [username]. Iba oprávnení používatelia ho môžu odomknúť.', 'lock_status' => 'Stav', 'login' => 'Prihlásiť sa', -'login_disabled_text' => 'Vaše konto bolo zakázané, pravdepodobne veľa pokusov o prihlásenie zlyhalo.', -'login_disabled_title' => 'Účet je zakázaný', +'login_disabled_text' => 'Váš účet bol zablokovaný, pravdepodobne veľa pokusov o prihlásenie zlyhalo.', +'login_disabled_title' => 'Účet je zablokovaný', 'login_error_text' => 'Chyba pri prihlasovaní. ID používateľa alebo heslo je nesprávne.', 'login_error_title' => 'Chyba pri prihlasovaní', 'login_not_given' => 'Nebolo zadané používateľské meno', 'login_ok' => 'Prihlásenie prebehlo úspešne', +'login_restrictions_apply' => '', 'logout' => 'Odhlásenie', 'log_management' => 'Správa protokolov', -'lo_LA' => '', -'manager' => 'Manager', +'lo_LA' => 'Laoský', +'malformed_expiration_date' => '', +'manager' => 'Manažér', 'manager_of_group' => 'Ste správcom tejto skupiny', -'mandatory_approvergroups' => '', -'mandatory_approvergroup_no_access' => '', -'mandatory_approvers' => '', -'mandatory_approver_no_access' => '', -'mandatory_reviewergroups' => '', -'mandatory_reviewergroup_no_access' => '', -'mandatory_reviewers' => '', -'mandatory_reviewer_no_access' => '', +'mandatory_approvergroups' => 'Mandatory Groups of approvers', +'mandatory_approvergroup_no_access' => 'Mandatory group of approvers \'[group]\' has insufficient access rights.', +'mandatory_approvers' => 'Mandatory approvers', +'mandatory_approver_no_access' => 'Mandatory approver \'[user]\' has insufficient access rights.', +'mandatory_reviewergroups' => 'Mandatory group of reviewers', +'mandatory_reviewergroup_no_access' => 'Mandatory group of reviewers \'[group]\' has insufficient access rights.', +'mandatory_reviewers' => 'Mandatory reviewers', +'mandatory_reviewer_no_access' => 'Mandatory reviewer \'[user]\' has insufficient access rights.', 'march' => 'Marec', 'max_upload_size' => 'Maximálna veľkosť každého súboru', 'may' => 'Máj', 'menu_dropfolder' => 'Drop zložka', +'menu_upload_from_dropfolder' => '', 'mimetype' => 'Mime typ', 'minutes' => 'minúty', 'misc' => 'Rôzne', -'missing_checksum' => '', +'missing_checksum' => 'Chýba kontrolný súčet', 'missing_file' => 'Chýba súbor', 'missing_filesize' => 'Chýba veľkosť súboru', -'missing_reception' => '', -'missing_request_object' => '', -'missing_transition_user_group' => '', +'missing_reception' => 'Missing reception', +'missing_request_object' => 'Chýba požadovaný objekt', +'missing_transition_user_group' => 'Chýba používateľ/skupina pre prenos', 'monday' => 'Pondelok', 'monday_abbr' => 'Po', 'monthly' => 'Mesačne', 'month_view' => 'Mesiac', -'more_objects_loading' => '', +'more_objects_loading' => 'Načítavajú sa ďalšie objekty ...', 'move' => 'Presunúť', 'move_clipboard' => 'Presunúť schránku', 'move_document' => 'Presunúť dokument', 'move_folder' => 'Presunúť zložku', 'my_account' => 'Môj účet', 'my_documents' => 'Moje dokumenty', -'my_transmittals' => '', +'my_transmittals' => 'My Transmittals', 'name' => 'Meno', -'needs_correction' => '', +'needs_correction' => 'Vyžaduje opravu', 'needs_workflow_action' => 'Tento dokument si vyžaduje vašu pozornosť. Skontrolujte kartu pracovného postupu.', 'network_drive' => 'Sieťová jednotka', 'never' => 'nikdy', @@ -703,105 +808,143 @@ URL: [url]', 'new_default_keywords' => 'Pridať kľúčové slová', 'new_default_keyword_category' => 'Pridať kategóriu', 'new_document_category' => 'Pridať kategóriu', -'new_document_email' => 'Novy dokument', -'new_document_email_body' => '', +'new_document_email' => 'Nový dokument', +'new_document_email_body' => 'Nový dokument +Meno: [name] +Nadradená zložka: [folder_path] +Komentár: [comment] +Komentár k verzii: [version_comment] +Používateľ: [username] +URL: [url]', 'new_document_email_subject' => '[sitename]: [folder_name] - Nový dokument', -'new_file_email' => 'Nova priloha', -'new_file_email_body' => '', +'new_file_email' => 'Nová príloha', +'new_file_email_body' => 'Nová príloha +Meno: [name] +Dokument: [document] +Komentár: [comment] +Používateľ: [username] +URL: [url]', 'new_file_email_subject' => '[sitename]: [document] - Nová príloha', 'new_folder' => 'Nová zložka', 'new_password' => 'Nové heslo', -'new_subfolder_email' => 'Nova zlozka', -'new_subfolder_email_body' => '', +'new_subfolder_email' => 'Nová zložka', +'new_subfolder_email_body' => 'Nová zložka +Meno: [name] +Nadradená zložka: [folder_path] +Komentár: [comment] +Používateľ: [username] +URL: [url]', 'new_subfolder_email_subject' => '[sitename]: [name] - Nová zložka', 'new_user_image' => 'Nový obrázok', 'next_state' => 'Nový stav', 'nl_NL' => 'Holandština', 'no' => 'Nie', -'notify_added_email' => 'Boli ste pridani do notifikacneho zoznamu', -'notify_added_email_body' => '', -'notify_added_email_subject' => '[sitename]: [name] - Pridané do zoznamu oznámení', -'notify_deleted_email' => 'Boli ste odstraneni do notifikacneho zoznamu', -'notify_deleted_email_body' => '', -'notify_deleted_email_subject' => '', +'notify_added_email' => 'Boli ste pridaní do notifikačného zoznamu', +'notify_added_email_body' => 'Pridanie do notifikačného zoznamu +Meno: [name] +Nadradená zložka: [folder_path] +Používateľ: [username] +URL: [url]', +'notify_added_email_subject' => '[sitename]: [name] - Pridané do zoznamu notifikácií', +'notify_deleted_email' => 'Boli ste odstránení z notifikačného zoznamu', +'notify_deleted_email_body' => 'Odstránené z notifikačného zoznamu +Meno: [name] +Nadradená zložka: [folder_path] +Používateľ: [username] +URL: [url]', +'notify_deleted_email_subject' => '[sitename]: [name] - Odstránené z notifikačného zoznamu', 'november' => 'November', 'now' => 'teraz', 'no_action' => 'Nič sa nevykoná', -'no_approval_needed' => '', +'no_approval_needed' => 'Neprebieha žiadne schvaľovanie.', 'no_attached_files' => 'Žiadne prílohy', -'no_current_version' => '', +'no_current_version' => 'Neaktualizovaná verzia', 'no_default_keywords' => 'Nie sú dostupné žiadne kľúčové slová.', -'no_docs_checked_out' => '', -'no_docs_locked' => '', -'no_docs_needs_correction' => '', +'no_docs_checked_out' => 'No documents checked out', +'no_docs_locked' => 'Žiadne uzamknuté dokumenty.', +'no_docs_needs_correction' => 'Žiadne dokumenty potrebné opraviť', 'no_docs_rejected' => 'Žiadne dokumenty neboli zamietnuté.', 'no_docs_to_approve' => 'Momentálne neexistujú žiadne dokumenty, ktoré vyžadujú schválenie.', 'no_docs_to_look_at' => 'Žiadne dokumenty, ktoré potrebujú pozornosť.', 'no_docs_to_receipt' => 'Žiadne dokumenty, ktoré požadujú potvrdenie.', -'no_docs_to_review' => 'Momentálne neexistujú žiadne dokumenty, ktoré vyžadujú kontrolu.', -'no_docs_to_revise' => '', -'no_email_or_login' => '', -'no_fulltextindex' => '', +'no_docs_to_review' => 'Momentálne neexistujú žiadne dokumenty, ktoré vyžadujú recenziu.', +'no_docs_to_revise' => 'There are currently no documents that need to be revised.', +'no_email_or_login' => 'Login a email treba zadať', +'no_fulltextindex' => 'Fulltextový index nie je k dispozícii', 'no_groups' => 'Žiadne skupiny', 'no_group_members' => 'Táto skupina nemá žiadnych členov', 'no_linked_files' => 'No linked files', 'no_previous_versions' => 'Neboli nájdené žiadne iné verzie', -'no_receipt_needed' => '', +'no_receipt_needed' => 'There are currently no documents requiring a receipt confirmation.', 'no_review_needed' => 'No review pending.', -'no_revision_needed' => '', -'no_revision_planed' => '', -'no_update_cause_locked' => 'Preto nemôžete aktualizovať tento dokument. Prosím, kontaktujte používateľa, ktorý ho zamkol.', +'no_revision_needed' => 'No revision pending.', +'no_revision_planed' => 'No revision of document scheduled', +'no_update_cause_locked' => 'Preto nemôžete aktualizovať tento dokument. Kontaktujte používateľa, ktorý ho zamkol.', 'no_user_image' => 'nebol nájdený žiadny obrázok', -'no_version_check' => '', +'no_version_check' => 'Checking for a new version of SeedDMS has failed! This could be caused by allow_url_fopen being set to 0 in your php configuration.', 'no_version_modification' => 'Žiadne zmeny', -'no_workflow_available' => '', +'no_workflow_available' => 'Nie je k dispozícii žiaden workflow', 'objectcheck' => 'Kontrola Adresárov/Dokumentov', 'object_check_critical' => 'Kritické chyby', 'object_check_warning' => 'Varovanie', 'obsolete' => 'Zastaralé', 'october' => 'Október', -'old' => 'Stare', +'old' => 'Staré', 'only_jpg_user_images' => 'Ako obrázky používateľov je možné použiť iba obrázky .jpg', -'order_by_sequence_off' => '', +'order_by_sequence_off' => 'Ordering by sequence is turned off in the settings. If you want this parameter to have effect, you will have to turn it back on.', 'original_filename' => 'Pôvodný názov súboru', 'overall_indexing_progress' => 'Celkový priebeh indexovania', 'owner' => 'Vlastník', -'ownership_changed_email' => 'Majitel zmeneny', -'ownership_changed_email_body' => '', -'ownership_changed_email_subject' => '[sitename]: [name] - Vlastník sa zmenil', +'ownership_changed_email' => 'Vlastník zmenený', +'ownership_changed_email_body' => 'Owner changed +Dokument: [name] +Nadradená zložka: [folder_path] +Predošlý vlastník: [old_owner] +Nový vlastník: [new_owner] +Používateľ: [username] +URL: [url]', +'ownership_changed_email_subject' => '[sitename]: [name] - Vlastník zmenený', 'password' => 'Heslo', 'password_already_used' => 'Heslo sa už používa', 'password_expiration' => 'Vypršanie hesla', -'password_expiration_text' => '', +'password_expiration_text' => 'Vaše heslo vypršalo. Zadajte si nové, aby ste sa mohli prihlásiť.', 'password_expired' => 'Heslo vypršalo', 'password_expires_in_days' => 'Heslo vyprší za %s dní.', 'password_forgotten' => 'Zabudnuté heslo', -'password_forgotten_email_body' => '', +'password_forgotten_email_body' => 'Dear user of SeedDMS, + +we have received a request to change your password. + +This can be done by clicking on the following link: + +[url_prefix]out/out.ChangePassword.php?hash=[hash] + +If you have still problems to login, then please contact your administrator.', 'password_forgotten_email_subject' => '[sitename]: Zabudnuté heslo', -'password_forgotten_send_hash' => '', -'password_forgotten_text' => '', +'password_forgotten_send_hash' => 'Instructions on how to proceed has been send to the user\'s email address', +'password_forgotten_text' => 'Fill out the form below and follow the instructions in the email, which will be sent to you.', 'password_forgotten_title' => 'Heslo bolo odoslané', 'password_repeat' => 'Zopakovať heslo', 'password_send' => 'Odoslať heslo', -'password_send_text' => '', +'password_send_text' => 'Your new password has been send to the given email address, if the login and email matches an existing user. If you do not receive an email within the next minutes, then make sure both login and email are correct and restart the process again.', 'password_strength' => 'Sila hesla', 'password_strength_insuffient' => 'Nedostatočná sila hesla', 'password_wrong' => 'Zlé heslo', -'pdf_converters' => '', +'pdf_converters' => 'PDF converters', 'pending_approvals' => 'Čakajúce schválenia', 'pending_receipt' => 'Čakajúci príjemcovia', 'pending_reviews' => 'Čakajúce recenzie', -'pending_revision' => '', -'pending_workflows' => '', +'pending_revision' => 'Pending revisions', +'pending_workflows' => 'Pending workflows', 'personal_default_keywords' => 'Osobné kľúčové slová', -'pl_PL' => 'Polština', -'possible_substitutes' => '', -'preset_expires' => '', +'pl_PL' => 'Poľština', +'possible_substitutes' => 'Substitutes', +'preset_expires' => 'Preset expiration', 'preview' => 'Náhľad', 'preview_converters' => 'Ukážka konverzie dokumentu', 'preview_images' => 'Náhľad obrázkov', 'preview_markdown' => 'Markdown', -'preview_pdf' => '', +'preview_pdf' => 'Preview as PDF', 'preview_plain' => 'Text', 'previous_state' => 'Predchádzajúci stav', 'previous_versions' => 'Predošlé verzie', @@ -812,98 +955,160 @@ URL: [url]', 'quota_exceeded' => 'Vaša disková kvóta bola prekročená o [bytes].', 'quota_is_disabled' => 'Podpora kvót je momentálne zakázaná v nastaveniach. Nastavenie kvóty používateľa nebude mať žiadny účinok, kým nebude znovu aktivovaná.', 'quota_warning' => 'Maximálne využitie disku je prekročené o [bytes]. Odstráňte dokumenty alebo predchádzajúce verzie.', -'receipts_accepted' => '[no_receipts] príjemcovia už prijatí', -'receipts_not_touched' => '[no_receipts] príjemcovia nedotknutí', -'receipts_rejected' => '', -'receipts_without_group' => '', -'receipts_without_user' => '', -'receipt_deletion_email_body' => '', -'receipt_deletion_email_subject' => '', -'receipt_log' => '', -'receipt_request_email_body' => '', -'receipt_request_email_subject' => '', +'receipts_accepted' => '[no_receipts] receipts already accepted', +'receipts_not_touched' => '[no_receipts] receipts not being touched', +'receipts_rejected' => '[no_receipts] receipts already rejected', +'receipts_without_group' => 'Receipts without group', +'receipts_without_user' => 'Receipts without user', +'receipt_deletion_email_body' => 'Používateľ bol odstránený zo zoznamu recipientov +Dokument: [name] +Verzia: [version] +Nadradená zložka: [folder_path] +Recipient: [recipient] +Používateľ: [username] +URL: [url]', +'receipt_deletion_email_subject' => '[sitename]: [name] - Recipient odstránený', +'receipt_log' => 'Reception Log', +'receipt_request_email_body' => 'Reception request +Dokument: [name] +Verzia: [version] +Nadradená zložka: [folder_path] +Používateľ: [username] +URL: [url]', +'receipt_request_email_subject' => '[sitename]: [name] - Reception request', 'receipt_status' => 'Stav', -'receipt_summary' => '', -'receipt_update_failed' => '', -'reception' => '', -'reception_acknowleged' => '', +'receipt_summary' => 'Receipt summary', +'receipt_update_failed' => 'Acknowledging reception failed', +'reception' => 'Reception', +'reception_acknowleged' => 'Reception acknowledged', 'reception_noaction' => 'Žiadna akcia', -'reception_rejected' => '', +'reception_rejected' => 'Reception rejected', 'recipients' => 'Príjemcovia', 'redraw' => 'Prekresliť', 'refresh' => 'Obnoviť', 'rejected' => 'Odmietnuté', 'released' => 'Vydané', 'removed_approver' => 'bol odstránený zo zoznamu schvaľovateľov.', -'removed_file_email' => 'Odstranena priloha', -'removed_file_email_body' => '', +'removed_file_email' => 'Odstránená príloha', +'removed_file_email_body' => 'Odstránená príloha +Dokument: [document] +Používateľ: [username] +URL: [url]', 'removed_file_email_subject' => '[sitename]: [document] - Príloha bola odstránená', -'removed_recipient' => '', -'removed_reviewer' => 'bol odstránený zo zoznamu kontrolórov.', -'removed_revisor' => '', -'removed_workflow_email_body' => '', -'removed_workflow_email_subject' => '', -'removeFolderFromDropFolder' => 'Po importu odstráňte zložku', -'remove_marked_files' => 'Zrušiť označenie súborov', +'removed_recipient' => 'bol odstránený zo zoznamu recipientov.', +'removed_reviewer' => 'bol odstránený zo zoznamu recenzentov.', +'removed_revisor' => 'has been removed from the list of revisors.', +'removed_workflow_email_body' => 'Removed workflow from document version +Document: [name] +Version: [version] +Workflow: [workflow] +Parent folder: [folder_path] +User: [username] +URL: [url]', +'removed_workflow_email_subject' => '[sitename]: [name] - Removed workflow from document version', +'removeFolderFromDropFolder' => 'Po importe odstrániť zložku', +'remove_marked_files' => 'Odstrániť označené súbory', 'repaired' => 'opravené', 'repairing_objects' => 'Oprava dokumentov a zložiek.', -'request_workflow_action_email_body' => '', -'request_workflow_action_email_subject' => '', -'reset_checkout' => '', +'request_workflow_action_email_body' => 'The workflow has reached a state which requires your action. +Document: [name] +Version: [version] +Workflow: [workflow] +Current state: [current_state] +Parent folder: [folder_path] +User: [username] +URL: [url]', +'request_workflow_action_email_subject' => '[sitename]: [name] - Workflow action required', +'reset_checkout' => 'Finish Check out', 'restrict_access' => 'Žiadny prístup k', 'results_page' => 'Výsledky', -'return_from_subworkflow' => '', -'return_from_subworkflow_email_body' => '', -'return_from_subworkflow_email_subject' => '', +'return_from_subworkflow' => 'Return from sub workflow', +'return_from_subworkflow_email_body' => 'Return from subworkflow +Document: [name] +Version: [version] +Workflow: [workflow] +Subworkflow: [subworkflow] +Parent folder: [folder_path] +User: [username] +URL: [url]', +'return_from_subworkflow_email_subject' => '[sitename]: [name] - Return from subworkflow', 'reverse_links' => 'Dokumenty, ktoré majú odkaz na aktuálny dokument', -'reviewers' => 'Kontrolóri', -'reviewer_already_assigned' => 'je už poverený ako kontrolór', -'reviewer_already_removed' => 'už bol odstránený z procesu kontroly alebo poslal kontrolu', -'reviews_accepted' => '', -'reviews_not_touched' => '', -'reviews_rejected' => '', -'reviews_without_group' => '', -'reviews_without_user' => '', -'review_deletion_email' => 'Poziadavka na recenziu zmazana', -'review_deletion_email_body' => '', -'review_deletion_email_subject' => '', +'reviewers' => 'Recenzenti', +'reviewer_already_assigned' => 'je už poverený ako recenzent', +'reviewer_already_removed' => 'už bol odstránený z procesu recenzie alebo už odoslal recenziu', +'reviews_accepted' => '[no_reviews] reviews already accepted', +'reviews_not_touched' => '[no_reviews] reviews not being touched', +'reviews_rejected' => '[no_reviews] reviews already rejected', +'reviews_without_group' => 'Reviews without group', +'reviews_without_user' => 'Reviews without user', +'review_deletion_email' => 'Požiadavka na recenziu zmazaná', +'review_deletion_email_body' => 'Požiadavka na recenziu zmazaná +Dokument: [name] +Verzia: [version] +Nadradená zložka: [folder_path] +Používateľ: [username] +URL: [url]', +'review_deletion_email_subject' => '[sitename]: [name] - Požiadavka na recenziu zmazaná', 'review_file' => 'Súbor', -'review_group' => 'Skupina kontroly', +'review_group' => 'Skupina recenzie', 'review_log' => 'Denník recenzií', -'review_request_email' => 'Poziadavka na recenziu', -'review_request_email_body' => '', -'review_request_email_subject' => '', -'review_status' => 'Stav kontroly', -'review_submit_email' => 'Poslana recenzia', -'review_submit_email_body' => '', -'review_submit_email_subject' => '', -'review_summary' => 'Zhrnutie kontroly', -'review_update_failed' => 'Chyba pri aktualizácii stavu kontroly. Aktualizácia zlyhala.', -'revise_document' => 'Revidujte dokument', -'revise_document_on' => '', -'revisions_accepted' => '', -'revisions_not_touched' => '', -'revisions_pending' => '', -'revisions_rejected' => '', +'review_request_email' => 'Požiadavka na recenziu', +'review_request_email_body' => 'Požiadavka na recenziu +Dokument: [name] +Verzia: [version] +Nadradená zložka: [folder_path] +Používateľ: [username] +URL: [url]', +'review_request_email_subject' => '[sitename]: [name] - Požiadavka na recenziu', +'review_status' => 'Stav recenzie', +'review_submit_email' => 'Odoslaná recenzia', +'review_submit_email_body' => 'Odoslaná recenzia +Dokument: [name] +Verzia: [version] +Stav: [status] +Komentár: [comment] +Nadradená zložka: [folder_path] +Používateľ: [username] +URL: [url]', +'review_submit_email_subject' => '[sitename]: [name] - Odoslaná recenzia', +'review_summary' => 'Zhrnutie recenzie', +'review_update_failed' => 'Chyba pri aktualizácii stavu recenzie. Aktualizácia zlyhala.', +'revise_document' => 'Revidovať dokument', +'revise_document_on' => 'Next revision of document version on [date]', +'revisions_accepted' => '[no_revisions] revisions already accepted', +'revisions_not_touched' => '[no_revisions] revisions not being touched', +'revisions_pending' => '[no_revisions] revisions due in future', +'revisions_rejected' => '[no_revisions] revisions already rejected', 'revisions_without_group' => 'Revízie bez skupiny', 'revisions_without_user' => 'Revízie bez používateľa', 'revision_date' => 'Dátum revízie', 'revision_log' => 'Protokol revízie', -'revision_request_email_body' => '', -'revision_request_email_subject' => '', +'revision_request_email_body' => 'Žiadosť o revíziu +Dokument: [name] +Verzia: [version] +Nadradený priečinok: [folder_path] +Používateľ: [username] +URL: [url]', +'revision_request_email_subject' => '[sitename]: [name] - Žiadosť o revíziu', 'revision_status' => 'Stav', 'revision_submit_email_body' => '', 'revision_submit_email_subject' => '', -'revisors' => '', -'revisor_already_assigned' => '', -'revisor_already_removed' => '', -'rewind_workflow' => '', -'rewind_workflow_email_body' => '', -'rewind_workflow_email_subject' => '', -'rewind_workflow_warning' => '', +'revisors' => 'Revisors', +'revisor_already_assigned' => 'User is already assigned as an revisor.', +'revisor_already_removed' => 'Revisor has already been removed from revision process or has already revised the document.', +'rewind_workflow' => 'Rewind workflow', +'rewind_workflow_email_body' => 'Workflow was rewinded +Document: [name] +Version: [version] +Workflow: [workflow] +Parent folder: [folder_path] +User: [username] +URL: [url]', +'rewind_workflow_email_subject' => '[sitename]: [name] - Workflow was rewinded', +'rewind_workflow_warning' => 'If you rewind a workflow to its initial state, then the whole workflow log for this document will be deleted and cannot be recovered.', 'rm_attrdef' => 'Odstrániť definíciu atribútu', -'rm_attrdefgroup' => '', -'rm_attr_value' => '', +'rm_attrdefgroup' => 'Odstrániť túto skupinu atribútov', +'rm_attr_value' => 'Odstrániť hodnotu', 'rm_default_keyword_category' => 'Zmazať kategóriu', 'rm_document' => 'Odstrániť dokument', 'rm_document_category' => 'Odstrániť kategóriu', @@ -913,36 +1118,43 @@ URL: [url]', 'rm_from_clipboard' => 'Odstrániť zo schránky', 'rm_group' => 'Odstrániť túto skupinu', 'rm_role' => 'Odstrániť túto rolu', -'rm_transmittal' => '', +'rm_transmittal' => 'Remove transmittal', 'rm_transmittalitem' => 'Odstrániť položku', 'rm_user' => 'Odstrániť tohto používateľa', 'rm_user_from_processes' => 'Odstrániť používateľa z procesu', 'rm_version' => 'Odstrániť verziu', 'rm_workflow' => 'Odstrániť pracovný postup', -'rm_workflow_action' => '', -'rm_workflow_state' => '', -'rm_workflow_warning' => '', +'rm_workflow_action' => 'Remove Workflow Action', +'rm_workflow_state' => 'Remove Workflow State', +'rm_workflow_warning' => 'You are about to remove the workflow from the document. This cannot be undone.', 'role' => 'Rola', 'role_admin' => 'Administrátor', 'role_guest' => 'Hosť', 'role_info' => 'Informácia', -'role_management' => '', +'role_management' => 'Správa rolí', 'role_name' => 'Názov role', 'role_type' => 'Typ role', 'role_user' => 'Používateľ', 'ro_RO' => 'Rumunština', -'run_subworkflow' => '', -'run_subworkflow_email_body' => '', -'run_subworkflow_email_subject' => '', +'run_subworkflow' => 'Run sub workflow', +'run_subworkflow_email_body' => 'Subworkflow was started +Document: [name] +Version: [version] +Workflow: [workflow] +Subworkflow: [subworkflow] +Parent folder: [folder_path] +User: [username] +URL: [url]', +'run_subworkflow_email_subject' => '[sitename]: [name] - Subworkflow was started', 'ru_RU' => 'Ruština', 'saturday' => 'Sobota', 'saturday_abbr' => 'So', 'save' => 'Uložiť', -'scheduler_class' => '', -'scheduler_class_description' => '', -'scheduler_class_parameter' => '', -'scheduler_class_tasks' => '', -'scheduler_task_mgr' => '', +'scheduler_class' => 'Class', +'scheduler_class_description' => 'Description', +'scheduler_class_parameter' => 'Parameter', +'scheduler_class_tasks' => 'Tasks of class', +'scheduler_task_mgr' => 'Scheduler', 'search' => 'Hľadať', 'search_fulltext' => 'Vyhľadávanie vo fulltexte', 'search_in' => 'Prehľadávať', @@ -961,286 +1173,295 @@ URL: [url]', 'search_time' => 'Uplynulý čas: [time] sek', 'seconds' => 'sekundy', 'selection' => 'Výber', -'select_attrdefgrp_show' => '', -'select_attribute_value' => '', +'select_attrdefgrp_show' => 'Choose when to show', +'select_attribute_value' => 'Vyberte hodnotu atribútu', 'select_category' => 'Vyber kategóriu', -'select_group' => '', -'select_groups' => '', -'select_grp_approvers' => '', +'select_group' => 'Vybrať skupinu', +'select_groups' => 'Kliknutím vyberte skupiny', +'select_grp_approvers' => 'Kliknutím vyberte schvaľovateľa skupiny', 'select_grp_ind_approvers' => 'Kliknutím vyberte skupinu', 'select_grp_ind_notification' => 'Kliknutím vyberte skupinu', 'select_grp_ind_recipients' => 'Kliknutím vyberte skupinu', 'select_grp_ind_reviewers' => 'Kliknutím vyberte skupinu', -'select_grp_ind_revisors' => '', -'select_grp_notification' => 'Kliknutím vyberte upozornenie skupiny', +'select_grp_ind_revisors' => 'Kliknutím vyberte skupinu', +'select_grp_notification' => 'Kliknutím vyberte notifikáciu skupiny', 'select_grp_recipients' => 'Kliknutím vyberte skupinu príjemcov', 'select_grp_reviewers' => 'Kliknutím vyberte recenzenta skupiny', -'select_grp_revisors' => 'Kliknutím vyberte skupinu kontrolórov', -'select_ind_approvers' => 'Kliknutím vyberte individuálneho schvaľovača', -'select_ind_notification' => 'Kliknutím vyberte individuálne upozornenie', +'select_grp_revisors' => 'Kliknutím vyberte skupinu revízorov', +'select_ind_approvers' => 'Kliknutím vyberte individuálneho schvaľovateľa', +'select_ind_notification' => 'Kliknutím vyberte individuálnu notifikáciu', 'select_ind_recipients' => 'Kliknutím vyberte individuálnych príjemcov', 'select_ind_reviewers' => 'Kliknutím vyberte individuálneho recenzenta', -'select_ind_revisors' => '', -'select_one' => 'Vyberte jeden', -'select_user' => '', +'select_ind_revisors' => 'Kliknutím vyberte individuálnych revízorov', +'select_one' => 'Vyberte', +'select_user' => 'Vyberte používateľa', 'select_users' => 'Kliknutím vyberte používateľov', 'select_value' => 'Vyberte hodnotu', -'select_workflow' => '', +'select_workflow' => 'Select workflow', 'send_email' => 'Poslať E-mail', 'send_login_data' => 'Poslať prihlasovacie údaje', -'send_login_data_body' => '', +'send_login_data_body' => 'Prihlasovacie údaje + +Login: [login] +Meno: [username] + +[comment]', 'send_login_data_subject' => '[sitename]: [login] - Vaše prihlasovacie údaje', 'send_test_mail' => 'Poslať testovací E-mail', 'september' => 'September', 'sequence' => 'Postupnosť', 'seq_after' => 'Po "[prevname]"', -'seq_end' => 'Na koniec', +'seq_end' => 'Nakoniec', 'seq_keep' => 'Ponechať pozíciu', 'seq_start' => 'Prvá pozícia', 'sessions' => 'Používatelia online', -'setDateFromFile' => '', -'setDateFromFolder' => '', +'setDateFromFile' => 'Prebrať dátumy z importovaných súborov', +'setDateFromFolder' => 'Prebrať dátumy z importovaných zložiek', 'settings' => 'Nastavenia', 'settings_activate_module' => 'Aktivovať modul', 'settings_activate_php_extension' => 'Aktivovať PHP rozšírenie', 'settings_adminIP' => 'IP administrátora', -'settings_adminIP_desc' => '', +'settings_adminIP_desc' => 'If set, admin can login only by specified IP address. Leave empty to avoid lose of access. NOTE: works only with local authentication (no LDAP)', 'settings_Advanced' => 'Rozšírené', -'settings_advancedAcl' => '', -'settings_advancedAcl_desc' => '', -'settings_allowReviewerOnly' => '', -'settings_allowReviewerOnly_desc' => '', +'settings_advancedAcl' => 'Advanced Access control', +'settings_advancedAcl_desc' => 'Advanced access controll will allow to turn on/off certain modules of the software. It can not be used for access rights on documents and folders.', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', +'settings_allowReviewerOnly' => 'Allow to set reviewer only', +'settings_allowReviewerOnly_desc' => 'Enable this, if it shall be allow to set just a reviewer but no approver in traditional workflow mode.', 'settings_apache_mod_rewrite' => 'Apache - Modul Rewrite', -'settings_Authentication' => '', +'settings_Authentication' => 'Authentication settings', 'settings_autoLoginUser' => 'Automatické prihlásenie', -'settings_autoLoginUser_desc' => '', +'settings_autoLoginUser_desc' => 'Use this user id for accesses if the user is not already logged in. Such an access will not create a session.', 'settings_available_languages' => 'Dostupné jazyky', -'settings_available_languages_desc' => '', +'settings_available_languages_desc' => 'Only the selected languages will be loaded and show up in the language selector. The default language will always be loaded.', 'settings_backupDir' => 'Zložka na zálohovanie', -'settings_backupDir_desc' => '', +'settings_backupDir_desc' => 'Directory where the backup tool saves backups. If this directory is not set or cannot be accessed, then the backups will be saved in the content directory.', 'settings_cacheDir' => 'Zložka medzipamäte', -'settings_cacheDir_desc' => '', +'settings_cacheDir_desc' => 'Where the preview images are stored (best to choose a directory that is not accessible through your web-server)', 'settings_Calendar' => 'Nastavenie kalendára', 'settings_calendarDefaultView' => 'Predvolené zobrazenie kalendára', 'settings_calendarDefaultView_desc' => 'Predvolené zobrazenie kalendára', 'settings_cannot_disable' => 'Súbor ENABLE_INSTALL_TOOL nie je možné odstrániť', -'settings_checkOutDir' => '', -'settings_checkOutDir_desc' => '', -'settings_cmdTimeout' => '', -'settings_cmdTimeout_desc' => '', +'settings_checkOutDir' => 'Directory for checked out documents', +'settings_checkOutDir_desc' => 'This is the directory where the latest content of a document is copied if the document is checked out. If you make this directory accessible for users, they can edit the file and check it back in when finished.', +'settings_cmdTimeout' => 'Timeout for external commands', +'settings_cmdTimeout_desc' => 'This duration in seconds determines when an external command (e.g. for creating the full text index) will be terminated.', 'settings_contentDir' => 'Zložka obsahu', -'settings_contentDir_desc' => '', -'settings_contentOffsetDir' => '', -'settings_contentOffsetDir_desc' => '', +'settings_contentDir_desc' => 'Where the uploaded files are stored (best to choose a directory that is not accessible through your web-server)', +'settings_contentOffsetDir' => 'Content Offset Directory', +'settings_contentOffsetDir_desc' => 'To work around limitations in the underlying file system, a new directory structure has been devised that exists within the content directory (Content Directory). This requires a base directory from which to begin. Usually leave this to the default setting, 1048576, but can be any number or string that does not already exist within (Content Directory)', 'settings_convertToPdf' => 'Konvertovať dokument do PDF pre náhľad', 'settings_convertToPdf_desc' => 'Ak dokument nemôže byť prirodzene zobrazený prehliadačom, konvertovaná verzia do formátu PDF bude zobrazená', 'settings_cookieLifetime' => 'Čas trvania súboru cookie', -'settings_cookieLifetime_desc' => '', -'settings_coreDir' => '', -'settings_coreDir_desc' => '', -'settings_createCheckOutDir' => '', -'settings_createCheckOutDir_desc' => '', +'settings_cookieLifetime_desc' => 'The life time of a cookie in seconds. If set to 0 the cookie will be removed when the browser is closed.', +'settings_coreDir' => 'Core SeedDMS directory', +'settings_coreDir_desc' => 'Path to SeedDMS_Core (optional). Leave this empty if you have installed SeedDMS_Core at a place where it can be found by PHP, e.g. Extra PHP Include-Path', +'settings_createCheckOutDir' => 'Create check out directory', +'settings_createCheckOutDir_desc' => 'Create checkout dir if it does not exists', 'settings_createdatabase' => 'Vytvoriť databázové tabuľky', 'settings_createdirectory' => 'Vytvoriť zložku', 'settings_currentvalue' => 'Aktuálna hodnota', 'settings_Database' => 'Nastavenia databazy', 'settings_dbDatabase' => 'Databáza', -'settings_dbDatabase_desc' => '', +'settings_dbDatabase_desc' => 'The name for your database entered during the installation process. Do not edit this field unless necessary, if for example the database has been moved.', 'settings_dbDriver' => 'Typ databázy', -'settings_dbDriver_desc' => '', +'settings_dbDriver_desc' => 'The type of database in use entered during the installation process. Do not edit this field unless you are having to migrate to a different type of database perhaps due to changing hosts. Type of DB-Driver used by adodb (see adodb-readme)', 'settings_dbHostname' => 'Názov servera', -'settings_dbHostname_desc' => '', +'settings_dbHostname_desc' => 'The hostname for your database entered during the installation process. Do not edit field unless absolutely necessary, for example transfer of the database to a new Host.', 'settings_dbPass' => 'Heslo', 'settings_dbPass_desc' => 'Heslo pre prístup k databáze zadané počas inštalácie.', 'settings_dbUser' => 'Používateľské meno', -'settings_dbUser_desc' => '', -'settings_dbVersion' => '', -'settings_defaultAccessDocs' => 'Štandardný prístup pre nové dokumenty', -'settings_defaultAccessDocs_desc' => '', -'settings_defaultDocPosition' => '', -'settings_defaultDocPosition_desc' => '', -'settings_defaultDocPosition_val_end' => '', -'settings_defaultDocPosition_val_start' => '', -'settings_defaultSearchMethod' => '', -'settings_defaultSearchMethod_desc' => '', +'settings_dbUser_desc' => 'The username for access to your database entered during the installation process. Do not edit field unless absolutely necessary, for example transfer of the database to a new Host.', +'settings_dbVersion' => 'Database schema too old', +'settings_defaultAccessDocs' => 'Východzí prístup pre nové dokumenty', +'settings_defaultAccessDocs_desc' => 'When a new document is created, this will be the default access right.', +'settings_defaultDocPosition' => 'Position of document when created', +'settings_defaultDocPosition_desc' => 'This is the default position within a folder when a document is created.', +'settings_defaultDocPosition_val_end' => 'end', +'settings_defaultDocPosition_val_start' => 'start', +'settings_defaultSearchMethod' => 'Default search method', +'settings_defaultSearchMethod_desc' => 'Default search method, when a search is started by the search form in the main menu.', 'settings_defaultSearchMethod_valdatabase' => 'databáza', -'settings_defaultSearchMethod_valfulltext' => '', -'settings_delete_install_folder' => '', -'settings_disableSelfEdit' => '', -'settings_disableSelfEdit_desc' => '', -'settings_disable_install' => '', +'settings_defaultSearchMethod_valfulltext' => 'fulltext', +'settings_delete_install_folder' => 'In order to use SeedDMS, you must delete the file ENABLE_INSTALL_TOOL in the configuration directory', +'settings_disableSelfEdit' => 'Disable Self Edit', +'settings_disableSelfEdit_desc' => 'If checked user cannot edit his own profile', +'settings_disable_install' => 'Delete file ENABLE_INSTALL_TOOL if possible', 'settings_Display' => 'Zobraziť nastavenia', 'settings_dropFolderDir' => 'Zložka pre drop zložku', -'settings_dropFolderDir_desc' => '', -'settings_Edition' => '', -'settings_editOnlineFileTypes' => '', -'settings_editOnlineFileTypes_desc' => '', -'settings_enable2FactorAuthentication' => '', -'settings_enable2FactorAuthentication_desc' => '', +'settings_dropFolderDir_desc' => 'This directory can be used for dropping files on the server\'s file system and importing them from there instead of uploading via the browser. The directory must contain a sub directory for each user who is allowed to import files this way.', +'settings_Edition' => 'Edition settings', +'settings_editOnlineFileTypes' => 'Edit Online File Types', +'settings_editOnlineFileTypes_desc' => 'Files with one of the following endings can be edited online (USE ONLY LOWER CASE CHARACTERS)', +'settings_enable2FactorAuthentication' => 'Enable 2-factor authentication', +'settings_enable2FactorAuthentication_desc' => 'Enable/disable 2 factor authentication. The users will need the Google Authenticator on its mobile phone.', 'settings_enableAcknowledgeWorkflow' => '', 'settings_enableAcknowledgeWorkflow_desc' => '', -'settings_enableAdminReceipt' => '', -'settings_enableAdminReceipt_desc' => '', -'settings_enableAdminRevApp' => '', -'settings_enableAdminRevApp_desc' => '', +'settings_enableAdminReceipt' => 'Allow reception of documents for admins', +'settings_enableAdminReceipt_desc' => 'Enable this if you want administrators to be listed as recipients of documents.', +'settings_enableAdminRevApp' => 'Allow review/approval for admins', +'settings_enableAdminRevApp_desc' => 'Enable this if you want administrators to be listed as reviewers/approvers and for workflow transitions.', 'settings_enableCalendar' => 'Zapnúť kalendár', 'settings_enableCalendar_desc' => 'Zapnúť/vypnúť kalendár', 'settings_enableClipboard' => 'Aktivovať schránky', -'settings_enableClipboard_desc' => '', +'settings_enableClipboard_desc' => 'Enable/disable the clipboard on the \'View Folder\' page', 'settings_enableConverting' => 'Povoliť konverziu', 'settings_enableConverting_desc' => 'Povoliť/zakázať konvertovať súbory', -'settings_enableDropFolderList' => '', -'settings_enableDropFolderList_desc' => '', +'settings_enableDropFolderList' => 'Enable list of files in drop folder in menu', +'settings_enableDropFolderList_desc' => 'Turn on a list of files in the drop folder. The list is shown in the main menu.', 'settings_enableDropUpload' => 'Zapnúť rýchle nahratie', -'settings_enableDropUpload_desc' => '', +'settings_enableDropUpload_desc' => 'Enable/Disable the drop area on the \'View Folder\' page for uploading files by Drag&Drop.', 'settings_enableDuplicateDocNames' => 'Povoliť duplicitné názvy dokumentov', 'settings_enableDuplicateDocNames_desc' => 'Povoliť duplicitné názvy dokumentov v zložke.', 'settings_enableEmail' => 'Povoliť e-mail', -'settings_enableEmail_desc' => 'Povoliť/zakázať automatické emailové upozornenie', -'settings_enableFilterReceipt' => '', -'settings_enableFilterReceipt_desc' => '', -'settings_enableFolderTree' => 'Aktivovať strom priečinkov', -'settings_enableFolderTree_desc' => '', +'settings_enableEmail_desc' => 'Povoliť/zakázať automatickú emailovú notifikáciu', +'settings_enableFilterReceipt' => 'Filter out owner, reviewer, ... from reception list', +'settings_enableFilterReceipt_desc' => 'Enable, in order to filter out some recipients from a reception list if members of a group are selected.', +'settings_enableFolderTree' => 'Zobrazovať strom zložiek', +'settings_enableFolderTree_desc' => 'Enable/Disable the folder tree on the \'View Folder\' page', 'settings_enableFullSearch' => 'Povoliť Fulltextové vyhľadávanie', 'settings_enableFullSearch_desc' => 'Povoliť Fulltextové vyhľadávanie', 'settings_enableGuestAutoLogin' => 'Povoliť automatické prihlásenie pre hosťa', -'settings_enableGuestAutoLogin_desc' => '', +'settings_enableGuestAutoLogin_desc' => 'If a guest login and auto login is enabled, the guest will be logged in automatically.', 'settings_enableGuestLogin' => 'Povoliť prihlásenie Hosťa', -'settings_enableGuestLogin_desc' => '', -'settings_enableHelp' => 'Zapnúť nápovedu', -'settings_enableHelp_desc' => '', +'settings_enableGuestLogin_desc' => 'If you want anybody to login as guest, check this option. Note: guest login should be used only in a trusted environment', +'settings_enableHelp' => 'Povoliť nápovedu', +'settings_enableHelp_desc' => 'Enable/disable the link to the help screens in the menu', 'settings_enableLanguageSelector' => 'Aktivovať voľbu jazyka', 'settings_enableLanguageSelector_desc' => 'Zobraziť výber pre jazyk používateľského rozhrania potom, čo bol prihlásený.', -'settings_enableLargeFileUpload' => 'Povoliť nahrať veľké súbory', -'settings_enableLargeFileUpload_desc' => '', -'settings_enableMenuTasks' => '', -'settings_enableMenuTasks_desc' => '', -'settings_enableMultiUpload' => 'Povoliť nahrať viac súborov', -'settings_enableMultiUpload_desc' => '', -'settings_enableNotificationAppRev' => '', -'settings_enableNotificationAppRev_desc' => '', -'settings_enableNotificationWorkflow' => '', -'settings_enableNotificationWorkflow_desc' => '', -'settings_enableOwnerNotification' => '', -'settings_enableOwnerNotification_desc' => '', -'settings_enableOwnerReceipt' => '', -'settings_enableOwnerReceipt_desc' => '', -'settings_enableOwnerRevApp' => '', -'settings_enableOwnerRevApp_desc' => '', +'settings_enableLargeFileUpload' => 'Povoliť nahrávať veľké súbory', +'settings_enableLargeFileUpload_desc' => 'If set, file upload is also available through a java applet called jumploader without a file size limit set by the browser. It also allows to upload several files in one step. Turning this on will turn off http only cookies.', +'settings_enableMenuTasks' => 'Enable task list in menu', +'settings_enableMenuTasks_desc' => 'Enable/Disable the menu item which contains all tasks for the user. This contains documents, that need to be reviewed, approved, etc.', +'settings_enableMultiUpload' => 'Povoliť nahrať viacero súborov', +'settings_enableMultiUpload_desc' => 'When creating a new document, multiple files can be uploaded. Each will create a new document.', +'settings_enableNotificationAppRev' => 'Enable reviewer/approver notification', +'settings_enableNotificationAppRev_desc' => 'Check to send a notification to the reviewer/approver when a new document version is added', +'settings_enableNotificationWorkflow' => 'Send notification to users in next workflow transition', +'settings_enableNotificationWorkflow_desc' => 'If this option is enabled, the users and groups which need to take action in the next workflow transition will be notified. Even if they have not added a notification for the document.', +'settings_enableOwnerNotification' => 'Enable owner notification by default', +'settings_enableOwnerNotification_desc' => 'Check for adding a notification for the owner if a document when it is added.', +'settings_enableOwnerReceipt' => 'Allow reception of documents by owner', +'settings_enableOwnerReceipt_desc' => 'Enable this if you want the owner of a document to be listed as a recipient.', +'settings_enableOwnerRevApp' => 'Allow review/approval for owner', +'settings_enableOwnerRevApp_desc' => 'Enable this if you want the owner of a document to be listed as reviewers/approvers and for workflow transitions.', 'settings_enablePasswordForgotten' => 'Povoliť zabudnuté heslo', -'settings_enablePasswordForgotten_desc' => '', -'settings_enableReceiptWorkflow' => '', -'settings_enableReceiptWorkflow_desc' => '', -'settings_enableRecursiveCount' => '', -'settings_enableRecursiveCount_desc' => '', -'settings_enableRevisionOnVoteReject' => '', -'settings_enableRevisionOnVoteReject_desc' => '', +'settings_enablePasswordForgotten_desc' => 'If you want to allow user to set a new password and send it by mail, check this option.', +'settings_enableReceiptWorkflow' => 'Enable acknowledge of document reception', +'settings_enableReceiptWorkflow_desc' => 'Enable, to turn on the workflow to acknowledge document reception.', +'settings_enableRecursiveCount' => 'Enable recursive document/folder count', +'settings_enableRecursiveCount_desc' => 'If turned on, the number of documents and folders in the folder view will be determined by counting all objects by recursively processing the folders and counting those documents and folders the user is allowed to access.', +'settings_enableRevisionOnVoteReject' => 'Reject by one revisor', +'settings_enableRevisionOnVoteReject_desc' => 'If set the document will be reject if one revisor rejects the document.', 'settings_enableRevisionWorkflow' => 'Povoliť revíziu dokumentov', -'settings_enableRevisionWorkflow_desc' => '', -'settings_enableSelfReceipt' => '', -'settings_enableSelfReceipt_desc' => '', -'settings_enableSelfRevApp' => '', -'settings_enableSelfRevApp_desc' => '', -'settings_enableSessionList' => '', -'settings_enableSessionList_desc' => '', +'settings_enableRevisionWorkflow_desc' => 'Enable, to be able to run the workflow for revising a document after a given period of time.', +'settings_enableSelfReceipt' => 'Allow reception of documents for logged in user', +'settings_enableSelfReceipt_desc' => 'Enable this if you want the currently logged in user to be listed as recipient for a document.', +'settings_enableSelfRevApp' => 'Allow review/approval for logged in user', +'settings_enableSelfRevApp_desc' => 'Enable this if you want the currently logged in user to be listed as reviewers/approvers and for workflow transitions.', +'settings_enableSessionList' => 'Enable list of users online in menu', +'settings_enableSessionList_desc' => 'Enable list of currently logged in users in menu.', 'settings_enableThemeSelector' => 'Výber šablóny', -'settings_enableThemeSelector_desc' => '', -'settings_enableUpdateReceipt' => '', -'settings_enableUpdateReceipt_desc' => '', -'settings_enableUpdateRevApp' => '', -'settings_enableUpdateRevApp_desc' => '', +'settings_enableThemeSelector_desc' => 'Turns on/off the theme selector on the login page.', +'settings_enableUpdateReceipt' => 'Allow editing of existing reception', +'settings_enableUpdateReceipt_desc' => 'Enable this, if the user who has made a reception may change the decission.', +'settings_enableUpdateRevApp' => 'Allow editing of exting review/approval', +'settings_enableUpdateRevApp_desc' => 'Enable this, if the user who has made a review/approval may change the decission as long as the current workflow step has not been finished.', 'settings_enableUserImage' => 'Povoliť obrázok používateľa', 'settings_enableUserImage_desc' => 'Povoliť používateľské obrázky', 'settings_enableUsersView' => 'Povoliť zobrazenie používateľov', -'settings_enableUsersView_desc' => '', -'settings_enableVersionDeletion' => '', -'settings_enableVersionDeletion_desc' => '', -'settings_enableVersionModification' => '', -'settings_enableVersionModification_desc' => '', -'settings_enableWebdavReplaceDoc' => '', -'settings_enableWebdavReplaceDoc_desc' => '', -'settings_encryptionKey' => '', -'settings_encryptionKey_desc' => '', +'settings_enableUsersView_desc' => 'Enable/disable group and user view for all users', +'settings_enableVersionDeletion' => 'Enable deletion of previous versions', +'settings_enableVersionDeletion_desc' => 'Enable/disable deletion of previous document versions by regular users. Admin may always delete old versions.', +'settings_enableVersionModification' => 'Enable modification of versions', +'settings_enableVersionModification_desc' => 'Enable/disable modification of a document versions by regular users after a version was uploaded. Admin may always modify the version after upload.', +'settings_enableWebdavReplaceDoc' => 'Replace document when saving', +'settings_enableWebdavReplaceDoc_desc' => 'If enabled, saving a new version of a document will replace the old document instead of creating a new version. This will only apply if the user, mimetype and filename are equal to the last version. This can be usefull when applications are auto saving a document in fixed intervals.', +'settings_enableXsendfile' => '', +'settings_enableXsendfile_desc' => '', +'settings_encryptionKey' => 'Encryption key', +'settings_encryptionKey_desc' => 'This string is used for creating a unique identifier being added as a hidden field to a form in order to prevent CSRF attacks.', 'settings_error' => 'Chyba', 'settings_expandFolderTree' => 'Rozbaliť', -'settings_expandFolderTree_desc' => 'Rozbaľte strom priečinkov', +'settings_expandFolderTree_desc' => 'Rozbaliť strom zložiek', 'settings_expandFolderTree_val0' => 'začať so skrytou stromovou štruktúrou', -'settings_expandFolderTree_val1' => 'začať so stromovou štruktúrou a prvou rozbalenou úrovňou', -'settings_expandFolderTree_val2' => '', +'settings_expandFolderTree_val1' => 'začať so stromovou štruktúrou s prvou rozbalenou úrovňou', +'settings_expandFolderTree_val2' => 'začať so stromovou štruktúrou plne rozbalenou', 'settings_Extensions' => 'Rozšírenia', -'settings_extraPath' => '', -'settings_extraPath_desc' => '', +'settings_extraPath' => 'Extra PHP include Path', +'settings_extraPath_desc' => 'Path to additional software. This is the directory containing e.g. the adodb directory or additional pear packages', 'settings_firstDayOfWeek' => 'Prvý deň v týždni', 'settings_firstDayOfWeek_desc' => 'Prvý deň v týždni', 'settings_footNote' => 'Poznámka pod čiarou', 'settings_footNote_desc' => 'Správa sa zobrazí v dolnej časti každej stránky', -'settings_fullSearchEngine' => '', -'settings_fullSearchEngine_desc' => '', +'settings_fullSearchEngine' => 'Fulltext engine', +'settings_fullSearchEngine_desc' => 'Set the method used for the fulltext search.', 'settings_fullSearchEngine_vallucene' => 'Zend Lucene', 'settings_fullSearchEngine_valsqlitefts' => 'SQLiteFTS', 'settings_guestID' => 'Hosť ID', -'settings_guestID_desc' => '', +'settings_guestID_desc' => 'ID of guest-user used when logged in as guest (mostly no need to change)', 'settings_httpRoot' => 'Http Root', -'settings_httpRoot_desc' => '', -'settings_incItemsPerPage' => '', -'settings_incItemsPerPage_desc' => '', -'settings_initialDocumentStatus' => '', -'settings_initialDocumentStatus_desc' => '', +'settings_httpRoot_desc' => 'The relative path in the URL, after the domain part. Do not include the http:// prefix or the web host name. e.g. If the full URL is http://www.example.com/seeddms/, set \'/seeddms/\'. If the URL is http://www.example.com/, set \'/\'', +'settings_incItemsPerPage' => 'Number of entries loaded at end of page', +'settings_incItemsPerPage_desc' => 'If the number of folders and documents is limited, this will set the number of additionally loaded objects, when scrolling down to the bottom of the view folder page. Setting this to 0, will load the same number of objects as has been loaded initially.', +'settings_initialDocumentStatus' => 'Initial document status', +'settings_initialDocumentStatus_desc' => 'This status will be set when a document is added.', 'settings_initialDocumentStatus_draft' => 'Návrh', 'settings_initialDocumentStatus_released' => 'Vydaný', 'settings_installADOdb' => 'Inštalovať ADOdb', -'settings_install_disabled' => '', +'settings_install_disabled' => 'File ENABLE_INSTALL_TOOL was deleted. You can now log into SeedDMS and do further configuration.', 'settings_install_pear_package_log' => 'Inštalovať Pear balíček \'Log\'', 'settings_install_pear_package_webdav' => 'Inštalovať Pear balíček \'HTTP_WebDAV_Server\', ak máte v umysle používať rozhranie webdav', 'settings_install_success' => 'Inštalácia bola úspešne dokončená.', -'settings_install_welcome_text' => '', +'settings_install_welcome_text' => '

Before you start to install SeedDMS make sure you have created a file \'ENABLE_INSTALL_TOOL\' in your configuration directory, otherwise the installation will not work. On Unix-System this can easily be done with \'touch conf/ENABLE_INSTALL_TOOL\'. After you have finished the installation delete the file.

SeedDMS has very minimal requirements. You will need a mysql database or sqlite support and a php enabled web server. The pear package Log has to be installed too. For the lucene full text search, you will also need the Zend framework installed on disc where it can be found by php. For the WebDAV server you will also need the HTTP_WebDAV_Server. The path to it can later be set during installation.

If you like to create the database before you start installation, then just create it manually with your favorite tool, optionally create a database user with access on the database and import one of the database dumps in the configuration directory. The installation script can do that for you as well, but it will need database access with sufficient rights to create databases.

', 'settings_install_welcome_title' => 'Vitajte v inštalácii SeedDMS', -'settings_install_zendframework' => '', +'settings_install_zendframework' => 'Install Zend Framework, if you intend to use the zend based full text search engine. Otherwise, ignore this message and continue the installation.', 'settings_language' => 'Predvolený jazyk', -'settings_language_desc' => '', -'settings_libraryFolder' => '', -'settings_libraryFolder_desc' => '', +'settings_language_desc' => 'Default language (name of a subfolder in folder "languages")', +'settings_libraryFolder' => 'Library folder', +'settings_libraryFolder_desc' => 'Folder where documents can be copied to create new documents.', 'settings_logFileEnable' => 'Povoliť Log súbor', 'settings_logFileEnable_desc' => 'Povoliť/zakázať log súbor', -'settings_logFileRotation' => '', -'settings_logFileRotation_desc' => '', +'settings_logFileRotation' => 'Log File Rotation', +'settings_logFileRotation_desc' => 'The log file rotation', 'settings_loginFailure' => 'Prihlásenie zlyhalo', -'settings_loginFailure_desc' => '', +'settings_loginFailure_desc' => 'Disable account after n login failures.', 'settings_luceneClassDir' => 'Lucene SeedDMS zložka', -'settings_luceneClassDir_desc' => '', -'settings_luceneDir' => '', +'settings_luceneClassDir_desc' => 'Path to SeedDMS_Lucene (optional). Leave this empty if you have installed SeedDMS_Lucene at a place where it can be found by PHP, e.g. Extra PHP Include-Path', +'settings_luceneDir' => 'Directory for full text index', 'settings_luceneDir_desc' => 'Cesta do Lucene indexu', 'settings_maxDirID' => 'Max Zložka ID', -'settings_maxDirID_desc' => '', -'settings_maxExecutionTime' => '', -'settings_maxExecutionTime_desc' => '', -'settings_maxItemsPerPage' => '', -'settings_maxItemsPerPage_desc' => '', -'settings_maxRecursiveCount' => '', -'settings_maxRecursiveCount_desc' => '', -'settings_maxSizeForFullText' => '', -'settings_maxSizeForFullText_desc' => '', +'settings_maxDirID_desc' => 'Maximum number of sub-directories per parent directory. Do not change this value unless you know what you do! Default: 0.', +'settings_maxExecutionTime' => 'Max Execution Time (s)', +'settings_maxExecutionTime_desc' => 'This sets the maximum time in seconds a script is allowed to run before it is terminated by the parse', +'settings_maxItemsPerPage' => 'Max. number of entries on a page', +'settings_maxItemsPerPage_desc' => 'Restricts the number of folders and documents shown on the view folder page. Further objects will be loaded when scrolling to the end of the page. Set to 0 to always show all objects.', +'settings_maxRecursiveCount' => 'Max. number of recursive document/folder count', +'settings_maxRecursiveCount_desc' => 'This is the maximum number of documents or folders that will be checked for access rights, when recursively counting objects. If this number is exceeded, the number of documents and folders in the folder view will be estimated.', +'settings_maxSizeForFullText' => 'Maximum filesize for instant indexing', +'settings_maxSizeForFullText_desc' => 'All new document version smaller than the configured size will be fully indexed right after uploading. In all other cases only the metadata will be indexed.', 'settings_maxUploadSize' => 'Maximálna veľkosť pre nahrávané súbory', -'settings_maxUploadSize_desc' => '', -'settings_more_settings' => '', +'settings_maxUploadSize_desc' => 'This is the maximum size for uploaded files. It will take affect for document versions and attachments.', +'settings_more_settings' => 'Configure more settings. Default login: admin/admin', 'settings_notfound' => 'Nenájdené', -'settings_Notification' => 'Nastavenia upozornení', -'settings_notwritable' => '', -'settings_no_content_dir' => '', -'settings_overrideMimeType' => '', -'settings_overrideMimeType_desc' => '', +'settings_Notification' => 'Nastavenia notifikácií', +'settings_notwritable' => 'The configuration cannot be saved because the configuration file is not writable.', +'settings_no_content_dir' => 'Content directory', +'settings_overrideMimeType' => 'Override MimeType', +'settings_overrideMimeType_desc' => 'Override the MimeType delivered by the browser, if a file is uploaded. The new MimeType is determined by SeedDMS itself.', 'settings_partitionSize' => 'Čiastočná veľkosť súboru', -'settings_partitionSize_desc' => '', +'settings_partitionSize_desc' => 'Size of partial files in bytes, uploaded by jumploader. Do not set a value larger than the maximum upload size set by the server.', 'settings_passwordExpiration' => 'Vypršanie hesla', -'settings_passwordExpiration_desc' => '', +'settings_passwordExpiration_desc' => 'The number of days after which a password expireѕ and must be reset. 0 turns password expiration off.', 'settings_passwordHistory' => 'História hesla', -'settings_passwordHistory_desc' => '', +'settings_passwordHistory_desc' => 'The number of passwords a user must have been used before a password can be reused. 0 turns the password history off.', 'settings_passwordStrength' => 'Min. sila hesla', 'settings_passwordStrengthAlgorithm' => 'Algoritmus pre silu hesla', -'settings_passwordStrengthAlgorithm_desc' => '', +'settings_passwordStrengthAlgorithm_desc' => 'The algorithm used for calculating the password strength. The \'simple\' algorithm just checks for at least eight chars total, a lower case letter, an upper case letter, a number and a special char. If those conditions are met the returned score is 100 otherwise 0.', 'settings_passwordStrengthAlgorithm_valadvanced' => 'pokročilý', 'settings_passwordStrengthAlgorithm_valsimple' => 'jednoduchý', -'settings_passwordStrength_desc' => '', +'settings_passwordStrength_desc' => 'The minimum password strength is an integer value from 0 to 100. Setting it to 0 will turn off checking for the minimum password strength.', 'settings_pear_log' => 'Pear balíček : Log', 'settings_pear_webdav' => 'Pear balíček : HTTP_WebDAV_Server', 'settings_perms' => 'Oprávnenie', @@ -1248,8 +1469,8 @@ URL: [url]', 'settings_php_gd2' => 'PHP rozšírenie : php_gd2', 'settings_php_mbstring' => 'PHP rozšírenie : php_mbstring', 'settings_php_version' => 'PHP verzia', -'settings_presetExpirationDate' => '', -'settings_presetExpirationDate_desc' => '', +'settings_presetExpirationDate' => 'Preset expiration date', +'settings_presetExpirationDate_desc' => 'All new uploaded documents will have an expiration date set to this value. The date entered can be specified as understood by PHP\'s strtotime() function, e.g. +5 weeks.', 'settings_previewWidthDetail' => 'Šírka náhľadu obrázkov (detail)', 'settings_previewWidthDetail_desc' => 'Šírka náhľadu obrázku zobrazená na stránke podrobností', 'settings_previewWidthDropFolderList' => 'Šírka náhľadu obrázku (zoznam drop zložka)', @@ -1258,31 +1479,31 @@ URL: [url]', 'settings_previewWidthList_desc' => 'Šírka pre náhľad obrázkov je uvedené v zoznamoch', 'settings_previewWidthMenuList' => 'Šírka náhľadu obrázku (zoznam ponúk)', 'settings_previewWidthMenuList_desc' => 'Šírka náhľadu obrázkov zobrazených ako položky v ponuke drop zložky.', -'settings_printDisclaimer' => '', -'settings_printDisclaimer_desc' => '', +'settings_printDisclaimer' => 'Print Disclaimer', +'settings_printDisclaimer_desc' => 'If enabled, the disclaimer message will be printed on the bottom of every page', 'settings_quota' => 'Kvóta používateľa', -'settings_quota_desc' => '', -'settings_removeFromDropFolder' => '', -'settings_removeFromDropFolder_desc' => '', -'settings_repositoryUrl' => '', -'settings_repositoryUrl_desc' => '', -'settings_restricted' => '', -'settings_restricted_desc' => '', +'settings_quota_desc' => 'The maximum number of bytes a user may use on disk. Set this to 0 for unlimited disk space. This value can be overridden for each user in his profile.', +'settings_removeFromDropFolder' => 'Remove file from drop folder after successful upload', +'settings_removeFromDropFolder_desc' => 'Enable this, if a file taken from the drop folder shall be deleted after successful upload.', +'settings_repositoryUrl' => 'URL of repository', +'settings_repositoryUrl_desc' => 'URL of repository for extensions', +'settings_restricted' => 'Restricted access', +'settings_restricted_desc' => 'Only allow users to log in if they have an entry in the local database (irrespective of successful authentication with LDAP)', 'settings_rootDir' => 'Koreňový adresár', 'settings_rootDir_desc' => 'Cesta k miestu, kde sa nachádza SeedDMS', -'settings_rootFolderID' => 'Koreňová zložka ID', -'settings_rootFolderID_desc' => '', -'settings_SaveError' => '', +'settings_rootFolderID' => 'ID koreňovej zložky', +'settings_rootFolderID_desc' => 'ID of root-folder (mostly no need to change)', +'settings_SaveError' => 'Configuration file save error', 'settings_Server' => 'Nastavenie servera', 'settings_showFullPreview' => 'Zobraziť kompletný dokument', -'settings_showFullPreview_desc' => '', +'settings_showFullPreview_desc' => 'Enable/disable a full preview of the document on the details page, if the browser is capable to do so.', 'settings_showMissingTranslations' => 'Ukázať chýbajúce preklady', -'settings_showMissingTranslations_desc' => '', -'settings_showSingleSearchHit' => '', -'settings_showSingleSearchHit_desc' => '', +'settings_showMissingTranslations_desc' => 'List all missing translations on the page at the bottom of the page. The logged in user will be able to submit a proposal for a missing translation which will be saved in a csv file. Do not turn this function on if in a production environment!', +'settings_showSingleSearchHit' => 'Jump straight to a single search hit', +'settings_showSingleSearchHit_desc' => 'If the search results into just one hit, then it will be displayed right away instead of the result list.', 'settings_Site' => 'Stránka', -'settings_siteDefaultPage' => '', -'settings_siteDefaultPage_desc' => '', +'settings_siteDefaultPage' => 'Site Default Page', +'settings_siteDefaultPage_desc' => 'Default page on login. If empty defaults to out/out.ViewFolder.php', 'settings_siteName' => 'Názov stránky', 'settings_siteName_desc' => 'Názov stránky používaný v nadpisoch. Predvolený: SeedDMS', 'settings_SMTP' => 'SMTP Server nastavenia', @@ -1292,67 +1513,67 @@ URL: [url]', 'settings_smtpPort_desc' => 'SMTP Server port, štandardne 25', 'settings_smtpSendFrom' => 'Odoslané z', 'settings_smtpSendFrom_desc' => 'Odoslané z', -'settings_smtpSendTestMail' => '', -'settings_smtpSendTestMail_desc' => '', +'settings_smtpSendTestMail' => 'Send test mail', +'settings_smtpSendTestMail_desc' => 'Sends a test mail, for checking the current email configuration.', 'settings_smtpServer' => 'SMTP Server názov hostiteľa', 'settings_smtpServer_desc' => 'SMTP Server názov hostiteľa', 'settings_smtpUser' => 'SMTP Server používateľ', 'settings_smtpUser_desc' => 'SMTP Server používateľ', 'settings_sortFoldersDefault' => 'Predvolená metóda triedenia', -'settings_sortFoldersDefault_desc' => 'Toto nastavenie triedi metódy pre zložky a dokumenty v zobrazení priečinkov.', +'settings_sortFoldersDefault_desc' => 'Toto nastavenie triedi metódy pre zložky a dokumenty v zobrazení zložiek.', 'settings_sortFoldersDefault_val_name' => 'podľa mena', 'settings_sortFoldersDefault_val_sequence' => 'podľa sekvencií', 'settings_sortFoldersDefault_val_unsorted' => 'neutriedený', 'settings_sortUsersInList' => 'Triediť užívateľov v zozname', -'settings_sortUsersInList_desc' => '', +'settings_sortUsersInList_desc' => 'Sets if users in selection menus are ordered by login or by its full name', 'settings_sortUsersInList_val_fullname' => 'Triediť podľa celého mena', 'settings_sortUsersInList_val_login' => 'Triediť podľa prihlásenie', -'settings_stagingDir' => '', -'settings_stagingDir_desc' => '', +'settings_stagingDir' => 'Directory for partial uploads', +'settings_stagingDir_desc' => 'The directory where jumploader places the parts of a file upload before it is put back together.', 'settings_start_install' => 'Začať inštaláciu', -'settings_stopWordsFile' => '', -'settings_stopWordsFile_desc' => '', -'settings_strictFormCheck' => '', -'settings_strictFormCheck_desc' => '', -'settings_suggestionvalue' => '', +'settings_stopWordsFile' => 'Path to stop words file', +'settings_stopWordsFile_desc' => 'If fulltext search is enabled, this file will contain stop words not being indexed', +'settings_strictFormCheck' => 'Strict Form Check', +'settings_strictFormCheck_desc' => 'Strict form checking. If set to true, then all fields in the form will be checked for a value. If set to false, then (most) comments and keyword fields become optional. Comments are always required when submitting a review or overriding document status', +'settings_suggestionvalue' => 'Suggestion value', 'settings_System' => 'Systém', -'settings_tasksInMenu' => '', -'settings_tasksInMenu_approval' => '', -'settings_tasksInMenu_desc' => '', -'settings_tasksInMenu_needscorrection' => '', -'settings_tasksInMenu_receipt' => '', -'settings_tasksInMenu_review' => '', -'settings_tasksInMenu_revision' => '', -'settings_tasksInMenu_workflow' => '', +'settings_tasksInMenu' => 'Selected tasks', +'settings_tasksInMenu_approval' => 'Approvals', +'settings_tasksInMenu_desc' => 'Select those tasks which are to be counted. If none is selected, then all tasks will be counted.', +'settings_tasksInMenu_needscorrection' => 'Correction needed', +'settings_tasksInMenu_receipt' => 'Reviews', +'settings_tasksInMenu_review' => 'Receipts', +'settings_tasksInMenu_revision' => 'Revisions', +'settings_tasksInMenu_workflow' => 'Workflow', 'settings_theme' => 'Prednastavená téma', -'settings_theme_desc' => '', -'settings_titleDisplayHack' => '', -'settings_titleDisplayHack_desc' => '', -'settings_undelUserIds' => '', -'settings_undelUserIds_desc' => '', -'settings_updateDatabase' => '', -'settings_updateNotifyTime' => 'Aktualizovať čas upozornenia', -'settings_updateNotifyTime_desc' => '', -'settings_upgrade_php' => '', -'settings_versioningFileName' => '', -'settings_versioningFileName_desc' => '', +'settings_theme_desc' => 'Default style (name of a subfolder in folder "styles")', +'settings_titleDisplayHack' => 'Title Display Hack', +'settings_titleDisplayHack_desc' => 'Workaround for page titles that go over more than 2 lines.', +'settings_undelUserIds' => 'Undeletable User IDs', +'settings_undelUserIds_desc' => 'Comma separated list of user ids, that cannot be deleted.', +'settings_updateDatabase' => 'Run schema update scripts on database', +'settings_updateNotifyTime' => 'Aktualizovať čas notifikácie', +'settings_updateNotifyTime_desc' => 'Users are notified about document-changes that took place within the last \'Update Notify Time\' seconds', +'settings_upgrade_php' => 'Upgrade PHP to at least version 5.2.0', +'settings_versioningFileName' => 'Versioning FileName', +'settings_versioningFileName_desc' => 'The name of the versioning info file created by the backup tool', 'settings_versiontolow' => 'Verzia je nízka', 'settings_viewOnlineFileTypes' => 'Zobraziť online typy súborov', -'settings_viewOnlineFileTypes_desc' => '', -'settings_webdav' => '', -'settings_workflowMode' => '', -'settings_workflowMode_desc' => '', +'settings_viewOnlineFileTypes_desc' => 'Files with one of the following endings can be viewed online (USE ONLY LOWER CASE CHARACTERS)', +'settings_webdav' => 'WebDAV', +'settings_workflowMode' => 'Workflow mode', +'settings_workflowMode_desc' => 'The advanced workflow allows to specify your own release workflow for document versions.', 'settings_workflowMode_valadvanced' => 'pokročilý', -'settings_workflowMode_valtraditional' => '', -'settings_workflowMode_valtraditional_only_approval' => '', +'settings_workflowMode_valtraditional' => 'traditional', +'settings_workflowMode_valtraditional_only_approval' => 'traditional (without review)', 'settings_zendframework' => 'Zend Framework', 'set_expiry' => 'Nastaviť vypršanie', 'set_owner' => 'Nastaviť vlastníka', -'set_owner_error' => '', +'set_owner_error' => 'Chyba pri nastavovaní vlastníka', 'set_password' => 'Nastaviť heslo', -'set_workflow' => '', -'show_extension_changelog' => '', -'show_extension_version_list' => '', +'set_workflow' => 'Set Workflow', +'show_extension_changelog' => 'Show Changelog', +'show_extension_version_list' => 'Show list of versions', 'signed_in_as' => 'Prihlásený ako', 'sign_in' => 'Prihlásiť sa', 'sign_out' => 'odhlásiť', @@ -1360,129 +1581,134 @@ URL: [url]', 'sk_SK' => 'Slovenčina', 'space_used_on_data_folder' => 'Space used on data folder', 'splash_added_to_clipboard' => 'Pridané do schránky', -'splash_add_access' => '', +'splash_add_access' => 'Prístupové právo pridané', 'splash_add_attribute' => 'Bol pridaný nový atribút', 'splash_add_group' => 'Bola pridaná nová skupina', -'splash_add_group_member' => '', +'splash_add_group_member' => 'New group member added', 'splash_add_role' => 'Nová rola bola pridaná', -'splash_add_to_transmittal' => '', -'splash_add_transmittal' => '', +'splash_add_to_transmittal' => 'Add to transmittal', +'splash_add_transmittal' => 'Added transmittal', 'splash_add_user' => 'Pridaný nový používateľ', 'splash_cleared_cache' => 'Vymazanie vyrovnávacej pamäte', 'splash_cleared_clipboard' => 'Schránka bola vymazaná', -'splash_delete_access' => '', +'splash_delete_access' => 'Access right deleted', 'splash_document_added' => 'Dokument bol pridaný', -'splash_document_checkedout' => '', +'splash_document_checkedout' => 'Document checked out', 'splash_document_edited' => 'Dokument bol uložený', 'splash_document_indexed' => 'Dokument \'[name]\' bol indexovaný.', 'splash_document_locked' => 'Dokument uzamknutý', 'splash_document_unlocked' => 'Dokument odomknutý', -'splash_edit_access' => '', +'splash_edit_access' => 'Access right changed', 'splash_edit_attribute' => 'Atribút bol uložený', 'splash_edit_event' => 'Udalosť bola uložená', 'splash_edit_group' => 'Skupina bola uložená', 'splash_edit_role' => 'Rola bola uložená', +'splash_edit_task' => '', 'splash_edit_user' => 'Používateľ bol uložený', -'splash_error_add_to_transmittal' => '', -'splash_error_rm_download_link' => '', -'splash_error_send_download_link' => '', -'splash_extension_getlist' => '', -'splash_extension_import' => '', -'splash_extension_refresh' => '', -'splash_extension_upload' => '', +'splash_error_add_to_transmittal' => 'Error while adding document to transmittal', +'splash_error_rm_download_link' => 'Error when removing download link', +'splash_error_send_download_link' => 'Error while sending download link', +'splash_extension_getlist' => 'Updated list of extensions from repository', +'splash_extension_import' => 'Extensition installed', +'splash_extension_refresh' => 'Refreshed list of extensions', +'splash_extension_upload' => 'Extension installed', 'splash_folder_edited' => 'Uložiť zmeny zložky', 'splash_importfs' => 'Importované dokumenty [docs] a zložky [folders]', -'splash_inherit_access' => '', +'splash_inherit_access' => 'Access right will be inherited', 'splash_invalid_folder_id' => 'Neplatné ID zložky', -'splash_invalid_searchterm' => '', +'splash_invalid_searchterm' => 'Invalid search term', 'splash_moved_clipboard' => 'Schránka sa presunula do aktuálnej zložky', 'splash_move_document' => 'Dokument bol presunutý', 'splash_move_folder' => 'Zložka bola presunutá', -'splash_notinherit_access' => '', -'splash_receipt_update_success' => '', +'splash_notinherit_access' => 'Prístupové práva sa už nededia', +'splash_receipt_update_success' => 'Reception added successfully', 'splash_removed_from_clipboard' => 'Odstránené zo schránky', 'splash_rm_attribute' => 'Atribút bol odstránený', -'splash_rm_attr_value' => '', +'splash_rm_attr_value' => 'Attribute value removed', 'splash_rm_document' => 'Dokument odstránený', 'splash_rm_download_link' => 'Odkaz na prevzatie bol odstránený', 'splash_rm_folder' => 'Zložka zmazaná', 'splash_rm_group' => 'Skupina bola odstránená', -'splash_rm_group_member' => '', +'splash_rm_group_member' => 'Člen skupiny odstránený', 'splash_rm_role' => 'Rola bola odstránená', -'splash_rm_transmittal' => '', +'splash_rm_transmittal' => 'Transmittal deleted', 'splash_rm_user' => 'Používateľ bol odstránený', 'splash_rm_user_processes' => 'Používateľ bol odstránený zo všetkých procesov', +'splash_rm_workflow' => '', +'splash_rm_workflow_action' => '', +'splash_rm_workflow_state' => '', 'splash_saved_file' => 'Verzia bola uložená', 'splash_save_user_data' => 'Používateľské údaje boli uložené', -'splash_send_download_link' => '', -'splash_send_login_data' => '', -'splash_setowner' => '', +'splash_send_download_link' => 'Download link sent by email.', +'splash_send_login_data' => 'Login data sent', +'splash_setowner' => 'Nastaviť nového vlastníka', 'splash_settings_saved' => 'Nastavenia boli uložené', -'splash_set_default_access' => '', -'splash_substituted_user' => '', -'splash_switched_back_user' => '', -'splash_toogle_group_manager' => '', -'splash_transfer_document' => '', -'splash_transfer_objects' => '', -'state_and_next_state' => '', +'splash_set_default_access' => 'Default access right set', +'splash_substituted_user' => 'Substituted user', +'splash_switched_back_user' => 'Switched back to original user', +'splash_toogle_group_manager' => 'Group manager toogled', +'splash_transfer_document' => 'Document transfered', +'splash_transfer_objects' => 'Objects transfered', +'splash_trigger_workflow' => '', +'state_and_next_state' => 'State/Next state', 'statistic' => 'Štatistika', 'status' => 'Stav', 'status_approval_rejected' => 'Návrh zamietnutý', 'status_approved' => 'Schválený', 'status_approver_removed' => 'Schvaľovateľ odstránený z procesu', -'status_needs_correction' => '', +'status_needs_correction' => 'Vyžaduje opravu', 'status_not_approved' => 'Neschválený', -'status_not_receipted' => '', -'status_not_reviewed' => 'Neskontrolovaný', -'status_not_revised' => '', -'status_receipted' => '', -'status_receipt_rejected' => '', -'status_recipient_removed' => '', -'status_reviewed' => 'Skontrolovaný', +'status_not_receipted' => 'Zatiaľ neprijatý', +'status_not_reviewed' => 'Nerecenzovaný', +'status_not_revised' => 'nezrevidovaný', +'status_receipted' => 'Receipted', +'status_receipt_rejected' => 'Odmietnuté', +'status_recipient_removed' => 'Recipient odstránený zo zoznamu', +'status_reviewed' => 'Recenzovaný', 'status_reviewer_rejected' => 'Návrh zamietnutý', -'status_reviewer_removed' => 'Kontrolór odstránený z procesu', -'status_revised' => '', -'status_revision_rejected' => '', -'status_revision_sleeping' => '', -'status_revisor_removed' => '', +'status_reviewer_removed' => 'Recenzent odstránený z procesu', +'status_revised' => 'revised', +'status_revision_rejected' => 'Rejected', +'status_revision_sleeping' => 'pending', +'status_revisor_removed' => 'Revisor removed from list', 'status_unknown' => 'Neznámy', 'storage_size' => 'Objem dát', -'submit_2_fact_auth' => '', +'submit_2_fact_auth' => 'Save secret', 'submit_approval' => 'Poslať schválenie', 'submit_login' => 'Prihlásiť sa', 'submit_password' => 'Nastaviť nové heslo', 'submit_password_forgotten' => 'Spustiť proces', -'submit_receipt' => '', -'submit_review' => 'Poslať kontrolu', -'submit_revision' => '', -'submit_userinfo' => '', -'subsribe_timelinefeed' => '', +'submit_receipt' => 'Submit receipt', +'submit_review' => 'Poslať recenziu', +'submit_revision' => 'Add Revision', +'submit_userinfo' => 'Submit info', +'subsribe_timelinefeed' => 'Subscribe to time line feed', 'substitute_to_user' => 'Prepnúť do \'[username]\'', 'substitute_user' => 'Nahradiť používateľa', -'success_add_aro' => '', -'success_add_permission' => '', +'success_add_aro' => 'Access request object added', +'success_add_permission' => 'Oprávnenie pridané', 'success_remove_permission' => 'Oprávnenie bolo odstránené', -'success_toogle_permission' => '', +'success_toogle_permission' => 'Oprávnenie zmenené', 'sunday' => 'Nedeľa', 'sunday_abbr' => 'Ne', 'sv_SE' => 'Švédština', 'switched_to' => 'Prepnúť na', -'takeOverAttributeValue' => '', -'takeOverGrpApprover' => '', -'takeOverGrpReviewer' => '', -'takeOverIndApprover' => '', -'takeOverIndReviewer' => '', +'takeOverAttributeValue' => 'Take over attribute value from last version', +'takeOverGrpApprover' => 'Take over group of approvers from last version.', +'takeOverGrpReviewer' => 'Take over group of reviewers from last version.', +'takeOverIndApprover' => 'Take over individual approver from last version.', +'takeOverIndReviewer' => 'Take over individual reviewer from last version.', 'tasks' => 'Úlohy', -'task_description' => '', -'task_disabled' => '', -'task_frequency' => '', -'task_last_run' => '', -'task_name' => '', -'task_next_run' => '', +'task_description' => 'Description', +'task_disabled' => 'Disabled', +'task_frequency' => 'Frequency', +'task_last_run' => 'Last run', +'task_name' => 'Name', +'task_next_run' => 'Next run', 'temp_jscode' => 'Dočasný javascript kód', -'testmail_body' => '', +'testmail_body' => 'This mail is just for testing the mail configuration of SeedDMS', 'testmail_subject' => 'Testovací E-mail', -'theme' => 'Vzhľad', +'theme' => 'Šablóna', 'thursday' => 'Štvrtok', 'thursday_abbr' => 'Št', 'timeline' => 'Časová os', @@ -1490,47 +1716,56 @@ URL: [url]', 'timeline_add_version' => 'Nová verzia [version]', 'timeline_full_add_file' => '[document]
Nová príloha', 'timeline_full_add_version' => '[document]
Nová verzia [version]', -'timeline_full_scheduled_revision' => '', +'timeline_full_scheduled_revision' => '[document]
Revision of version [version]', 'timeline_full_status_change' => '[document]
Verzia [version]: [status]', -'timeline_scheduled_revision' => '', +'timeline_scheduled_revision' => 'Revision of version [version]', 'timeline_selected_item' => 'Vybraný dokument', 'timeline_skip_add_file' => 'príloha bola pridaná', -'timeline_skip_scheduled_revision' => '', +'timeline_skip_scheduled_revision' => 'Scheduled revision', 'timeline_skip_status_change_-1' => 'odmietnuté', 'timeline_skip_status_change_-3' => 'expirovaný', 'timeline_skip_status_change_0' => 'čaká na revíziu', 'timeline_skip_status_change_1' => 'čaká na potvrdenie', 'timeline_skip_status_change_2' => 'uvoľnený', 'timeline_skip_status_change_3' => 'v spracovaní', -'timeline_skip_status_change_4' => '', +'timeline_skip_status_change_4' => 'v revízii', 'timeline_skip_status_change_5' => 'návrh', 'timeline_status_change' => 'Verzia [version]: [status]', 'to' => 'Do', 'toggle_manager' => 'Prepnúť stav manager', 'toggle_qrcode' => 'Ukázať/skryť QR kód', -'to_before_from' => '', +'to_before_from' => 'End date may not be before start date', 'transfer_document' => 'Zmeniť vlastníka', 'transfer_no_read_access' => 'Používateľ nemá práva na čítanie v adresári', 'transfer_no_write_access' => 'Používateľ nemá práva na zapisovanie v adresári', 'transfer_objects' => 'Prenesené objekty', 'transfer_objects_to_user' => 'Nový vlastník', -'transfer_to_user' => '', -'transition_triggered_email' => '', -'transition_triggered_email_body' => '', -'transition_triggered_email_subject' => '', -'transmittal' => '', -'transmittalitem_removed' => '', +'transfer_to_user' => 'Transfer používateľovi', +'transition_triggered_email' => 'Workflow transition triggered', +'transition_triggered_email_body' => 'Workflow transition triggered +Document: [name] +Version: [version] +Comment: [comment] +Workflow: [workflow] +Previous state: [previous_state] +Current state: [current_state] +Parent folder: [folder_path] +User: [username] +URL: [url]', +'transition_triggered_email_subject' => '[sitename]: [name] - Workflow transition triggered', +'transmittal' => 'Transmittal', +'transmittalitem_removed' => 'Transmittal item removed', 'transmittalitem_updated' => 'Dokument bol aktualizovaný na najnovšiu verziu', 'transmittal_comment' => 'Komentár', 'transmittal_name' => 'Názov', 'transmittal_size' => 'Veľkosť', 'tree_loading' => 'Prosím počkajte kým sa nahrá strom dokumentov...', -'trigger_workflow' => '', +'trigger_workflow' => 'Workflow', 'tr_TR' => 'Turecky', 'tuesday' => 'Utorok', 'tuesday_abbr' => 'Ut', -'type_of_hook' => 'Typ', -'type_to_search' => 'Vyhľadať typ', +'type_of_hook' => 'Zadajte', +'type_to_search' => 'Zadajte na vyhľadanie', 'uk_UA' => 'Ukrajinsky', 'under_folder' => 'V zložke', 'unknown_attrdef' => 'Neznáme definovanie atribútu', @@ -1554,13 +1789,13 @@ URL: [url]', 'update_fulltext_index' => 'Aktualizovať fulltext index', 'update_info' => 'Aktualizovať informácie', 'update_locked_msg' => 'Tento dokument je zamknutý.', -'update_recipients' => '', -'update_reviewers' => 'Aktualizovať zoznam kontrolórov', -'update_revisors' => '', -'update_transmittalitem' => '', -'uploaded_by' => 'Nahral', -'uploading_failed' => 'Nahranie zlyhalo. Prosám, kontaktujte správcu.', -'uploading_maxsize' => 'Uploadovaný súbor prekročil maximálnu povolenú velkosť.', +'update_recipients' => 'Aktualizovať zoznam recipientov', +'update_reviewers' => 'Aktualizovať zoznam recenzentov', +'update_revisors' => 'Update list of resubmitters', +'update_transmittalitem' => 'Update to latest document version', +'uploaded_by' => 'Nahral/a', +'uploading_failed' => 'Nahranie niektorého súboru zlyhalo. Preverte maximálnu povolenú veľkosť.', +'uploading_maxsize' => 'Nahrávaný súbor prekročil maximálnu povolenú velkosť.', 'uploading_zerosize' => 'Nahrávate prázdny súbor. Nahrávanie je zrušené.', 'used_discspace' => 'Využitý priestor na disku', 'user' => 'Používateľ', @@ -1583,11 +1818,16 @@ URL: [url]', 'valid_till' => 'Platný do', 'version' => 'Verzia', 'versioning_file_creation' => 'Vytvorenie verziovacieho súboru', -'versioning_file_creation_warning' => 'Touto akciou môžete vytvoriť súbor, obsahujúci verziovaciu informáciu celej DMS zložky. Po vytvorení bude každý súbor uložený do zložky súborov.', +'versioning_file_creation_warning' => 'Touto operáciou môžete vytvoriť súbor pre každý dokument, obsahujúci verziovaciu informáciu toho dokumentu. Po vytvorení bude každý súbor uložený do zložky dokumentu. Those files are not needed for the regular operation of the dms, but could be of value if the complete repository shall be transferred to an other system.', 'versioning_info' => 'Informácie o verziách', 'versiontolow' => 'Verzia je nízka', 'version_deleted_email' => 'Verzia zmazana', -'version_deleted_email_body' => 'Verzia bola zmazaná Dokument: [name] Verzia: [version] Nadradená zložka: [folder_path] Používateľ: [username] URL: [url]', +'version_deleted_email_body' => 'Verzia bola zmazaná +Dokument: [name] +Verzia: [version] +Nadradená zložka: [folder_path] +Používateľ: [username] +URL: [url]', 'version_deleted_email_subject' => '[sitename]: [name] - Verzia bola odstránená', 'version_info' => 'Informácie o verzii', 'view' => 'Zobraziť', @@ -1597,33 +1837,33 @@ URL: [url]', 'wednesday_abbr' => 'St', 'weeks' => 'týždne', 'week_view' => 'Týždeň', -'workflow' => '', -'workflows_involded' => '', -'workflow_actions_management' => '', -'workflow_action_in_use' => '', +'workflow' => 'Workflow', +'workflows_involded' => 'Involved in workflow', +'workflow_actions_management' => 'Workflow actions management', +'workflow_action_in_use' => 'This action is currently used by workflows.', 'workflow_action_name' => 'Názov', -'workflow_editor' => '', -'workflow_group_summary' => '', -'workflow_has_cycle' => '', -'workflow_initstate' => '', -'workflow_in_use' => '', -'workflow_layoutdata_saved' => '', -'workflow_management' => '', +'workflow_editor' => 'Workflow Editor', +'workflow_group_summary' => 'Group summary', +'workflow_has_cycle' => 'Workflow has cycle', +'workflow_initstate' => 'Initial state', +'workflow_in_use' => 'This workflow is currently used by documents.', +'workflow_layoutdata_saved' => 'Layout data saved', +'workflow_management' => 'Workflow management', 'workflow_name' => 'Názov', -'workflow_no_doc_rejected_state' => '', -'workflow_no_doc_released_state' => '', -'workflow_no_initial_state' => '', -'workflow_no_states' => '', -'workflow_save_layout' => '', -'workflow_state' => '', -'workflow_states_management' => '', +'workflow_no_doc_rejected_state' => 'The document will not be rejected in a workflow state!', +'workflow_no_doc_released_state' => 'The document will not be released in a workflow state!', +'workflow_no_initial_state' => 'None of the transitions starts with the initial state of the workflow!', +'workflow_no_states' => 'You must first define workflow states, before adding a workflow.', +'workflow_save_layout' => 'Save layout', +'workflow_state' => 'workflow state', +'workflow_states_management' => 'Workflow states management', 'workflow_state_docstatus' => 'Stav dokumentu', -'workflow_state_in_use' => '', +'workflow_state_in_use' => 'This state is currently used by workflows.', 'workflow_state_name' => 'Názov', -'workflow_summary' => '', -'workflow_transition_without_user_group' => '', -'workflow_user_summary' => '', -'x_more_objects' => 'viac objektov', +'workflow_summary' => 'Workflow summary', +'workflow_transition_without_user_group' => 'At least one of the transitions has neither a user nor a group!', +'workflow_user_summary' => 'User summary', +'x_more_objects' => 'ďalších [number] objektov', 'year_view' => 'Rok', 'yes' => 'Áno', 'zh_CN' => 'Čínština (CN)', diff --git a/languages/sv_SE/lang.inc b/languages/sv_SE/lang.inc index 5ed1f361d..ec4285d62 100644 --- a/languages/sv_SE/lang.inc +++ b/languages/sv_SE/lang.inc @@ -199,6 +199,7 @@ URL: [url]', 'at_least_n_users_of_group' => 'Åtminstone [number_of_users] användare av [group]', 'august' => 'Augusti', 'authentication' => 'Autentisering', +'authentication_failed' => '', 'author' => 'Författare', 'automatic_status_update' => 'Automatisk ändring av status', 'back' => 'Tillbaka', @@ -494,6 +495,7 @@ Länken är giltig t o m [valid]. 'error_add_aro' => 'Fel vid begärd åtkomst till objekt', 'error_add_permission' => 'Fel vid tilldelning av behörighet', 'error_cleared_cache' => 'Fel vid rensning av cache', +'error_edit_task' => '', 'error_extension_getlist' => '', 'error_importfs' => 'Fel vid import från filsystem', 'error_no_document_selected' => 'Inget dokument har valts', @@ -502,8 +504,12 @@ Länken är giltig t o m [valid]. 'error_remove_document' => 'Fel vid radering av dokument', 'error_remove_folder' => 'Fel vid radering av katalog', 'error_remove_permission' => 'Fel vid borttagen behörighet', +'error_rm_workflow' => '', +'error_rm_workflow_action' => '', +'error_rm_workflow_state' => '', 'error_toogle_permission' => 'Fel vid förändring av behörighet', 'error_transfer_document' => 'Fel vid förflyttning av dokument', +'error_trigger_workflow' => '', 'error_update_document' => '', 'error_uploading_reviewer_only' => '', 'es_ES' => 'Spanska', @@ -646,7 +652,6 @@ URL: [url]', 'index_waiting' => 'Väntar', 'individuals' => 'Personer', 'individuals_in_groups' => 'Medlemmar i en grupp', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => '', 'inherited' => 'ärvd', 'inherits_access_copy_msg' => 'Kopiera lista för behörighetsarv', @@ -739,9 +744,11 @@ URL: [url]', 'login_error_title' => 'Fel vid inloggningen', 'login_not_given' => 'Användarnamn saknas', 'login_ok' => 'Inloggningen lyckades', +'login_restrictions_apply' => '', 'logout' => 'Logga ut', 'log_management' => 'Loggfilshantering', 'lo_LA' => 'Laotisk', +'malformed_expiration_date' => '', 'manager' => 'Manager', 'manager_of_group' => 'Du är förvaltaren av denna grupp', 'mandatory_approvergroups' => 'Obligatoriska grupper för godkännande', @@ -756,6 +763,7 @@ URL: [url]', 'max_upload_size' => 'Maximal storlek för uppladdning', 'may' => 'Maj', 'menu_dropfolder' => 'Mapp för snabbuppladdning', +'menu_upload_from_dropfolder' => '', 'mimetype' => 'Mimetyp', 'minutes' => 'minuter', 'misc' => 'Diverse', @@ -1190,6 +1198,8 @@ Kommentar: [comment]', 'settings_Advanced' => 'Avancerat', 'settings_advancedAcl' => 'Avancerad åtkomstkontroll', 'settings_advancedAcl_desc' => 'Avancerad åtkomskontroll används för att aktivera/avaktivera särskilda moduler i mjukvaran. Du kan inte använda denna funktion för att ange åtkomst till dokument eller kataloger.', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', 'settings_allowReviewerOnly' => '', 'settings_allowReviewerOnly_desc' => '', 'settings_apache_mod_rewrite' => 'Apache - Module Rewrite', @@ -1341,6 +1351,8 @@ Kommentar: [comment]', 'settings_enableVersionModification_desc' => 'Aktivera/Inaktivera modifiering av en dokumentversionen genom användare efter att en version har laddats upp. Administratören kan alltid ändra versionen efter att den har laddats upp.', 'settings_enableWebdavReplaceDoc' => '', 'settings_enableWebdavReplaceDoc_desc' => '', +'settings_enableXsendfile' => '', +'settings_enableXsendfile_desc' => '', 'settings_encryptionKey' => 'Krypteringsnyckel', 'settings_encryptionKey_desc' => 'Denna sträng används för att generera en unik identifierare, som är inrymd som ett dolt fält i ett formulär. Det används för att förhindra CSRF-attacker.', 'settings_error' => 'Fel', @@ -1564,6 +1576,7 @@ Kommentar: [comment]', 'splash_edit_event' => 'Händelse sparad', 'splash_edit_group' => 'Grupp sparad', 'splash_edit_role' => 'Roll sparad', +'splash_edit_task' => '', 'splash_edit_user' => 'Användare sparad', 'splash_error_add_to_transmittal' => '', 'splash_error_rm_download_link' => 'Fel vid borttagande av nedladdningslänk', @@ -1594,6 +1607,9 @@ Kommentar: [comment]', 'splash_rm_transmittal' => 'Meddelande raderat', 'splash_rm_user' => 'Användare har tagits bort', 'splash_rm_user_processes' => 'Användare borttagen från alla processer', +'splash_rm_workflow' => '', +'splash_rm_workflow_action' => '', +'splash_rm_workflow_state' => '', 'splash_saved_file' => 'Version sparad', 'splash_save_user_data' => 'Användarinställningar sparade', 'splash_send_download_link' => 'Nedladdningslänk skickad via e-post.', @@ -1606,6 +1622,7 @@ Kommentar: [comment]', 'splash_toogle_group_manager' => 'Gruppmanager har ändrats', 'splash_transfer_document' => 'Dokument överfört', 'splash_transfer_objects' => 'Objekt överförda', +'splash_trigger_workflow' => '', 'state_and_next_state' => 'Status/Nästa status', 'statistic' => 'Statistik', 'status' => 'Status', diff --git a/languages/tr_TR/lang.inc b/languages/tr_TR/lang.inc index 02e128f2c..393ebd32e 100644 --- a/languages/tr_TR/lang.inc +++ b/languages/tr_TR/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (1074), aydin (83) +// Translators: Admin (1082), aydin (83) $text = array( '2_factor_auth' => '', @@ -192,6 +192,7 @@ URL: [url]', 'at_least_n_users_of_group' => '[group] için en az [number_of_users] kullanıcı', 'august' => 'Ağustos', 'authentication' => 'Kimlik doğrulama', +'authentication_failed' => '', 'author' => 'Yazan', 'automatic_status_update' => 'Otomatik durumu değişimi', 'back' => 'Geri dön', @@ -292,7 +293,7 @@ URL: [url]', 'confirm_update_transmittalitem' => '', 'content' => 'İçerik', 'continue' => 'Devam', -'converter_new_cmd' => '', +'converter_new_cmd' => 'Komut', 'converter_new_mimetype' => '', 'copied_to_checkout_as' => '', 'create_download_link' => '', @@ -475,6 +476,7 @@ URL: [url]', 'error_add_aro' => '', 'error_add_permission' => '', 'error_cleared_cache' => '', +'error_edit_task' => '', 'error_extension_getlist' => '', 'error_importfs' => '', 'error_no_document_selected' => 'Hiçbir doküman seçilmedi', @@ -483,8 +485,12 @@ URL: [url]', 'error_remove_document' => '', 'error_remove_folder' => '', 'error_remove_permission' => '', +'error_rm_workflow' => '', +'error_rm_workflow_action' => '', +'error_rm_workflow_state' => '', 'error_toogle_permission' => '', 'error_transfer_document' => '', +'error_trigger_workflow' => '', 'error_update_document' => '', 'error_uploading_reviewer_only' => '', 'es_ES' => 'İspanyolca', @@ -627,7 +633,6 @@ URL: [url]', 'index_waiting' => 'Bekliyor', 'individuals' => 'Bireysel', 'individuals_in_groups' => '', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => '', 'inherited' => 'devralındı', 'inherits_access_copy_msg' => 'Devralınan erişim listesini kopyala', @@ -720,9 +725,11 @@ URL: [url]', 'login_error_title' => 'Hatalı giriş', 'login_not_given' => 'Kullanıcı adı verilmedi', 'login_ok' => 'Giriş başarılı', +'login_restrictions_apply' => '', 'logout' => 'Çıkış', 'log_management' => 'Log yönetimi', 'lo_LA' => 'Laotian', +'malformed_expiration_date' => '', 'manager' => 'Yönetici', 'manager_of_group' => 'Bu grubun yöneticisi sizsiniz', 'mandatory_approvergroups' => 'Onaylayıcılar için zorunlu grup', @@ -737,6 +744,7 @@ URL: [url]', 'max_upload_size' => 'Maksimum yükleme boyutu', 'may' => 'Mayıs', 'menu_dropfolder' => '', +'menu_upload_from_dropfolder' => '', 'mimetype' => 'Mime tipi', 'minutes' => 'dakika', 'misc' => 'Diğer', @@ -1131,7 +1139,7 @@ URL: [url]', 'send_login_data' => '', 'send_login_data_body' => '', 'send_login_data_subject' => '', -'send_test_mail' => '', +'send_test_mail' => 'Test maili gönder', 'september' => 'Eylül', 'sequence' => 'Sıralama', 'seq_after' => 'Şundan sonra: "[prevname]"', @@ -1149,11 +1157,13 @@ URL: [url]', 'settings_Advanced' => 'Gelişmiş ayarlar', 'settings_advancedAcl' => '', 'settings_advancedAcl_desc' => '', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', 'settings_allowReviewerOnly' => '', 'settings_allowReviewerOnly_desc' => '', 'settings_apache_mod_rewrite' => 'Apache - Module Rewrite', 'settings_Authentication' => 'Yetkilendirme ayarları', -'settings_autoLoginUser' => '', +'settings_autoLoginUser' => 'otomatik giriş', 'settings_autoLoginUser_desc' => '', 'settings_available_languages' => 'kullanılabilir diller', 'settings_available_languages_desc' => '', @@ -1300,6 +1310,8 @@ URL: [url]', 'settings_enableVersionModification_desc' => 'Bu etkinleştirilirse kullanıcılar yeni doküman yüklediklerinde versiyon numaralarını değiştirebilirler. Yöneticiler yükleme yaptıklarında her zaman değişiklik yapabilirler.', 'settings_enableWebdavReplaceDoc' => '', 'settings_enableWebdavReplaceDoc_desc' => '', +'settings_enableXsendfile' => '', +'settings_enableXsendfile_desc' => '', 'settings_encryptionKey' => 'Şifreleme anahtarı', 'settings_encryptionKey_desc' => 'Bu string, CSRF ataklarını önlemek için eşsiz id olarak kaydedilir.', 'settings_error' => 'Hata', @@ -1433,7 +1445,7 @@ URL: [url]', 'settings_smtpPort_desc' => 'SMTP Sunucu portu, varsayılan 25', 'settings_smtpSendFrom' => 'Kimden', 'settings_smtpSendFrom_desc' => 'Gönderilecek e-postalar kimden gidecek', -'settings_smtpSendTestMail' => '', +'settings_smtpSendTestMail' => 'Test maili gönder', 'settings_smtpSendTestMail_desc' => '', 'settings_smtpServer' => 'SMTP Sunucu adı/adresi', 'settings_smtpServer_desc' => 'SMTP sunucu adı/adresi', @@ -1523,6 +1535,7 @@ URL: [url]', 'splash_edit_event' => '', 'splash_edit_group' => 'Grup kaydedildi', 'splash_edit_role' => '', +'splash_edit_task' => '', 'splash_edit_user' => 'Kullanıcı kaydedildi', 'splash_error_add_to_transmittal' => '', 'splash_error_rm_download_link' => '', @@ -1553,6 +1566,9 @@ URL: [url]', 'splash_rm_transmittal' => '', 'splash_rm_user' => 'Kullanıcı silindi', 'splash_rm_user_processes' => '', +'splash_rm_workflow' => '', +'splash_rm_workflow_action' => '', +'splash_rm_workflow_state' => '', 'splash_saved_file' => '', 'splash_save_user_data' => '', 'splash_send_download_link' => '', @@ -1565,6 +1581,7 @@ URL: [url]', 'splash_toogle_group_manager' => 'Grup yöneticisi değişti', 'splash_transfer_document' => '', 'splash_transfer_objects' => '', +'splash_trigger_workflow' => '', 'state_and_next_state' => 'Durum/Sonraki durum', 'statistic' => 'İstatistik', 'status' => 'Durum', @@ -1651,11 +1668,11 @@ URL: [url]', 'toggle_qrcode' => '', 'to_before_from' => 'Bitiş tarihi başlama tarihinden önce olamaz', 'transfer_document' => 'Dokumanı gönder', -'transfer_no_read_access' => '', +'transfer_no_read_access' => 'Kullanıcının klasörde okuma erişimi yok.', 'transfer_no_write_access' => 'Kullanıcının klasör üzerinde yazma hakkı yok', 'transfer_objects' => '', 'transfer_objects_to_user' => '', -'transfer_to_user' => '', +'transfer_to_user' => 'Kullanıcıya transfer et', 'transition_triggered_email' => 'İş Akış Geçişi Tetiklendi', 'transition_triggered_email_body' => 'İş Akış Geçişi Tetiklendi Doküman: [name] diff --git a/languages/uk_UA/lang.inc b/languages/uk_UA/lang.inc index e5c9df8e3..c69a2334b 100644 --- a/languages/uk_UA/lang.inc +++ b/languages/uk_UA/lang.inc @@ -198,6 +198,7 @@ URL: [url]', 'at_least_n_users_of_group' => '[number_of_users] користувачі групи [group]', 'august' => 'Серпень', 'authentication' => 'Авторизація', +'authentication_failed' => '', 'author' => 'Автор', 'automatic_status_update' => 'Автоматична зміна статусу', 'back' => 'Назад', @@ -481,6 +482,7 @@ URL: [url]', 'error_add_aro' => '', 'error_add_permission' => '', 'error_cleared_cache' => '', +'error_edit_task' => '', 'error_extension_getlist' => '', 'error_importfs' => '', 'error_no_document_selected' => 'Немає вибраних документів', @@ -489,8 +491,12 @@ URL: [url]', 'error_remove_document' => '', 'error_remove_folder' => '', 'error_remove_permission' => '', +'error_rm_workflow' => '', +'error_rm_workflow_action' => '', +'error_rm_workflow_state' => '', 'error_toogle_permission' => '', 'error_transfer_document' => '', +'error_trigger_workflow' => '', 'error_update_document' => '', 'error_uploading_reviewer_only' => '', 'es_ES' => 'Spanish', @@ -633,7 +639,6 @@ URL: [url]', 'index_waiting' => '', 'individuals' => 'Користувачі', 'individuals_in_groups' => 'Користувачі групи', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => '', 'inherited' => 'успадкований', 'inherits_access_copy_msg' => 'Скопіювати успадкований список', @@ -726,9 +731,11 @@ URL: [url]', 'login_error_title' => 'Помилка входу', 'login_not_given' => 'Не вказано користувача', 'login_ok' => 'Вхід успішний', +'login_restrictions_apply' => '', 'logout' => 'Вихід', 'log_management' => 'Керування журналами', 'lo_LA' => 'Лаоська', +'malformed_expiration_date' => '', 'manager' => 'Менеджер', 'manager_of_group' => 'Менеджер групи', 'mandatory_approvergroups' => 'Обов\'язкові групи затвержувачів', @@ -743,6 +750,7 @@ URL: [url]', 'max_upload_size' => 'Обмеження розміру файлу', 'may' => 'Травень', 'menu_dropfolder' => '', +'menu_upload_from_dropfolder' => '', 'mimetype' => 'MIME-тип', 'minutes' => 'хвилини', 'misc' => 'Інше', @@ -1170,6 +1178,8 @@ URL: [url]', 'settings_Advanced' => 'Додатково', 'settings_advancedAcl' => '', 'settings_advancedAcl_desc' => '', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', 'settings_allowReviewerOnly' => '', 'settings_allowReviewerOnly_desc' => '', 'settings_apache_mod_rewrite' => 'Apache — модуль Rewrite', @@ -1321,6 +1331,8 @@ URL: [url]', 'settings_enableVersionModification_desc' => 'Дозволити/заборонити звичайним користувачам змінювати версію документів після завантаження їх на сервер. Адміністратор завжди зможе змінювати версії документів після завантаження їх на сервер.', 'settings_enableWebdavReplaceDoc' => '', 'settings_enableWebdavReplaceDoc_desc' => '', +'settings_enableXsendfile' => '', +'settings_enableXsendfile_desc' => '', 'settings_encryptionKey' => 'Ключ шифрування', 'settings_encryptionKey_desc' => 'Рядок використовується для створення унікального ідентифікатора, який додається як приховане поле до формулярів, для запобігання CSRF-атак.', 'settings_error' => 'Помилка', @@ -1544,6 +1556,7 @@ URL: [url]', 'splash_edit_event' => '', 'splash_edit_group' => 'Групу збережено', 'splash_edit_role' => '', +'splash_edit_task' => '', 'splash_edit_user' => 'Користувача збережено', 'splash_error_add_to_transmittal' => '', 'splash_error_rm_download_link' => '', @@ -1574,6 +1587,9 @@ URL: [url]', 'splash_rm_transmittal' => '', 'splash_rm_user' => 'Користувача видалено', 'splash_rm_user_processes' => '', +'splash_rm_workflow' => '', +'splash_rm_workflow_action' => '', +'splash_rm_workflow_state' => '', 'splash_saved_file' => '', 'splash_save_user_data' => '', 'splash_send_download_link' => '', @@ -1586,6 +1602,7 @@ URL: [url]', 'splash_toogle_group_manager' => 'Змінено менеджера групи', 'splash_transfer_document' => '', 'splash_transfer_objects' => '', +'splash_trigger_workflow' => '', 'state_and_next_state' => 'Статус / наступний статус', 'statistic' => 'Статистика', 'status' => 'Статус', diff --git a/languages/zh_CN/lang.inc b/languages/zh_CN/lang.inc index 4e2160251..5f13d24f7 100644 --- a/languages/zh_CN/lang.inc +++ b/languages/zh_CN/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (749), archonwang (469), fengjohn (5), yang86 (1) +// Translators: Admin (757), archonwang (469), fengjohn (5), yang86 (1) $text = array( '2_factor_auth' => '双重认证', @@ -190,6 +190,7 @@ URL: [url]', 'at_least_n_users_of_group' => '', 'august' => '八 月', 'authentication' => '认证', +'authentication_failed' => '', 'author' => '作者', 'automatic_status_update' => '自动状态变化', 'back' => '返回', @@ -265,7 +266,7 @@ URL: [url]', 'comment' => '说明', 'comment_changed_email' => '', 'comment_for_current_version' => '版本说明', -'configure_extension' => '', +'configure_extension' => '配置扩展', 'confirm_clear_cache' => '', 'confirm_create_fulltext_index' => '确认重新创建全文索引', 'confirm_move_document' => '', @@ -414,7 +415,7 @@ URL: [url]', 'does_not_expire' => '永不过期', 'does_not_inherit_access_msg' => '继承访问权限', 'download' => '下载', -'download_extension' => '', +'download_extension' => '以ZIP格式下载扩展', 'download_links' => '下载链接', 'download_link_email_body' => '点击以下链接下载文档 \'[docname]\' 的 [version] 版本。 @@ -481,6 +482,7 @@ URL: [url]', 'error_add_aro' => '', 'error_add_permission' => '添加权限时出错', 'error_cleared_cache' => '清理缓存时出错', +'error_edit_task' => '', 'error_extension_getlist' => '', 'error_importfs' => '从文件系统导入时出错', 'error_no_document_selected' => '请选择文档', @@ -489,8 +491,12 @@ URL: [url]', 'error_remove_document' => '删除文档时出错', 'error_remove_folder' => '删除文件夹时出错', 'error_remove_permission' => '移除权限时报错', +'error_rm_workflow' => '', +'error_rm_workflow_action' => '', +'error_rm_workflow_state' => '', 'error_toogle_permission' => '修改权限时报错', 'error_transfer_document' => '', +'error_trigger_workflow' => '', 'error_update_document' => '', 'error_uploading_reviewer_only' => '', 'es_ES' => '西班牙语', @@ -516,9 +522,9 @@ URL: [url]', 'export' => '导出', 'extension_archive' => '', 'extension_changelog' => '更新日志', -'extension_loading' => '', +'extension_loading' => '加载扩展', 'extension_manager' => '扩展管理器', -'extension_mgr_installed' => '', +'extension_mgr_installed' => '已安装', 'extension_mgr_no_upload' => '上传新扩展名是不可能的,因为extentension目录不可写', 'extension_mgr_repository' => '可得到', 'extension_version_list' => '版本列表', @@ -629,7 +635,6 @@ URL: [url]', 'index_waiting' => '', 'individuals' => '个人', 'individuals_in_groups' => '组成员', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => '', 'inherited' => '继承', 'inherits_access_copy_msg' => '复制继承访问权限列表', @@ -722,9 +727,11 @@ URL: [url]', 'login_error_title' => '登录错误', 'login_not_given' => '缺少用户名', 'login_ok' => '登录成功', +'login_restrictions_apply' => '', 'logout' => '登出', 'log_management' => '日志管理', 'lo_LA' => '老挝', +'malformed_expiration_date' => '', 'manager' => '管理员', 'manager_of_group' => '您是当前组的管理员', 'mandatory_approvergroups' => '', @@ -739,6 +746,7 @@ URL: [url]', 'max_upload_size' => '最大上传文件大小', 'may' => '五 月', 'menu_dropfolder' => '删除文件夹', +'menu_upload_from_dropfolder' => '', 'mimetype' => 'MIME类型', 'minutes' => '分钟', 'misc' => '其他', @@ -1151,6 +1159,8 @@ URL: [url]', 'settings_Advanced' => '高级设置', 'settings_advancedAcl' => '高级访问控制', 'settings_advancedAcl_desc' => '', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', 'settings_allowReviewerOnly' => '', 'settings_allowReviewerOnly_desc' => '', 'settings_apache_mod_rewrite' => '', @@ -1302,6 +1312,8 @@ URL: [url]', 'settings_enableVersionModification_desc' => '通过用户上传新版本,启用/禁用文档版本修改', 'settings_enableWebdavReplaceDoc' => '', 'settings_enableWebdavReplaceDoc_desc' => '', +'settings_enableXsendfile' => '', +'settings_enableXsendfile_desc' => '', 'settings_encryptionKey' => '加密密钥', 'settings_encryptionKey_desc' => '', 'settings_error' => '错误', @@ -1399,8 +1411,8 @@ URL: [url]', 'settings_previewWidthDropFolderList_desc' => '', 'settings_previewWidthList' => '缩略图宽度(列表中)', 'settings_previewWidthList_desc' => '列表中缩略图的宽度', -'settings_previewWidthMenuList' => '', -'settings_previewWidthMenuList_desc' => '', +'settings_previewWidthMenuList' => '预览图像的宽度(菜单列表)', +'settings_previewWidthMenuList_desc' => '预览图像的宽度显示为丢弃文件夹菜单中的项目', 'settings_printDisclaimer' => '显示免责声明', 'settings_printDisclaimer_desc' => '如果开启,这个免责声明信息将在每个页面的底部显示', 'settings_quota' => '设置磁盘配额', @@ -1494,8 +1506,8 @@ URL: [url]', 'set_owner_error' => '错误 设置所有者', 'set_password' => '设定密码', 'set_workflow' => '', -'show_extension_changelog' => '', -'show_extension_version_list' => '', +'show_extension_changelog' => '显示更新记录', +'show_extension_version_list' => '显示版本列表', 'signed_in_as' => '登录为', 'sign_in' => '登录', 'sign_out' => '登出', @@ -1525,6 +1537,7 @@ URL: [url]', 'splash_edit_event' => '事件已保存', 'splash_edit_group' => '组已保存', 'splash_edit_role' => '角色已保存', +'splash_edit_task' => '', 'splash_edit_user' => '用户信息已保存', 'splash_error_add_to_transmittal' => '', 'splash_error_rm_download_link' => '移除下载链接时报错', @@ -1555,6 +1568,9 @@ URL: [url]', 'splash_rm_transmittal' => '', 'splash_rm_user' => '用户信息已删除', 'splash_rm_user_processes' => '', +'splash_rm_workflow' => '', +'splash_rm_workflow_action' => '', +'splash_rm_workflow_state' => '', 'splash_saved_file' => '版本已保存', 'splash_save_user_data' => '用户数据已保存', 'splash_send_download_link' => '下载链接已通过邮件发送。', @@ -1567,6 +1583,7 @@ URL: [url]', 'splash_toogle_group_manager' => '', 'splash_transfer_document' => '', 'splash_transfer_objects' => '', +'splash_trigger_workflow' => '', 'state_and_next_state' => '', 'statistic' => '统计', 'status' => '状态', diff --git a/languages/zh_TW/lang.inc b/languages/zh_TW/lang.inc index 73a16464b..ec317d2be 100644 --- a/languages/zh_TW/lang.inc +++ b/languages/zh_TW/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (2415) +// Translators: Admin (2417) $text = array( '2_factor_auth' => '', @@ -173,6 +173,7 @@ URL: [url]', 'at_least_n_users_of_group' => '', 'august' => '八 月', 'authentication' => '', +'authentication_failed' => '', 'author' => '作者', 'automatic_status_update' => '自動狀態變化', 'back' => '返回', @@ -426,6 +427,7 @@ URL: [url]', 'error_add_aro' => '', 'error_add_permission' => '', 'error_cleared_cache' => '', +'error_edit_task' => '', 'error_extension_getlist' => '', 'error_importfs' => '', 'error_no_document_selected' => '請選擇文檔', @@ -434,8 +436,12 @@ URL: [url]', 'error_remove_document' => '', 'error_remove_folder' => '', 'error_remove_permission' => '', +'error_rm_workflow' => '', +'error_rm_workflow_action' => '', +'error_rm_workflow_state' => '', 'error_toogle_permission' => '', 'error_transfer_document' => '', +'error_trigger_workflow' => '', 'error_update_document' => '', 'error_uploading_reviewer_only' => '', 'es_ES' => '西班牙語', @@ -554,7 +560,6 @@ URL: [url]', 'index_waiting' => '請稍後', 'individuals' => '個人', 'individuals_in_groups' => '', -'indivіduals_in_groups' => '', 'info_recipients_tab_not_released' => '', 'inherited' => '繼承', 'inherits_access_copy_msg' => '複製繼承存取權限列表', @@ -647,9 +652,11 @@ URL: [url]', 'login_error_title' => '登錄錯誤', 'login_not_given' => '缺少用戶名', 'login_ok' => '登錄成功', +'login_restrictions_apply' => '', 'logout' => '登出', 'log_management' => '日誌管理', 'lo_LA' => '', +'malformed_expiration_date' => '', 'manager' => '管理員', 'manager_of_group' => '', 'mandatory_approvergroups' => '', @@ -664,6 +671,7 @@ URL: [url]', 'max_upload_size' => '最大上傳文件大小', 'may' => '五 月', 'menu_dropfolder' => '', +'menu_upload_from_dropfolder' => '', 'mimetype' => 'MIME類型', 'minutes' => '', 'misc' => '其他', @@ -976,7 +984,7 @@ URL: [url]', 'select_one' => '選擇一個', 'select_user' => '', 'select_users' => '點擊選擇用戶', -'select_value' => '', +'select_value' => '選取值', 'select_workflow' => '', 'send_email' => '', 'send_login_data' => '', @@ -1000,6 +1008,8 @@ URL: [url]', 'settings_Advanced' => '進階', 'settings_advancedAcl' => '', 'settings_advancedAcl_desc' => '', +'settings_allowChangeRevAppInProcess' => '', +'settings_allowChangeRevAppInProcess_desc' => '', 'settings_allowReviewerOnly' => '', 'settings_allowReviewerOnly_desc' => '', 'settings_apache_mod_rewrite' => '', @@ -1151,6 +1161,8 @@ URL: [url]', 'settings_enableVersionModification_desc' => '', 'settings_enableWebdavReplaceDoc' => '', 'settings_enableWebdavReplaceDoc_desc' => '', +'settings_enableXsendfile' => '', +'settings_enableXsendfile_desc' => '', 'settings_encryptionKey' => '', 'settings_encryptionKey_desc' => '', 'settings_error' => '', @@ -1374,6 +1386,7 @@ URL: [url]', 'splash_edit_event' => '', 'splash_edit_group' => '', 'splash_edit_role' => '', +'splash_edit_task' => '', 'splash_edit_user' => '', 'splash_error_add_to_transmittal' => '', 'splash_error_rm_download_link' => '', @@ -1404,6 +1417,9 @@ URL: [url]', 'splash_rm_transmittal' => '', 'splash_rm_user' => '', 'splash_rm_user_processes' => '', +'splash_rm_workflow' => '', +'splash_rm_workflow_action' => '', +'splash_rm_workflow_state' => '', 'splash_saved_file' => '', 'splash_save_user_data' => '', 'splash_send_download_link' => '', @@ -1416,6 +1432,7 @@ URL: [url]', 'splash_toogle_group_manager' => '', 'splash_transfer_document' => '', 'splash_transfer_objects' => '', +'splash_trigger_workflow' => '', 'state_and_next_state' => '', 'statistic' => '', 'status' => '狀態', @@ -1615,7 +1632,7 @@ URL: [url]', 'workflow_summary' => '', 'workflow_transition_without_user_group' => '', 'workflow_user_summary' => '', -'x_more_objects' => '', +'x_more_objects' => '增加[數值]物件', 'year_view' => '年視圖', 'yes' => '是', 'zh_CN' => '中文簡體', diff --git a/op/op.AddDocument.php b/op/op.AddDocument.php index cace6483f..ec27f46c6 100644 --- a/op/op.AddDocument.php +++ b/op/op.AddDocument.php @@ -84,7 +84,8 @@ $categories = isset($_POST["categories"]) ? $_POST["categories"] : null; $cats = array(); if($categories) { foreach($categories as $catid) { - $cats[] = $dms->getDocumentCategory($catid); + if($cat = $dms->getDocumentCategory($catid)) + $cats[] = $cat; } } @@ -93,14 +94,15 @@ if(isset($_POST["attributes"])) else $attributes = array(); foreach($attributes as $attrdefid=>$attribute) { - $attrdef = $dms->getAttributeDefinition($attrdefid); - if($attribute) { - if(!$attrdef->validate($attribute)) { - $errmsg = getAttributeValidationText($attrdef->getValidationError(), $attrdef->getName(), $attribute); - UI::exitError(getMLText("folder_title", array("foldername" => $folder->getName())), $errmsg); + if($attrdef = $dms->getAttributeDefinition($attrdefid)) { + if($attribute) { + if(!$attrdef->validate($attribute)) { + $errmsg = getAttributeValidationText($attrdef->getValidationError(), $attrdef->getName(), $attribute); + UI::exitError(getMLText("folder_title", array("foldername" => $folder->getName())), $errmsg); + } + } elseif($attrdef->getMinValues() > 0) { + UI::exitError(getMLText("folder_title", array("foldername" => $folder->getName())),getMLText("attr_min_values", array("attrname"=>$attrdef->getName()))); } - } elseif($attrdef->getMinValues() > 0) { - UI::exitError(getMLText("folder_title", array("foldername" => $folder->getName())),getMLText("attr_min_values", array("attrname"=>$attrdef->getName()))); } } @@ -130,6 +132,8 @@ if (!is_numeric($sequence)) { switch($_POST["presetexpdate"]) { case "date": $tmp = explode('-', $_POST["expdate"]); + if(count($tmp) != 3) + UI::exitError(getMLText("folder_title", array("foldername" => $folder->getName())),getMLText("malformed_expiration_date")); $expires = mktime(0,0,0, $tmp[1], $tmp[2], $tmp[0]); break; case "1w": diff --git a/op/op.Ajax.php b/op/op.Ajax.php index b2a68d9b2..3e987b459 100644 --- a/op/op.Ajax.php +++ b/op/op.Ajax.php @@ -806,12 +806,14 @@ switch($command) { if(isset($GLOBALS['SEEDDMS_HOOKS']['indexDocument'])) { foreach($GLOBALS['SEEDDMS_HOOKS']['indexDocument'] as $hookObj) { if (method_exists($hookObj, 'preIndexDocument')) { - $hookObj->preIndexDocument(null, $document, $idoc); + if(false !== ($ires = $hookObj->preIndexDocument(null, $document, $idoc))) { + $ires = $index->addDocument($idoc); + } } } } header('Content-Type: application/json'); - if(false === $index->addDocument($idoc)) { + if(false === $ires) { echo json_encode(array('success'=>false, 'message'=>getMLText('error_document_indexed'), 'data'=>$document->getID())); } else { echo json_encode(array('success'=>true, 'message'=>getMLText('splash_document_indexed'), 'data'=>$document->getID(), 'cmd'=>$idoc->getCmd())); diff --git a/op/op.Download.php b/op/op.Download.php index 7b5b09a0f..888ca6032 100644 --- a/op/op.Download.php +++ b/op/op.Download.php @@ -58,16 +58,14 @@ if (isset($_GET["version"])) { /* {{{ */ UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("invalid_version")); } $version = $_GET["version"]; - $content = $document->getContentByVersion($version); - if (!is_object($content)) { + $controller->setParam('document', $document); + $controller->setParam('version', $version); + $controller->setParam('type', 'version'); + if(!$controller->run()) { UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("invalid_version")); } - $controller->setParam('content', $content); - $controller->setParam('type', 'version'); - $controller->run(); - } /* }}} */ elseif (isset($_GET["file"])) { /* {{{ */ diff --git a/op/op.DropFolderPreview.php b/op/op.DropFolderPreview.php index 89393af7d..8a0da1513 100644 --- a/op/op.DropFolderPreview.php +++ b/op/op.DropFolderPreview.php @@ -52,6 +52,8 @@ if(!empty($_GET["width"])) $previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir, $_GET["width"]); else $previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir); +$previewer->setConverters($settings->_converters['preview']); +$previewer->setXsendfile($settings->_enableXsendfile); if(!$previewer->hasRawPreview($dir.'/'.$filename, 'dropfolder/')) $previewer->createRawPreview($dir.'/'.$filename, 'dropfolder/'); header('Content-Type: image/png'); diff --git a/op/op.LockDocument.php b/op/op.LockDocument.php index 7992ef05b..a72b873fa 100644 --- a/op/op.LockDocument.php +++ b/op/op.LockDocument.php @@ -18,15 +18,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"])<1) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); diff --git a/op/op.Login.php b/op/op.Login.php index 6c5d40a3d..7f98452f9 100644 --- a/op/op.Login.php +++ b/op/op.Login.php @@ -31,21 +31,20 @@ include("../inc/inc.ClassController.php"); include $settings->_rootDir . "languages/" . $settings->_language . "/lang.inc"; -function _printMessage($heading, $message) { /* {{{ */ +function _printMessage($message) { /* {{{ */ global $session, $dms, $theme; header("Location:../out/out.Login.php?msg=".urlencode($message)); exit; - - UI::exitError($heading, $message, true); - return; } /* }}} */ $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $controller = Controller::factory($tmp[1], array('dms'=>$dms)); +$sesstheme = ''; if (isset($_REQUEST["sesstheme"]) && strlen($_REQUEST["sesstheme"])>0 && is_numeric(array_search($_REQUEST["sesstheme"],UI::getStyles())) ) { $theme = $_REQUEST["sesstheme"]; + $sesstheme = $_REQUEST["sesstheme"]; } if (isset($_REQUEST["login"])) { @@ -54,7 +53,7 @@ if (isset($_REQUEST["login"])) { } if (!isset($login) || strlen($login)==0) { - _printMessage(getMLText("login_error_title"), getMLText("login_not_given")."\n"); + _printMessage(getMLText("login_not_given")."\n"); exit; } @@ -66,147 +65,8 @@ if(isset($_POST['pwd'])) { } } -/* Initialy set $user to false. It will contain a valid user record - * if the user is a guest user or authentication will succeed. - */ -$user = false; - -/* The password may only be empty if the guest user tries to log in. - * There is just one guest account with id $settings->_guestID which - * is allowed to log in without a password. All other guest accounts - * are treated like regular logins - */ -if($settings->_enableGuestLogin && (int) $settings->_guestID) { - $guestUser = $dms->getUser((int) $settings->_guestID); - if(($login != $guestUser->getLogin())) { - if ((!isset($pwd) || strlen($pwd)==0)) { - _printMessage(getMLText("login_error_title"), getMLText("login_error_text")."\n"); - exit; - } - } else { - $user = $guestUser; - } -} - -if(!$user && isset($GLOBALS['SEEDDMS_HOOKS']['authentication'])) { - foreach($GLOBALS['SEEDDMS_HOOKS']['authentication'] as $authObj) { - if(!$user && method_exists($authObj, 'authenticate')) { - $user = $authObj->authenticate($dms, $settings, $login, $pwd); - } - } -} - -/* Authenticate against LDAP server {{{ */ -if (!$user && isset($settings->_ldapHost) && strlen($settings->_ldapHost)>0) { - require_once("../inc/inc.ClassLdapAuthentication.php"); - $authobj = new SeedDMS_LdapAuthentication($dms, $settings); - $user = $authobj->authenticate($login, $pwd); -} /* }}} */ - -/* Authenticate against SeedDMS database {{{ */ -if(!$user) { - require_once("../inc/inc.ClassDbAuthentication.php"); - $authobj = new SeedDMS_DbAuthentication($dms, $settings); - $user = $authobj->authenticate($login, $pwd); -} /* }}} */ - -if(!$user) { - _printMessage(getMLText("login_error_title"), getMLText("login_error_text")); - exit; -} - -$userid = $user->getID(); -if (($userid == $settings->_guestID) && (!$settings->_enableGuestLogin)) { - _printMessage(getMLText("login_error_title"), getMLText("guest_login_disabled")); - exit; -} - -// Check if account is disabled -if($user->isDisabled()) { - _printMessage(getMLText("login_disabled_title"), getMLText("login_disabled_text")); - exit; -} - -// control admin IP address if required -if ($user->isAdmin() && ($_SERVER['REMOTE_ADDR'] != $settings->_adminIP ) && ( $settings->_adminIP != "") ){ - _printMessage(getMLText("login_error_title"), getMLText("invalid_user_id")); - exit; -} - -/* Clear login failures if login was successful */ -$user->clearLoginFailures(); - -// Capture the user's language and theme settings. -if (isset($_REQUEST["lang"]) && strlen($_REQUEST["lang"])>0 && is_numeric(array_search($_REQUEST["lang"],getLanguages())) ) { - $lang = $_REQUEST["lang"]; - $user->setLanguage($lang); -} -else { - $lang = $user->getLanguage(); - if (strlen($lang)==0) { - $lang = $settings->_language; - $user->setLanguage($lang); - } -} -if (isset($_REQUEST["sesstheme"]) && strlen($_REQUEST["sesstheme"])>0 && is_numeric(array_search($_REQUEST["sesstheme"],UI::getStyles())) ) { - $sesstheme = $_REQUEST["sesstheme"]; - $user->setTheme($sesstheme); -} -else { - $sesstheme = $user->getTheme(); - if (strlen($sesstheme)==0) { - $sesstheme = $settings->_theme; -// $user->setTheme($sesstheme); - } -} - $session = new SeedDMS_Session($db); -// Delete all sessions that are more than 1 week or the configured -// cookie lifetime old. Probably not the most -// reliable place to put this check -- move to inc.Authentication.php? -if($settings->_cookieLifetime) - $lifetime = intval($settings->_cookieLifetime); -else - $lifetime = 7*86400; -if(!$session->deleteByTime($lifetime)) { - _printMessage(getMLText("login_error_title"), getMLText("error_occured").": ".$db->getErrorMsg()); - exit; -} - -if (isset($_COOKIE["mydms_session"])) { - /* This part will never be reached unless the session cookie is kept, - * but op.Logout.php deletes it. Keeping a session could be a good idea - * for retaining the clipboard data, but the user id in the session should - * be set to 0 which is not possible due to foreign key constraints. - * So for now op.Logout.php will delete the cookie as always - */ - /* Load session */ - $dms_session = $_COOKIE["mydms_session"]; - if(!$resArr = $session->load($dms_session)) { - /* Turn off http only cookies if jumploader is enabled */ - setcookie("mydms_session", $dms_session, time()-3600, $settings->_httpRoot, null, null, !$settings->_enableLargeFileUpload); //delete cookie - header("Location: " . $settings->_httpRoot . "out/out.Login.php?referuri=".$refer); - exit; - } else { - $session->updateAccess($dms_session); - $session->setUser($userid); - } -} else { - // Create new session in database - if(!$id = $session->create(array('userid'=>$userid, 'theme'=>$sesstheme, 'lang'=>$lang))) { - _printMessage(getMLText("login_error_title"), getMLText("error_occured").": ".$db->getErrorMsg()); - exit; - } - - // Set the session cookie. - if($settings->_cookieLifetime) - $lifetime = time() + intval($settings->_cookieLifetime); - else - $lifetime = 0; - setcookie("mydms_session", $id, $lifetime, $settings->_httpRoot, null, null, !$settings->_enableLargeFileUpload); -} - // TODO: by the PHP manual: The superglobals $_GET and $_REQUEST are already decoded. // Using urldecode() on an element in $_GET or $_REQUEST could have unexpected and dangerous results. @@ -219,9 +79,18 @@ else if (isset($_GET["referuri"]) && strlen($_GET["referuri"])>0) { add_log_line(); -$controller->setParam('user', $user); +$controller->setParam('login', $login); +$controller->setParam('pwd', $pwd); +$controller->setParam('lang', $lang); +$controller->setParam('sesstheme', $sesstheme); $controller->setParam('session', $session); -$controller->run(); +if(!$controller->run()) { + add_log_line("login failed", PEAR_LOG_ERR); + _printMessage(getMLText($controller->getErrorMsg()), getMLText($controller->getErrorMsg())."\n"); + exit; +} + +$user = $controller->getUser(); if (isset($referuri) && strlen($referuri)>0) { // header("Location: http".((isset($_SERVER['HTTPS']) && (strcmp($_SERVER['HTTPS'],'off')!=0)) ? "s" : "")."://".$_SERVER['HTTP_HOST'] . $referuri); diff --git a/op/op.PdfPreview.php b/op/op.PdfPreview.php index 48c85485f..62bc00dcb 100644 --- a/op/op.PdfPreview.php +++ b/op/op.PdfPreview.php @@ -69,7 +69,9 @@ if (!is_object($object)) { exit; } -$previewer = new SeedDMS_Preview_PdfPreviewer($settings->_cacheDir); +$previewer = new SeedDMS_Preview_PdfPreviewer($settings->_cacheDir, $settings->_cmdTimeout); +$previewer->setConverters(isset($settings->_converters['pdf']) ? $settings->_converters['pdf'] : array()); +$previewer->setXsendfile($settings->_enableXsendfile); if(!$previewer->hasPreview($object)) $previewer->createPreview($object); header('Content-Type: application/pdf'); diff --git a/op/op.Preview.php b/op/op.Preview.php index 488555945..ee6a3adf1 100644 --- a/op/op.Preview.php +++ b/op/op.Preview.php @@ -27,6 +27,7 @@ include("../inc/inc.Init.php"); include("../inc/inc.Extension.php"); include("../inc/inc.DBInit.php"); include("../inc/inc.ClassUI.php"); +include("../inc/inc.ClassController.php"); include("../inc/inc.Authentication.php"); /** @@ -34,6 +35,9 @@ include("../inc/inc.Authentication.php"); */ require_once("SeedDMS/Preview.php"); +$tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); +$controller = Controller::factory($tmp[1], array('dms'=>$dms, 'user'=>$user)); + $documentid = $_GET["documentid"]; if (!isset($documentid) || !is_numeric($documentid) || intval($documentid)<1) { exit; @@ -52,10 +56,15 @@ if(isset($_GET['version'])) { $version = $_GET["version"]; if (!is_numeric($version)) exit; - if(intval($version)<1) - $object = $document->getLatestContent(); - else - $object = $document->getContentByVersion($version); + + $controller->setParam('width', !empty($_GET["width"]) ? $_GET["width"] : null); + $controller->setParam('document', $document); + $controller->setParam('version', $version); + $controller->setParam('type', 'version'); + if(!$controller->run()) { + UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("invalid_version")); + } + exit; } elseif(isset($_GET['file'])) { $file = $_GET['file']; if (!is_numeric($file) || intval($file)<1) @@ -74,6 +83,7 @@ if(!empty($_GET["width"])) else $previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir); $previewer->setConverters($settings->_converters['preview']); +$previewer->setXsendfile($settings->_enableXsendfile); if(!$previewer->hasPreview($object)) { if(!$previewer->createPreview($object)) { } diff --git a/op/op.RemoveWorkflow.php b/op/op.RemoveWorkflow.php index 37865ddb0..fe361eb7c 100644 --- a/op/op.RemoveWorkflow.php +++ b/op/op.RemoveWorkflow.php @@ -46,9 +46,12 @@ if (!is_object($workflow)) { } if($workflow->remove()) { + $session->setSplashMsg(array('type'=>'success', 'msg'=>getMLText('splash_rm_workflow'))); +} else { + $session->setSplashMsg(array('type'=>'error', 'msg'=>getMLText('error_rm_workflow'))); } -add_log_line(""); +add_log_line("?workflowid=".$_POST["workflowid"]); header("Location:../out/out.WorkflowMgr.php"); ?> diff --git a/op/op.RemoveWorkflowAction.php b/op/op.RemoveWorkflowAction.php index 7fbf709c0..6d7e7c462 100644 --- a/op/op.RemoveWorkflowAction.php +++ b/op/op.RemoveWorkflowAction.php @@ -32,23 +32,26 @@ if (!$user->isAdmin()) { } /* Check if the form data comes from a trusted request */ -if(!checkFormKey('removeworkflowaction')) { +if(!checkFormKey('removeworkflowaction', 'GET')) { UI::exitError(getMLText("workflow_editor"), getMLText("invalid_request_token")); } -if (!isset($_POST["workflowactionid"]) || !is_numeric($_POST["workflowactionid"]) || intval($_POST["workflowactionid"])<1) { +if (!isset($_GET["workflowactionid"]) || !is_numeric($_GET["workflowactionid"]) || intval($_GET["workflowactionid"])<1) { UI::exitError(getMLText("workflow_editor"), getMLText("invalid_version")); } -$workflowaction = $dms->getWorkflowAction($_POST["workflowactionid"]); +$workflowaction = $dms->getWorkflowAction($_GET["workflowactionid"]); if (!is_object($workflowaction)) { UI::exitError(getMLText("workflow_editor"), getMLText("invalid_workflow_action")); } if($workflowaction->remove()) { + $session->setSplashMsg(array('type'=>'success', 'msg'=>getMLText('splash_rm_workflow_action'))); +} else { + $session->setSplashMsg(array('type'=>'error', 'msg'=>getMLText('error_rm_workflow_action'))); } -add_log_line("?workflowactionid=".$_POST["workflowactionid"]); +add_log_line("?workflowactionid=".$_GET["workflowactionid"]); header("Location:../out/out.WorkflowActionsMgr.php"); ?> diff --git a/op/op.RemoveWorkflowState.php b/op/op.RemoveWorkflowState.php index 3b82bff63..22ace8ff0 100644 --- a/op/op.RemoveWorkflowState.php +++ b/op/op.RemoveWorkflowState.php @@ -32,23 +32,25 @@ if (!$user->isAdmin()) { } /* Check if the form data comes from a trusted request */ -if(!checkFormKey('removeworkflowstate')) { +if(!checkFormKey('removeworkflowstate', 'GET')) { UI::exitError(getMLText("workflow_editor"), getMLText("invalid_request_token")); } -if (!isset($_POST["workflowstateid"]) || !is_numeric($_POST["workflowstateid"]) || intval($_POST["workflowstateid"])<1) { +if (!isset($_GET["workflowstateid"]) || !is_numeric($_GET["workflowstateid"]) || intval($_GET["workflowstateid"])<1) { UI::exitError(getMLText("workflow_editor"), getMLText("invalid_version")); } -$workflowstate = $dms->getWorkflowState($_POST["workflowstateid"]); +$workflowstate = $dms->getWorkflowState($_GET["workflowstateid"]); if (!is_object($workflowstate)) { UI::exitError(getMLText("workflow_editor"), getMLText("invalid_workflow_state")); } if($workflowstate->remove()) { + $session->setSplashMsg(array('type'=>'success', 'msg'=>getMLText('splash_rm_workflow_state'))); +} else { + $session->setSplashMsg(array('type'=>'error', 'msg'=>getMLText('error_rm_workflow_state'))); } -add_log_line("?workflowstateid=".$_POST["workflowstateid"]); +add_log_line("?workflowstateid=".$_GET["workflowstateid"]); header("Location:../out/out.WorkflowStatesMgr.php"); -?> diff --git a/op/op.Settings.php b/op/op.Settings.php index 61b6be6b7..d02deff6d 100644 --- a/op/op.Settings.php +++ b/op/op.Settings.php @@ -127,6 +127,7 @@ if ($action == "saveSettings") $settings->_enableLargeFileUpload = getBoolValue("enableLargeFileUpload"); $settings->_partitionSize = $_POST["partitionSize"]; $settings->_maxUploadSize = $_POST["maxUploadSize"]; + $settings->_enableXsendfile = getBoolValue("enableXsendfile"); // SETTINGS - SYSTEM - AUTHENTICATION $settings->_enableGuestLogin = getBoolValue("enableGuestLogin"); diff --git a/op/op.TriggerWorkflow.php b/op/op.TriggerWorkflow.php index 6d59f8ff6..0e0e46d4f 100644 --- a/op/op.TriggerWorkflow.php +++ b/op/op.TriggerWorkflow.php @@ -116,9 +116,13 @@ if($version->triggerWorkflowTransition($user, $transition, $_POST["comment"])) { $params['http_root'] = $settings->_httpRoot; $params['url'] = "http".((isset($_SERVER['HTTPS']) && (strcmp($_SERVER['HTTPS'],'off')!=0)) ? "s" : "")."://".$_SERVER['HTTP_HOST'].$settings->_httpRoot."out/out.ViewDocument.php?documentid=".$document->getID(); + $usersinformed = array(); foreach($workflow->getNextTransitions($transition->getNextState()) as $ntransition) { foreach($ntransition->getUsers() as $tuser) { - $notifier->toIndividual($user, $tuser->getUser(), $subject, $message, $params); + if(!in_array($tuser->getUser()->getID(), $usersinformed)) { + $usersinformed[] = $tuser->getUser()->getID(); + $notifier->toIndividual($user, $tuser->getUser(), $subject, $message, $params); + } } foreach($ntransition->getGroups() as $tuser) { $notifier->toGroup($user, $tuser->getGroup(), $subject, $message, $params); @@ -127,6 +131,8 @@ if($version->triggerWorkflowTransition($user, $transition, $_POST["comment"])) { } } + $session->setSplashMsg(array('type'=>'success', 'msg'=>getMLText('splash_trigger_workflow'))); + if(isset($GLOBALS['SEEDDMS_HOOKS']['triggerWorkflowTransition'])) { foreach($GLOBALS['SEEDDMS_HOOKS']['triggerWorkflowTransition'] as $hookObj) { if (method_exists($hookObj, 'postTriggerWorkflowTransition')) { @@ -134,6 +140,8 @@ if($version->triggerWorkflowTransition($user, $transition, $_POST["comment"])) { } } } +} else { + $session->setSplashMsg(array('type'=>'error', 'msg'=>getMLText('error_trigger_workflow'))); } add_log_line("?documentid=".$documentid."&version".$version_num); diff --git a/op/op.ViewOnline.php b/op/op.ViewOnline.php index 34ba3e108..79cdef8da 100644 --- a/op/op.ViewOnline.php +++ b/op/op.ViewOnline.php @@ -53,18 +53,12 @@ if(isset($_GET["version"])) { UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("invalid_version")); } - if(intval($version)<1) - $content = $document->getLatestContent(); - else - $content = $document->getContentByVersion($version); - - if (!is_object($content)) { + $controller->setParam('document', $document); + $controller->setParam('version', intval($version)); + $controller->setParam('type', 'version'); + if(!$controller->run()) { UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("invalid_version")); } - - $controller->setParam('content', $content); - $controller->setParam('type', 'version'); - $controller->run(); } elseif(isset($_GET["file"])) { $fileid = $_GET["file"]; diff --git a/out/out.AddDocument.php b/out/out.AddDocument.php index 1f693931e..82a68ec8e 100644 --- a/out/out.AddDocument.php +++ b/out/out.AddDocument.php @@ -19,15 +19,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.AddEvent.php b/out/out.AddEvent.php index 0412c9ccf..e97f2cf98 100644 --- a/out/out.AddEvent.php +++ b/out/out.AddEvent.php @@ -17,14 +17,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.AddFile.php b/out/out.AddFile.php index 88f35e789..79ac15d08 100644 --- a/out/out.AddFile.php +++ b/out/out.AddFile.php @@ -19,16 +19,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.AddSubFolder.php b/out/out.AddSubFolder.php index a6c573278..42216d13d 100644 --- a/out/out.AddSubFolder.php +++ b/out/out.AddSubFolder.php @@ -19,15 +19,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.AdminTools.php b/out/out.AdminTools.php index 873222e61..506bcbde1 100644 --- a/out/out.AdminTools.php +++ b/out/out.AdminTools.php @@ -17,14 +17,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.ApprovalSummary.php b/out/out.ApprovalSummary.php index 1e5091fa9..370234205 100644 --- a/out/out.ApprovalSummary.php +++ b/out/out.ApprovalSummary.php @@ -19,14 +19,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); @@ -39,6 +40,7 @@ if($view) { $view->setParam('cachedir', $settings->_cacheDir); $view->setParam('previewWidthList', $settings->_previewWidthList); $view->setParam('timeout', $settings->_cmdTimeout); + $view->setParam('xsendfile', $settings->_enableXsendfile); $view($_GET); exit; } diff --git a/out/out.ApproveDocument.php b/out/out.ApproveDocument.php index 1631740f8..ac284ee42 100644 --- a/out/out.ApproveDocument.php +++ b/out/out.ApproveDocument.php @@ -19,16 +19,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"])<1) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); @@ -58,7 +59,7 @@ if (!is_object($content)) { UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("invalid_version")); } -// operation is admitted only for last deocument version +// operation is admitted only for last document version $latestContent = $document->getLatestContent(); if ($latestContent->getVersion()!=$version) { UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("invalid_version")); diff --git a/out/out.AttributeMgr.php b/out/out.AttributeMgr.php index e02d80b7c..a455e6199 100644 --- a/out/out.AttributeMgr.php +++ b/out/out.AttributeMgr.php @@ -19,14 +19,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); @@ -51,6 +52,7 @@ if($view) { $view->setParam('maxRecursiveCount', $settings->_maxRecursiveCount); $view->setParam('previewWidthList', $settings->_previewWidthList); $view->setParam('timeout', $settings->_cmdTimeout); + $view->setParam('xsendfile', $settings->_enableXsendfile); $view($_GET); } diff --git a/out/out.BackupTools.php b/out/out.BackupTools.php index 3202da372..38ea9a04c 100644 --- a/out/out.BackupTools.php +++ b/out/out.BackupTools.php @@ -17,15 +17,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user, 'contentdir'=>$settings->_contentDir)); diff --git a/out/out.Calendar.php b/out/out.Calendar.php index cad975bff..2622b4958 100644 --- a/out/out.Calendar.php +++ b/out/out.Calendar.php @@ -17,15 +17,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.ClassCalendar.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.ClassCalendar.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); @@ -74,6 +75,7 @@ if($view) { $view->setParam('previewWidthList', $settings->_previewWidthList); $view->setParam('previewWidthDetail', $settings->_previewWidthDetail); $view->setParam('timeout', $settings->_cmdTimeout); + $view->setParam('xsendfile', $settings->_enableXsendfile); $view($_GET); exit; } diff --git a/out/out.Categories.php b/out/out.Categories.php index 5c359fe0e..6009753b4 100644 --- a/out/out.Categories.php +++ b/out/out.Categories.php @@ -19,14 +19,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); @@ -49,5 +50,6 @@ if($view) { $view->setParam('cachedir', $settings->_cacheDir); $view->setParam('previewWidthList', $settings->_previewWidthList); $view->setParam('timeout', $settings->_cmdTimeout); + $view->setParam('xsendfile', $settings->_enableXsendfile); $view($_GET); } diff --git a/out/out.CategoryChooser.php b/out/out.CategoryChooser.php index 44e7feb16..2ab2570b8 100644 --- a/out/out.CategoryChooser.php +++ b/out/out.CategoryChooser.php @@ -18,14 +18,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.Authentication.php"); $form = preg_replace('/[^A-Za-z0-9_]+/', '', $_GET["form"]); $selcats = preg_replace('/[^0-9,]+/', '', $_GET["cats"]); diff --git a/out/out.ChangePassword.php b/out/out.ChangePassword.php index 48d781335..a19768f91 100644 --- a/out/out.ChangePassword.php +++ b/out/out.ChangePassword.php @@ -18,10 +18,11 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.ClassUI.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.ClassUI.php"); include $settings->_rootDir . "languages/" . $settings->_language . "/lang.inc"; diff --git a/out/out.Charts.php b/out/out.Charts.php index 84591584d..7114ad30f 100644 --- a/out/out.Charts.php +++ b/out/out.Charts.php @@ -17,15 +17,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.ClearCache.php b/out/out.ClearCache.php index 96f0b1b7b..cd9a8775d 100644 --- a/out/out.ClearCache.php +++ b/out/out.ClearCache.php @@ -19,15 +19,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.Authentication.php"); -include("../inc/inc.ClassUI.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.Authentication.php"); +require_once("inc/inc.ClassUI.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.Clipboard.php b/out/out.Clipboard.php index 45c2e21fa..bef7d4108 100644 --- a/out/out.Clipboard.php +++ b/out/out.Clipboard.php @@ -19,15 +19,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.Authentication.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.ClassUI.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.Authentication.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.ClassUI.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); @@ -35,6 +36,7 @@ $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); if($view) { $view->setParam('previewWidthList', $settings->_previewWidthList); $view->setParam('timeout', $settings->_cmdTimeout); + $view->setParam('xsendfile', $settings->_enableXsendfile); $view($_GET); exit; } diff --git a/out/out.CreateIndex.php b/out/out.CreateIndex.php index 330f4fabe..3968d8d2b 100644 --- a/out/out.CreateIndex.php +++ b/out/out.CreateIndex.php @@ -20,15 +20,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Version.php"); -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.Version.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.DefaultKeywords.php b/out/out.DefaultKeywords.php index 0864b462c..85294f68a 100644 --- a/out/out.DefaultKeywords.php +++ b/out/out.DefaultKeywords.php @@ -19,14 +19,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.DocumentAccess.php b/out/out.DocumentAccess.php index e5c531cee..779e14e76 100644 --- a/out/out.DocumentAccess.php +++ b/out/out.DocumentAccess.php @@ -19,16 +19,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"])<1) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); diff --git a/out/out.DocumentChooser.php b/out/out.DocumentChooser.php index 0ebe87ae8..b6c7f4d2d 100644 --- a/out/out.DocumentChooser.php +++ b/out/out.DocumentChooser.php @@ -19,14 +19,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $folderid = intval($_GET["folderid"]); $form = preg_replace('/[^A-Za-z0-9_]+/', '', $_GET["form"]); diff --git a/out/out.DocumentNotify.php b/out/out.DocumentNotify.php index 12018f791..0cdd88793 100644 --- a/out/out.DocumentNotify.php +++ b/out/out.DocumentNotify.php @@ -19,16 +19,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"]<1)) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); diff --git a/out/out.DocumentVersionDetail.php b/out/out.DocumentVersionDetail.php index 8a53790fc..2a7bcc5b3 100644 --- a/out/out.DocumentVersionDetail.php +++ b/out/out.DocumentVersionDetail.php @@ -19,16 +19,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"])<1) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); @@ -80,6 +81,7 @@ if($view) { $view->setParam('convertToPdf', $settings->_convertToPdf); $view->setParam('cachedir', $settings->_cacheDir); $view->setParam('timeout', $settings->_cmdTimeout); + $view->setParam('xsendfile', $settings->_enableXsendfile); $view->setParam('accessobject', $accessop); $view($_GET); exit; diff --git a/out/out.DropFolderChooser.php b/out/out.DropFolderChooser.php index 54d6928ea..c40f5f096 100644 --- a/out/out.DropFolderChooser.php +++ b/out/out.DropFolderChooser.php @@ -18,14 +18,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); if(isset($_GET["form"])) $form = preg_replace('/[^A-Za-z0-9_]+/', '', $_GET["form"]); @@ -59,6 +60,7 @@ if($view) { $view->setParam('previewWidthMenuList', $settings->_previewWidthMenuList); $view->setParam('previewWidthList', $settings->_previewWidthDropFolderList); $view->setParam('timeout', $settings->_cmdTimeout); + $view->setParam('xsendfile', $settings->_enableXsendfile); $view->setParam('showfolders', $showfolders); $view->setParam('folder', $folder); $view($_GET); diff --git a/out/out.EditAttributes.php b/out/out.EditAttributes.php index e103c98d6..27af0bcd2 100644 --- a/out/out.EditAttributes.php +++ b/out/out.EditAttributes.php @@ -19,16 +19,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"])<1) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); diff --git a/out/out.EditComment.php b/out/out.EditComment.php index ff7884d2b..fbb700748 100644 --- a/out/out.EditComment.php +++ b/out/out.EditComment.php @@ -19,16 +19,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.EditDocument.php b/out/out.EditDocument.php index b0958904d..a4cfd8e72 100644 --- a/out/out.EditDocument.php +++ b/out/out.EditDocument.php @@ -18,16 +18,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"])<1) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); diff --git a/out/out.EditDocumentFile.php b/out/out.EditDocumentFile.php index 20499f566..8c7078f1a 100644 --- a/out/out.EditDocumentFile.php +++ b/out/out.EditDocumentFile.php @@ -17,16 +17,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"])<1) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); diff --git a/out/out.EditEvent.php b/out/out.EditEvent.php index b60b00075..6f72bcaba 100644 --- a/out/out.EditEvent.php +++ b/out/out.EditEvent.php @@ -17,15 +17,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Calendar.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Calendar.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.EditFolder.php b/out/out.EditFolder.php index b7d872dd1..5f0480a94 100644 --- a/out/out.EditFolder.php +++ b/out/out.EditFolder.php @@ -18,15 +18,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.EditOnline.php b/out/out.EditOnline.php index bfc5c6027..00af1f66a 100644 --- a/out/out.EditOnline.php +++ b/out/out.EditOnline.php @@ -18,15 +18,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.EditUserData.php b/out/out.EditUserData.php index 348723ef3..5e110fbaa 100644 --- a/out/out.EditUserData.php +++ b/out/out.EditUserData.php @@ -19,14 +19,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.ErrorDlg.php b/out/out.ErrorDlg.php index 8b97683f6..bbea7a3ec 100644 --- a/out/out.ErrorDlg.php +++ b/out/out.ErrorDlg.php @@ -22,16 +22,17 @@ // This file is needed because SeedDMS_View_Bootstrap::htmlEndPage() includes // a file out/out.ErrorDlg.php?action=webrootjs and out/out.ErrorDlg.php?action=footerjs -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.ExpiredDocuments.php b/out/out.ExpiredDocuments.php index b81b83a61..f6becc6a3 100644 --- a/out/out.ExpiredDocuments.php +++ b/out/out.ExpiredDocuments.php @@ -19,14 +19,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); @@ -44,6 +45,7 @@ if($view) { $view->setParam('cachedir', $settings->_cacheDir); $view->setParam('previewWidthList', $settings->_previewWidthList); $view->setParam('timeout', $settings->_cmdTimeout); + $view->setParam('xsendfile', $settings->_enableXsendfile); $view($_GET); exit; } diff --git a/out/out.ExtensionMgr.php b/out/out.ExtensionMgr.php index d75345e77..2e7e0e896 100644 --- a/out/out.ExtensionMgr.php +++ b/out/out.ExtensionMgr.php @@ -16,15 +16,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Version.php"); -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.Version.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.FolderAccess.php b/out/out.FolderAccess.php index 970769c1a..08cf72877 100644 --- a/out/out.FolderAccess.php +++ b/out/out.FolderAccess.php @@ -19,15 +19,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.FolderChooser.php b/out/out.FolderChooser.php index 57023e9cc..0b47e55c1 100644 --- a/out/out.FolderChooser.php +++ b/out/out.FolderChooser.php @@ -18,14 +18,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $form = preg_replace('/[^A-Za-z0-9_]+/', '', $_GET["form"]); $mode = intval($_GET["mode"]); diff --git a/out/out.FolderNotify.php b/out/out.FolderNotify.php index ef667d9b9..e457802f9 100644 --- a/out/out.FolderNotify.php +++ b/out/out.FolderNotify.php @@ -18,15 +18,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.ForcePasswordChange.php b/out/out.ForcePasswordChange.php index 67303faa9..0c78e3d4b 100644 --- a/out/out.ForcePasswordChange.php +++ b/out/out.ForcePasswordChange.php @@ -30,14 +30,15 @@ * @version Release: @package_version@ */ -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.GroupMgr.php b/out/out.GroupMgr.php index 7f61bdaf5..1ee9cbfc7 100644 --- a/out/out.GroupMgr.php +++ b/out/out.GroupMgr.php @@ -19,14 +19,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); @@ -59,5 +60,6 @@ if($view) { $view->setParam('previewWidthList', $settings->_previewWidthList); $view->setParam('workflowmode', $settings->_workflowMode); $view->setParam('timeout', $settings->_cmdTimeout); + $view->setParam('xsendfile', $settings->_enableXsendfile); $view($_GET); } diff --git a/out/out.GroupView.php b/out/out.GroupView.php index 8024323cb..f2fa399c4 100644 --- a/out/out.GroupView.php +++ b/out/out.GroupView.php @@ -17,14 +17,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.Help.php b/out/out.Help.php index 705feb80e..dc8f2db78 100644 --- a/out/out.Help.php +++ b/out/out.Help.php @@ -17,14 +17,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1]); diff --git a/out/out.Hooks.php b/out/out.Hooks.php index 9eda3c44b..db3845254 100644 --- a/out/out.Hooks.php +++ b/out/out.Hooks.php @@ -16,14 +16,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.ImportFS.php b/out/out.ImportFS.php index af394806a..28ee7c482 100644 --- a/out/out.ImportFS.php +++ b/out/out.ImportFS.php @@ -17,15 +17,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.IndexInfo.php b/out/out.IndexInfo.php index 6e614a927..f6fa9f60e 100644 --- a/out/out.IndexInfo.php +++ b/out/out.IndexInfo.php @@ -19,15 +19,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Version.php"); -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.Version.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.Indexer.php b/out/out.Indexer.php index f7593b984..623fe8c2c 100644 --- a/out/out.Indexer.php +++ b/out/out.Indexer.php @@ -19,15 +19,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Version.php"); -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.Version.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); @@ -54,7 +55,10 @@ if(!isset($_GET['action']) || $_GET['action'] == 'show') { } else { $index = $indexconf['Indexer']::open($settings->_luceneDir); if(!$index) { - UI::exitError(getMLText("admin_tools"),getMLText("no_fulltextindex")); + $index = $indexconf['Indexer']::create($settings->_luceneDir); + if(!$index) { + UI::exitError(getMLText("admin_tools"),getMLText("no_fulltextindex")); + } } $indexconf['Indexer']::init($settings->_stopWordsFile); } diff --git a/out/out.Info.php b/out/out.Info.php index 09a382473..21f5b1483 100644 --- a/out/out.Info.php +++ b/out/out.Info.php @@ -19,15 +19,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Version.php"); -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.Version.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.KeywordChooser.php b/out/out.KeywordChooser.php index 2903a375f..1c1ec862a 100644 --- a/out/out.KeywordChooser.php +++ b/out/out.KeywordChooser.php @@ -19,14 +19,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $allusers = $dms->getAllUsers(); $userids = array($user->getID()); diff --git a/out/out.LogManagement.php b/out/out.LogManagement.php index 0984e4fcd..b02839b41 100644 --- a/out/out.LogManagement.php +++ b/out/out.LogManagement.php @@ -17,15 +17,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.Login.php b/out/out.Login.php index 4aa044fec..950750a7f 100644 --- a/out/out.Login.php +++ b/out/out.Login.php @@ -19,13 +19,14 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.ClassUI.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.ClassUI.php"); include $settings->_rootDir . "languages/" . $settings->_language . "/lang.inc"; diff --git a/out/out.ManageNotify.php b/out/out.ManageNotify.php index 6d2419fdb..bd204b655 100644 --- a/out/out.ManageNotify.php +++ b/out/out.ManageNotify.php @@ -17,14 +17,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); @@ -37,6 +38,7 @@ if($view) { $view->setParam('cachedir', $settings->_cacheDir); $view->setParam('previewWidthList', $settings->_previewWidthList); $view->setParam('timeout', $settings->_cmdTimeout); + $view->setParam('xsendfile', $settings->_enableXsendfile); $view($_GET); exit; } diff --git a/out/out.MoveDocument.php b/out/out.MoveDocument.php index 4f9fcdb5c..674036c89 100644 --- a/out/out.MoveDocument.php +++ b/out/out.MoveDocument.php @@ -18,16 +18,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"])<1) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); diff --git a/out/out.MoveFolder.php b/out/out.MoveFolder.php index 3cace3498..e5b101f49 100644 --- a/out/out.MoveFolder.php +++ b/out/out.MoveFolder.php @@ -18,15 +18,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.MyAccount.php b/out/out.MyAccount.php index 27fbbd853..ee6bd0ab9 100644 --- a/out/out.MyAccount.php +++ b/out/out.MyAccount.php @@ -19,14 +19,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.MyDocuments.php b/out/out.MyDocuments.php index 4af578678..d4f73fd67 100644 --- a/out/out.MyDocuments.php +++ b/out/out.MyDocuments.php @@ -19,14 +19,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); @@ -54,6 +55,7 @@ if($view) { $view->setParam('cachedir', $settings->_cacheDir); $view->setParam('previewWidthList', $settings->_previewWidthList); $view->setParam('timeout', $settings->_cmdTimeout); + $view->setParam('xsendfile', $settings->_enableXsendfile); $view($_GET); exit; } diff --git a/out/out.ObjectCheck.php b/out/out.ObjectCheck.php index 43fbd4135..37cad7348 100644 --- a/out/out.ObjectCheck.php +++ b/out/out.ObjectCheck.php @@ -19,15 +19,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Version.php"); -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.Version.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.OpensearchDesc.php b/out/out.OpensearchDesc.php index 8c4cc8d42..5d34d75b9 100644 --- a/out/out.OpensearchDesc.php +++ b/out/out.OpensearchDesc.php @@ -18,16 +18,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.OverrideContentStatus.php b/out/out.OverrideContentStatus.php index bb2c497d4..c7ef9d0d5 100644 --- a/out/out.OverrideContentStatus.php +++ b/out/out.OverrideContentStatus.php @@ -18,16 +18,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"])<1) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); diff --git a/out/out.PasswordForgotten.php b/out/out.PasswordForgotten.php index 81af10241..fddc18050 100644 --- a/out/out.PasswordForgotten.php +++ b/out/out.PasswordForgotten.php @@ -18,12 +18,13 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.ClassUI.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.ClassUI.php"); include $settings->_rootDir . "languages/" . $settings->_language . "/lang.inc"; diff --git a/out/out.PasswordSend.php b/out/out.PasswordSend.php index 81af10241..fddc18050 100644 --- a/out/out.PasswordSend.php +++ b/out/out.PasswordSend.php @@ -18,12 +18,13 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.ClassUI.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.ClassUI.php"); include $settings->_rootDir . "languages/" . $settings->_language . "/lang.inc"; diff --git a/out/out.RemoveArchive.php b/out/out.RemoveArchive.php index c8da8401b..fb5509962 100644 --- a/out/out.RemoveArchive.php +++ b/out/out.RemoveArchive.php @@ -16,15 +16,16 @@ // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +/ +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.RemoveDocument.php b/out/out.RemoveDocument.php index f82cea728..cd8363a28 100644 --- a/out/out.RemoveDocument.php +++ b/out/out.RemoveDocument.php @@ -18,16 +18,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"])<1) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); diff --git a/out/out.RemoveDocumentFile.php b/out/out.RemoveDocumentFile.php index 20499f566..8c7078f1a 100644 --- a/out/out.RemoveDocumentFile.php +++ b/out/out.RemoveDocumentFile.php @@ -17,16 +17,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"])<1) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); diff --git a/out/out.RemoveDump.php b/out/out.RemoveDump.php index f07777424..b42719c7c 100644 --- a/out/out.RemoveDump.php +++ b/out/out.RemoveDump.php @@ -17,14 +17,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.RemoveEvent.php b/out/out.RemoveEvent.php index 5b5c28ec6..9f695b96d 100644 --- a/out/out.RemoveEvent.php +++ b/out/out.RemoveEvent.php @@ -17,15 +17,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Calendar.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Calendar.php"); +require_once("inc/inc.Authentication.php"); if (!isset($_GET["id"]) || !is_numeric($_GET["id"]) || intval($_GET["id"])<1) { UI::exitError(getMLText("edit_event"),getMLText("error_occured")); diff --git a/out/out.RemoveFolder.php b/out/out.RemoveFolder.php index 35b40cc52..800e72195 100644 --- a/out/out.RemoveFolder.php +++ b/out/out.RemoveFolder.php @@ -18,15 +18,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.RemoveFolderFiles.php b/out/out.RemoveFolderFiles.php index 2151648d0..699dd449e 100644 --- a/out/out.RemoveFolderFiles.php +++ b/out/out.RemoveFolderFiles.php @@ -17,14 +17,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.RemoveGroup.php b/out/out.RemoveGroup.php index e1ffe181e..3116e9edf 100644 --- a/out/out.RemoveGroup.php +++ b/out/out.RemoveGroup.php @@ -18,14 +18,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.RemoveLog.php b/out/out.RemoveLog.php index 5910d9e9e..618009819 100644 --- a/out/out.RemoveLog.php +++ b/out/out.RemoveLog.php @@ -17,14 +17,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.RemoveUser.php b/out/out.RemoveUser.php index 541957199..ff062ae8d 100644 --- a/out/out.RemoveUser.php +++ b/out/out.RemoveUser.php @@ -18,14 +18,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.RemoveUserFromProcesses.php b/out/out.RemoveUserFromProcesses.php index 3948a5d78..c7e2afcb7 100644 --- a/out/out.RemoveUserFromProcesses.php +++ b/out/out.RemoveUserFromProcesses.php @@ -18,13 +18,14 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); if (!$user->isAdmin()) { UI::exitError(getMLText("admin_tools"),getMLText("access_denied")); diff --git a/out/out.RemoveVersion.php b/out/out.RemoveVersion.php index 547d7177f..9c982338e 100644 --- a/out/out.RemoveVersion.php +++ b/out/out.RemoveVersion.php @@ -19,16 +19,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"])<1) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); diff --git a/out/out.RemoveWorkflow.php b/out/out.RemoveWorkflow.php index a87592ed1..b94e6c444 100644 --- a/out/out.RemoveWorkflow.php +++ b/out/out.RemoveWorkflow.php @@ -19,15 +19,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.RemoveWorkflowFromDocument.php b/out/out.RemoveWorkflowFromDocument.php index 54b6ae2b5..9d7351aeb 100644 --- a/out/out.RemoveWorkflowFromDocument.php +++ b/out/out.RemoveWorkflowFromDocument.php @@ -19,16 +19,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); @@ -37,20 +38,20 @@ if (!$user->isAdmin()) { UI::exitError(getMLText("admin_tools"),getMLText("access_denied")); } -if (!isset($_POST["documentid"]) || !is_numeric($_POST["documentid"]) || intval($_POST["documentid"])<1) { +if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"])<1) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); } -$document = $dms->getDocument(intval($_POST["documentid"])); +$document = $dms->getDocument(intval($_GET["documentid"])); if (!is_object($document)) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); } -if (!isset($_POST["version"]) || !is_numeric($_POST["version"]) || intval($_POST["version"])<1) { +if (!isset($_GET["version"]) || !is_numeric($_GET["version"]) || intval($_GET["version"])<1) { UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("invalid_version")); } -$version = $_POST["version"]; +$version = $_GET["version"]; $version = $document->getContentByVersion($version); if (!is_object($version)) { diff --git a/out/out.ReturnFromSubWorkflow.php b/out/out.ReturnFromSubWorkflow.php index 61dde19ec..5ddf54709 100644 --- a/out/out.ReturnFromSubWorkflow.php +++ b/out/out.ReturnFromSubWorkflow.php @@ -19,29 +19,30 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); -if (!isset($_POST["documentid"]) || !is_numeric($_POST["documentid"]) || intval($_POST["documentid"])<1) { +if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"])<1) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); } -$document = $dms->getDocument(intval($_POST["documentid"])); +$document = $dms->getDocument(intval($_GET["documentid"])); if (!is_object($document)) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); } -if (!isset($_POST["version"]) || !is_numeric($_POST["version"]) || intval($_POST["version"])<1) { +if (!isset($_GET["version"]) || !is_numeric($_GET["version"]) || intval($_GET["version"])<1) { UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("invalid_version")); } -$version = $_POST["version"]; +$version = $_GET["version"]; $version = $document->getContentByVersion($version); if (!is_object($version)) { @@ -53,8 +54,8 @@ if (!is_object($workflow)) { UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("document_has_no_workflow")); } -if(isset($_POST["transition"]) && $_POST["transition"]) { - $transition = $dms->getWorkflowTransition($_POST["transition"]); +if(isset($_GET["transition"]) && $_GET["transition"]) { + $transition = $dms->getWorkflowTransition($_GET["transition"]); if (!is_object($transition)) { UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("invalid_workflow_transition")); } diff --git a/out/out.ReviewDocument.php b/out/out.ReviewDocument.php index 122242008..21445dfea 100644 --- a/out/out.ReviewDocument.php +++ b/out/out.ReviewDocument.php @@ -19,16 +19,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"])<1) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); @@ -55,7 +56,7 @@ if (!is_object($content)) { UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("invalid_version")); } -// operation is admitted only for last deocument version +// operation is admitted only for last document version $latestContent = $document->getLatestContent(); if ($latestContent->getVersion()!=$version) { UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("invalid_version")); diff --git a/out/out.ReviewSummary.php b/out/out.ReviewSummary.php index 1e5091fa9..370234205 100644 --- a/out/out.ReviewSummary.php +++ b/out/out.ReviewSummary.php @@ -19,14 +19,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); @@ -39,6 +40,7 @@ if($view) { $view->setParam('cachedir', $settings->_cacheDir); $view->setParam('previewWidthList', $settings->_previewWidthList); $view->setParam('timeout', $settings->_cmdTimeout); + $view->setParam('xsendfile', $settings->_enableXsendfile); $view($_GET); exit; } diff --git a/out/out.RewindWorkflow.php b/out/out.RewindWorkflow.php index 54b6ae2b5..9d7351aeb 100644 --- a/out/out.RewindWorkflow.php +++ b/out/out.RewindWorkflow.php @@ -19,16 +19,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); @@ -37,20 +38,20 @@ if (!$user->isAdmin()) { UI::exitError(getMLText("admin_tools"),getMLText("access_denied")); } -if (!isset($_POST["documentid"]) || !is_numeric($_POST["documentid"]) || intval($_POST["documentid"])<1) { +if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"])<1) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); } -$document = $dms->getDocument(intval($_POST["documentid"])); +$document = $dms->getDocument(intval($_GET["documentid"])); if (!is_object($document)) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); } -if (!isset($_POST["version"]) || !is_numeric($_POST["version"]) || intval($_POST["version"])<1) { +if (!isset($_GET["version"]) || !is_numeric($_GET["version"]) || intval($_GET["version"])<1) { UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("invalid_version")); } -$version = $_POST["version"]; +$version = $_GET["version"]; $version = $document->getContentByVersion($version); if (!is_object($version)) { diff --git a/out/out.RunSubWorkflow.php b/out/out.RunSubWorkflow.php index 98cfd3fa5..528cd21a4 100644 --- a/out/out.RunSubWorkflow.php +++ b/out/out.RunSubWorkflow.php @@ -19,35 +19,36 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); $accessop = new SeedDMS_AccessOperation($dms, $document, $user, $settings); -if (!isset($_POST["documentid"]) || !is_numeric($_POST["documentid"]) || intval($_POST["documentid"])<1) { +if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"])<1) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); } -$document = $dms->getDocument(intval($_POST["documentid"])); +$document = $dms->getDocument(intval($_GET["documentid"])); if (!is_object($document)) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); } -if (!isset($_POST["version"]) || !is_numeric($_POST["version"]) || intval($_POST["version"])<1) { +if (!isset($_GET["version"]) || !is_numeric($_GET["version"]) || intval($_GET["version"])<1) { UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("invalid_version")); } -$version = $_POST["version"]; +$version = $_GET["version"]; $version = $document->getContentByVersion($version); if (!is_object($version)) { @@ -59,11 +60,11 @@ if (!is_object($workflow)) { UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("document_has_no_workflow")); } -if (!isset($_POST["subworkflow"]) || !is_numeric($_POST["subworkflow"]) || intval($_POST["subworkflow"])<1) { +if (!isset($_GET["subworkflow"]) || !is_numeric($_GET["subworkflow"]) || intval($_GET["subworkflow"])<1) { UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("invalid_workflow")); } -$subworkflow = $dms->getWorkflow($_POST["subworkflow"]); +$subworkflow = $dms->getWorkflow($_GET["subworkflow"]); if (!is_object($subworkflow)) { UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("invalid_workflow")); } diff --git a/out/out.Search.php b/out/out.Search.php index e2643ed86..e5a7a52ff 100644 --- a/out/out.Search.php +++ b/out/out.Search.php @@ -18,16 +18,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); function getTime() { if (function_exists('microtime')) { @@ -436,6 +437,7 @@ if($settings->_showSingleSearchHit && count($entries) == 1) { $view->setParam('enablefullsearch', $settings->_enableFullSearch); $view->setParam('previewWidthList', $settings->_previewWidthList); $view->setParam('timeout', $settings->_cmdTimeout); + $view->setParam('xsendfile', $settings->_enableXsendfile); $view($_GET); exit; } diff --git a/out/out.SearchForm.php b/out/out.SearchForm.php index 36de4b92b..b70c6c617 100644 --- a/out/out.SearchForm.php +++ b/out/out.SearchForm.php @@ -19,15 +19,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); if (!isset($_GET["folderid"]) || !is_numeric($_GET["folderid"]) || intval($_GET["folderid"])<1) { $folderid=$settings->_rootFolderID; diff --git a/out/out.SendLoginData.php b/out/out.SendLoginData.php index 1ac00e443..bd8216498 100644 --- a/out/out.SendLoginData.php +++ b/out/out.SendLoginData.php @@ -18,13 +18,14 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); if (!$user->isAdmin()) { UI::exitError(getMLText("admin_tools"),getMLText("access_denied")); diff --git a/out/out.Session.php b/out/out.Session.php index cc6ac7e71..37b123ff5 100644 --- a/out/out.Session.php +++ b/out/out.Session.php @@ -19,15 +19,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); -include("../inc/inc.ClassAccessOperation.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); +require_once("inc/inc.ClassAccessOperation.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.SetExpires.php b/out/out.SetExpires.php index edec2d482..3edafd9e7 100644 --- a/out/out.SetExpires.php +++ b/out/out.SetExpires.php @@ -19,16 +19,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"])<1) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); diff --git a/out/out.SetReviewersApprovers.php b/out/out.SetReviewersApprovers.php index ceca25a3c..379c47086 100644 --- a/out/out.SetReviewersApprovers.php +++ b/out/out.SetReviewersApprovers.php @@ -19,16 +19,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.SetWorkflow.php b/out/out.SetWorkflow.php index 04b9d9d98..5ac1aacd8 100644 --- a/out/out.SetWorkflow.php +++ b/out/out.SetWorkflow.php @@ -19,16 +19,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"])<1) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); diff --git a/out/out.Settings.php b/out/out.Settings.php index c379177c7..0c3718d3a 100644 --- a/out/out.Settings.php +++ b/out/out.Settings.php @@ -17,14 +17,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.Setup2Factor.php b/out/out.Setup2Factor.php index 2bbcc3007..f7f0672d9 100644 --- a/out/out.Setup2Factor.php +++ b/out/out.Setup2Factor.php @@ -11,13 +11,14 @@ * @version Release: @package_version@ */ -include("../inc/inc.Settings.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.Statistic.php b/out/out.Statistic.php index e5b025637..ec6f0ecdd 100644 --- a/out/out.Statistic.php +++ b/out/out.Statistic.php @@ -17,15 +17,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.SubstituteUser.php b/out/out.SubstituteUser.php index 295ee3bb5..c4bce86bb 100644 --- a/out/out.SubstituteUser.php +++ b/out/out.SubstituteUser.php @@ -16,16 +16,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1]); diff --git a/out/out.Tasks.php b/out/out.Tasks.php index 3c0df220e..90bf3b384 100644 --- a/out/out.Tasks.php +++ b/out/out.Tasks.php @@ -19,14 +19,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.Authentication.php"); -include("../inc/inc.ClassUI.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.Authentication.php"); +require_once("inc/inc.ClassUI.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); @@ -35,6 +36,7 @@ if($view) { $view->setParam('workflowmode', $settings->_workflowMode); $view->setParam('previewWidthList', $settings->_previewWidthList); $view->setParam('timeout', $settings->_cmdTimeout); + $view->setParam('xsendfile', $settings->_enableXsendfile); $view($_GET); exit; } diff --git a/out/out.Timeline.php b/out/out.Timeline.php index 17b5412ab..e124ab13b 100644 --- a/out/out.Timeline.php +++ b/out/out.Timeline.php @@ -17,15 +17,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); @@ -62,6 +63,7 @@ if($view) { $view->setParam('previewWidthList', $settings->_previewWidthList); $view->setParam('previewWidthDetail', $settings->_previewWidthDetail); $view->setParam('timeout', $settings->_cmdTimeout); + $view->setParam('xsendfile', $settings->_enableXsendfile); $view($_GET); exit; } diff --git a/out/out.TransferDocument.php b/out/out.TransferDocument.php index 7d423e1f1..dbafb6411 100644 --- a/out/out.TransferDocument.php +++ b/out/out.TransferDocument.php @@ -18,16 +18,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.TransferObjects.php b/out/out.TransferObjects.php index 5831d6807..b2a0095c8 100644 --- a/out/out.TransferObjects.php +++ b/out/out.TransferObjects.php @@ -18,13 +18,14 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); if (!$user->isAdmin()) { UI::exitError(getMLText("admin_tools"),getMLText("access_denied")); diff --git a/out/out.TriggerWorkflow.php b/out/out.TriggerWorkflow.php index 6de4ae73e..bcbc988fc 100644 --- a/out/out.TriggerWorkflow.php +++ b/out/out.TriggerWorkflow.php @@ -19,31 +19,35 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); -if (!isset($_POST["documentid"]) || !is_numeric($_POST["documentid"]) || intval($_POST["documentid"])<1) { +$tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); +$view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); + +if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"])<1) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); } -$document = $dms->getDocument(intval($_POST["documentid"])); +$document = $dms->getDocument(intval($_GET["documentid"])); if (!is_object($document)) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); } -if (!isset($_POST["version"]) || !is_numeric($_POST["version"]) || intval($_POST["version"])<1) { +if (!isset($_GET["version"]) || !is_numeric($_GET["version"]) || intval($_GET["version"])<1) { UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("invalid_version")); } -$version = $_POST["version"]; +$version = $_GET["version"]; $version = $document->getContentByVersion($version); if (!is_object($version)) { @@ -55,7 +59,7 @@ if (!is_object($workflow)) { UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("document_has_no_workflow")); } -$transition = $dms->getWorkflowTransition($_POST["transition"]); +$transition = $dms->getWorkflowTransition($_GET["transition"]); if (!is_object($transition)) { UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("invalid_workflow_transition")); } @@ -65,8 +69,6 @@ $folder = $document->getFolder(); /* Create object for checking access to certain operations */ $accessop = new SeedDMS_AccessOperation($dms, $document, $user, $settings); -$tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); -$view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); if($view) { $view->setParam('folder', $folder); $view->setParam('document', $document); diff --git a/out/out.UpdateDocument.php b/out/out.UpdateDocument.php index 92433bff9..796c8852f 100644 --- a/out/out.UpdateDocument.php +++ b/out/out.UpdateDocument.php @@ -19,16 +19,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.UpdateDocument2.php b/out/out.UpdateDocument2.php index 88803a176..c3f760fa8 100644 --- a/out/out.UpdateDocument2.php +++ b/out/out.UpdateDocument2.php @@ -19,15 +19,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); if (!isset($_GET["documentid"]) || !is_numeric($_GET["documentid"]) || intval($_GET["documentid"])<1) { UI::exitError(getMLText("document_title", array("documentname" => getMLText("invalid_doc_id"))),getMLText("invalid_doc_id")); diff --git a/out/out.UserDefaultKeywords.php b/out/out.UserDefaultKeywords.php index d78691960..ce75d1273 100644 --- a/out/out.UserDefaultKeywords.php +++ b/out/out.UserDefaultKeywords.php @@ -18,14 +18,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.UserImage.php b/out/out.UserImage.php index 85c951760..a71891312 100644 --- a/out/out.UserImage.php +++ b/out/out.UserImage.php @@ -18,12 +18,13 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.Authentication.php"); /* Get the user as passed to the script. This allows to show * pictures of other users as well diff --git a/out/out.UserList.php b/out/out.UserList.php index 6b17312df..752ce0fd4 100644 --- a/out/out.UserList.php +++ b/out/out.UserList.php @@ -17,15 +17,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); -include("../inc/inc.ClassPasswordStrength.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); +require_once("inc/inc.ClassPasswordStrength.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.UsrMgr.php b/out/out.UsrMgr.php index 99e70f3f1..a0595a00d 100644 --- a/out/out.UsrMgr.php +++ b/out/out.UsrMgr.php @@ -19,14 +19,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.UsrView.php b/out/out.UsrView.php index db19bb304..01fb0d9b8 100644 --- a/out/out.UsrView.php +++ b/out/out.UsrView.php @@ -17,14 +17,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.ViewDocument.php b/out/out.ViewDocument.php index 1fd66e748..fd0a7d234 100644 --- a/out/out.ViewDocument.php +++ b/out/out.ViewDocument.php @@ -19,16 +19,17 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.ClassAccessOperation.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.ClassAccessOperation.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); @@ -79,6 +80,7 @@ if($view) { $view->setParam('convertToPdf', $settings->_convertToPdf); $view->setParam('currenttab', isset($_GET['currenttab']) ? $_GET['currenttab'] : ""); $view->setParam('timeout', $settings->_cmdTimeout); + $view->setParam('xsendfile', $settings->_enableXsendfile); $view($_GET); exit; } diff --git a/out/out.ViewEvent.php b/out/out.ViewEvent.php index a19d60484..4abac08c9 100644 --- a/out/out.ViewEvent.php +++ b/out/out.ViewEvent.php @@ -17,15 +17,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Calendar.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Calendar.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.ViewFolder.php b/out/out.ViewFolder.php index c48e243e5..eec5fdcba 100644 --- a/out/out.ViewFolder.php +++ b/out/out.ViewFolder.php @@ -19,15 +19,16 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Utils.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.Authentication.php"); -include("../inc/inc.ClassUI.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Utils.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.Authentication.php"); +require_once("inc/inc.ClassUI.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); @@ -75,6 +76,7 @@ if($view) { $view->setParam('previewWidthList', $settings->_previewWidthList); $view->setParam('previewConverters', isset($settings->_converters['preview']) ? $settings->_converters['preview'] : array()); $view->setParam('timeout', $settings->_cmdTimeout); + $view->setParam('xsendfile', $settings->_enableXsendfile); $view->setParam('maxItemsPerPage', $settings->_maxItemsPerPage); $view->setParam('incItemsPerPage', $settings->_incItemsPerPage != 0 ? $settings->_incItemsPerPage : $settings->_maxItemsPerPage); $view->setParam('offset', $offset); diff --git a/out/out.WorkflowActionsMgr.php b/out/out.WorkflowActionsMgr.php index 84593a195..85d133967 100644 --- a/out/out.WorkflowActionsMgr.php +++ b/out/out.WorkflowActionsMgr.php @@ -19,14 +19,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.WorkflowGraph.php b/out/out.WorkflowGraph.php index 0ea650493..290494e3c 100644 --- a/out/out.WorkflowGraph.php +++ b/out/out.WorkflowGraph.php @@ -19,14 +19,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.WorkflowMgr.php b/out/out.WorkflowMgr.php index b56414147..061ad0a87 100644 --- a/out/out.WorkflowMgr.php +++ b/out/out.WorkflowMgr.php @@ -19,14 +19,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.WorkflowStatesMgr.php b/out/out.WorkflowStatesMgr.php index fe226f977..1a1bd40dc 100644 --- a/out/out.WorkflowStatesMgr.php +++ b/out/out.WorkflowStatesMgr.php @@ -19,14 +19,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.WorkflowSummary.php b/out/out.WorkflowSummary.php index e76e17833..07fb7accc 100644 --- a/out/out.WorkflowSummary.php +++ b/out/out.WorkflowSummary.php @@ -19,14 +19,15 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -include("../inc/inc.Settings.php"); -include("../inc/inc.LogInit.php"); -include("../inc/inc.Language.php"); -include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); -include("../inc/inc.DBInit.php"); -include("../inc/inc.ClassUI.php"); -include("../inc/inc.Authentication.php"); +if(!isset($settings)) + require_once("../inc/inc.Settings.php"); +require_once("inc/inc.LogInit.php"); +require_once("inc/inc.Language.php"); +require_once("inc/inc.Init.php"); +require_once("inc/inc.Extension.php"); +require_once("inc/inc.DBInit.php"); +require_once("inc/inc.ClassUI.php"); +require_once("inc/inc.Authentication.php"); $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); @@ -40,6 +41,7 @@ if($view) { $view->setParam('workflowmode', $settings->_workflowMode); $view->setParam('previewWidthList', $settings->_previewWidthList); $view->setParam('timeout', $settings->_cmdTimeout); + $view->setParam('xsendfile', $settings->_enableXsendfile); $view($_GET); exit; } diff --git a/restapi/index.php b/restapi/index.php index 21ea8b1b4..d4e2afa91 100644 --- a/restapi/index.php +++ b/restapi/index.php @@ -2,6 +2,9 @@ define('USE_PHP_SESSION', 0); include("../inc/inc.Settings.php"); +include("../inc/inc.LogInit.php"); +include("../inc/inc.Utils.php"); +include("../inc/inc.Language.php"); include("../inc/inc.Init.php"); include("../inc/inc.DBInit.php"); include("../inc/inc.Extension.php"); @@ -62,6 +65,8 @@ function __getLatestVersionData($lc) { /* {{{ */ 'keywords'=>$document->getKeywords(), 'mimetype'=>$lc->getMimeType(), 'version'=>$lc->getVersion(), + 'version_comment'=>$lc->getComment(), + 'version_date'=>$lc->getDate(), 'size'=>$lc->getFileSize(), ); $cats = $document->getCategories(); @@ -146,11 +151,12 @@ function __getUserData($u) { /* {{{ */ return $data; } /* }}} */ -function doLogin() { /* {{{ */ - global $app, $dms, $userobj, $session, $settings; +function doLogin($request, $response) { /* {{{ */ + global $dms, $userobj, $session, $settings; - $username = $app->request()->post('user'); - $password = $app->request()->post('pass'); + $params = $request->getParsedBody(); + $username = $params['user']; + $password = $params['pass']; // $userobj = $dms->getUserByLogin($username); $userobj = null; @@ -175,9 +181,7 @@ function doLogin() { /* {{{ */ } else { setcookie("mydms_session", $session->getId(), time()-3600, $settings->_httpRoot); } - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Login failed', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'Login failed', 'data'=>''), 403); } else { if(USE_PHP_SESSION) { $_SESSION['userid'] = $userobj->getId(); @@ -194,13 +198,12 @@ function doLogin() { /* {{{ */ setcookie("mydms_session", $id, $lifetime, $settings->_httpRoot); $dms->setUser($userobj); } - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>__getUserData($userobj))); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>__getUserData($userobj)), 200); } } /* }}} */ -function doLogout() { /* {{{ */ - global $app, $dms, $userobj, $session, $settings; +function doLogout($request, $response) { /* {{{ */ + global $dms, $userobj, $session, $settings; if(USE_PHP_SESSION) { unset($_SESSION['userid']); @@ -208,42 +211,37 @@ function doLogout() { /* {{{ */ setcookie("mydms_session", $session->getId(), time()-3600, $settings->_httpRoot); } $userobj = null; - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>'')); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); } /* }}} */ -function setFullName() { /* {{{ */ - global $app, $dms, $userobj; +function setFullName($request, $response) { /* {{{ */ + global $dms, $userobj; if(!$userobj) { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Not logged in', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); return; } - $userobj->setFullName($app->request()->put('fullname')); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$userobj->getFullName())); + $params = $request->getParsedBody(); + $userobj->setFullName($params['fullname']); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$userobj->getFullName()), 200); } /* }}} */ -function setEmail($id) { /* {{{ */ - global $app, $dms, $userobj; +function setEmail($request, $response) { /* {{{ */ + global $dms, $userobj; if(!$userobj) { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Not logged in', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); return; } - $userobj->setEmail($app->request()->put('email')); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$userid)); + $params = $request->getParsedBody(); + $userobj->setEmail($params['email']); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$userid), 200); } /* }}} */ -function getLockedDocuments() { /* {{{ */ - global $app, $dms, $userobj; +function getLockedDocuments($request, $response) { /* {{{ */ + global $dms, $userobj; if(false !== ($documents = $dms->getDocumentsLockedByUser($userobj))) { $documents = SeedDMS_Core_DMS::filterAccess($documents, $userobj, M_READ); @@ -254,87 +252,74 @@ function getLockedDocuments() { /* {{{ */ $recs[] = __getLatestVersionData($lc); } } - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$recs)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$recs), 200); } else { - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>''), 500); } } /* }}} */ -function getFolder($id = null) { /* {{{ */ - global $app, $dms, $userobj, $settings; - $forcebyname = $app->request()->get('forcebyname'); +function getFolder($request, $response, $args) { /* {{{ */ + global $dms, $userobj, $settings; + $params = $request->getQueryParams(); + $forcebyname = isset($params['forcebyname']) ? $params['forcebyname'] : 0; + $parent = isset($params['parentid']) ? $dms->getFolder($params['parentid']) : null; - if ($id === null) + if (!isset($args['id'])) $folder = $dms->getFolder($settings->_rootFolderID); - else if(ctype_digit($id) && empty($forcebyname)) - $folder = $dms->getFolder($id); + elseif(ctype_digit($args['id']) && empty($forcebyname)) + $folder = $dms->getFolder($args['id']); else { - $parentid = $app->request()->get('parentid'); - $folder = $dms->getFolderByName($id, $parentid); + $folder = $dms->getFolderByName($args['id'], $parent); } if($folder) { if($folder->getAccessMode($userobj) >= M_READ) { $data = __getFolderData($folder); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$data)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); } else { - $app->response()->status(404); + return $response->withStatus(404); } } else { - $app->response()->status(404); + return $response->withStatus(404); } } /* }}} */ -function getFolderParent($id) { /* {{{ */ - global $app, $dms, $userobj; +function getFolderParent($request, $response, $args) { /* {{{ */ + global $dms, $userobj; if($id == 0) { - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'id is 0', 'data'=>'')); - return; + return $response->withJson(array('success'=>true, 'message'=>'id is 0', 'data'=>''), 200); } $root = $dms->getRootFolder(); if($root->getId() == $id) { - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'id is root folder', 'data'=>'')); - return; + return $response->withJson(array('success'=>true, 'message'=>'id is root folder', 'data'=>''), 200); } $folder = $dms->getFolder($id); $parent = $folder->getParent(); if($parent) { $rec = __getFolderData($parent); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$rec)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$rec), 200); } else { - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>''), 500); } } /* }}} */ -function getFolderPath($id) { /* {{{ */ - global $app, $dms, $userobj; - if($id == 0) { - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'id is 0', 'data'=>'')); - return; +function getFolderPath($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + if(empty($args['id'])) { + return $response->withJson(array('success'=>true, 'message'=>'id is 0', 'data'=>''), 200); } - $folder = $dms->getFolder($id); + $folder = $dms->getFolder($args['id']); $path = $folder->getPath(); $data = array(); foreach($path as $element) { $data[] = array('id'=>$element->getId(), 'name'=>$element->getName()); } - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$data)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); } /* }}} */ -function getFolderAttributes($id) { /* {{{ */ - global $app, $dms, $userobj; - $folder = $dms->getFolder($id); +function getFolderAttributes($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + $folder = $dms->getFolder($args['id']); if($folder) { if ($folder->getAccessMode($userobj) >= M_READ) { @@ -347,23 +332,21 @@ function getFolderAttributes($id) { /* {{{ */ 'name'=>$attribute->getAttributeDefinition()->getName(), ); } - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$recs)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$recs), 200); } else { - $app->response()->status(404); + return $response->withStatus(404); } } } /* }}} */ -function getFolderChildren($id) { /* {{{ */ - global $app, $dms, $userobj; - if($id == 0) { +function getFolderChildren($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + if(empty($args['id'])) { $folder = $dms->getRootFolder(); $recs = array(__getFolderData($folder)); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$recs)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$recs), 200); } else { - $folder = $dms->getFolder($id); + $folder = $dms->getFolder($args['id']); if($folder) { if($folder->getAccessMode($userobj) >= M_READ) { $recs = array(); @@ -380,280 +363,322 @@ function getFolderChildren($id) { /* {{{ */ $recs[] = __getLatestVersionData($lc); } } - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$recs)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$recs), 200); } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); } } else { - $app->response()->status(404); + return $response->withStatus(404); } } } /* }}} */ -function createFolder($id) { /* {{{ */ - global $app, $dms, $userobj; +function createFolder($request, $response, $args) { /* {{{ */ + global $dms, $userobj; if(!$userobj) { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Not logged in', 'data'=>'')); - return; + return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); } - if(!ctype_digit($id) || $id == 0) { - $app->response()->status(400); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No parent folder given', 'data'=>'')); + if(!ctype_digit($args['id']) || $args['id'] == 0) { + return $response->withJson(array('success'=>false, 'message'=>'No parent folder given', 'data'=>''), 400); return; } - $parent = $dms->getFolder($id); + $parent = $dms->getFolder($args['id']); if($parent) { if($parent->getAccessMode($userobj, 'addFolder') >= M_READWRITE) { - if($name = $app->request()->post('name')) { - $comment = $app->request()->post('comment'); - $attributes = $app->request()->post('attributes'); + $params = $request->getParsedBody(); + if(!empty($params['name'])) { + $comment = isset($params['comment']) ? $params['comment'] : ''; + if(isset($params['sequence'])) { + $sequence = str_replace(',', '.', $params["sequence"]); + if (!is_numeric($sequence)) + return $response->withJson(array('success'=>false, 'message'=>getMLText("invalid_sequence"), 'data'=>''), 400); + } else { + $dd = $parent->getSubFolders('s'); + if(count($dd) > 1) + $sequence = $dd[count($dd)-1]->getSequence() + 1; + else + $sequence = 1.0; + } $newattrs = array(); - if($attributes) { - foreach($attributes as $attrname=>$attrvalue) { + if(!empty($params['attributes'])) { + foreach($params['attributes'] as $attrname=>$attrvalue) { $attrdef = $dms->getAttributeDefinitionByName($attrname); if($attrdef) { $newattrs[$attrdef->getID()] = $attrvalue; } } } - if($folder = $parent->addSubFolder($name, $comment, $userobj, 0, $newattrs)) { + if($folder = $parent->addSubFolder($params['name'], $comment, $userobj, $sequence, $newattrs)) { $rec = __getFolderData($folder); - $app->response()->status(201); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$rec)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$rec), 201); } else { - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'Could not create folder', 'data'=>''), 500); } } else { - $app->response()->status(400); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'Missing folder name', 'data'=>''), 400); } } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access on destination folder', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access on destination folder', 'data'=>''), 403); } } else { - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'Could not find parent folder', 'data'=>''), 500); } } /* }}} */ -function moveFolder($id, $folderid) { /* {{{ */ - global $app, $dms, $userobj; +function moveFolder($request, $response, $args) { /* {{{ */ + global $dms, $userobj; if(!$userobj) { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Not logged in', 'data'=>'')); - return; + return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); } - if(!ctype_digit($id) || $id == 0) { - $app->response()->status(400); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'No source folder given', 'data'=>'')); - return; + if(!ctype_digit($args['id']) || $args['id'] == 0) { + return $response->withJson(array('success'=>true, 'message'=>'No source folder given', 'data'=>''), 400); } - if(!ctype_digit($folderid) || $folderid == 0) { - $app->response()->status(400); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'No destination folder given', 'data'=>'')); - return; + if(!ctype_digit($args['folderid']) || $args['folderid'] == 0) { + return $response->withJson(array('success'=>true, 'message'=>'No destination folder given', 'data'=>''), 400); } - $mfolder = $dms->getFolder($id); + $mfolder = $dms->getFolder($args['id']); if($mfolder) { if ($mfolder->getAccessMode($userobj, 'moveFolder') >= M_READ) { - if($folder = $dms->getFolder($folderid)) { + if($folder = $dms->getFolder($args['folderid'])) { if($folder->getAccessMode($userobj, 'moveFolder') >= M_READWRITE) { if($mfolder->setParent($folder)) { - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>'')); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); } else { - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Error moving folder', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'Error moving folder', 'data'=>''), 500); } } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access on destination folder', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access on destination folder', 'data'=>''), 403); } } else { if($folder === null) - $app->response()->status(400); + $status = 400; else - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No destination folder', 'data'=>'')); + $status = 500; + return $response->withJson(array('success'=>false, 'message'=>'No destination folder', 'data'=>''), $status); } } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); } } else { if($mfolder === null) - $app->response()->status(400); + $status=400; else - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No folder', 'data'=>'')); + $status=500; + return $response->withJson(array('success'=>false, 'message'=>'No folder', 'data'=>''), $status); } } /* }}} */ -function deleteFolder($id) { /* {{{ */ - global $app, $dms, $userobj; +function deleteFolder($request, $response, $args) { /* {{{ */ + global $dms, $userobj; if(!$userobj) { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Not logged in', 'data'=>'')); - return; + return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); } - if(!ctype_digit($id) || $id == 0) { - $app->response()->status(400); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'id is 0', 'data'=>'')); - return; + if(!ctype_digit($args['id']) || $args['id'] == 0) { + return $response->withJson(array('success'=>true, 'message'=>'id is 0', 'data'=>''), 400); } - $mfolder = $dms->getFolder($id); + $mfolder = $dms->getFolder($args['id']); if($mfolder) { if ($mfolder->getAccessMode($userobj, 'removeFolder') >= M_READWRITE) { if($mfolder->remove()) { - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>'')); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); } else { - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Error deleting folder', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'Error deleting folder', 'data'=>''), 500); } } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); } } else { if($mfolder === null) - $app->response()->status(400); + $status=400; else - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No folder', 'data'=>'')); + $status=500; + return $response->withJson(array('success'=>false, 'message'=>'No folder', 'data'=>''), $status); } } /* }}} */ -function uploadDocument($id) { /* {{{ */ - global $app, $dms, $userobj; +function uploadDocument($request, $response, $args) { /* {{{ */ + global $dms, $userobj; if(!$userobj) { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Not logged in', 'data'=>'')); - return; + return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); } - if(!ctype_digit($id) || $id == 0) { - $app->response()->status(400); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'id is 0', 'data'=>'')); - return; + if(!ctype_digit($args['id']) || $args['id'] == 0) { + return $response->withJson(array('success'=>false, 'message'=>'No parent folder id given', 'data'=>''), 400); } - $mfolder = $dms->getFolder($id); + + $mfolder = $dms->getFolder($args['id']); if($mfolder) { + $uploadedFiles = $request->getUploadedFiles(); if ($mfolder->getAccessMode($userobj, 'addDocument') >= M_READWRITE) { - $docname = $app->request()->params('name'); - $keywords = $app->request()->params('keywords'); -// $categories = $app->request()->params('categories') ? $app->request()->params('categories') : []; -// $attributes = $app->request()->params('attributes') ? $app->request()->params('attributes') : []; - $origfilename = $app->request()->params('origfilename'); - if (count($_FILES) == 0) { - $app->response()->status(400); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No file detected', 'data'=>'')); - return; + $params = $request->getParsedBody(); + $docname = isset($params['name']) ? $params['name'] : ''; + $keywords = isset($params['keywords']) ? $params['keywords'] : ''; + $comment = isset($params['comment']) ? $params['comment'] : ''; + if(isset($params['sequence'])) { + $sequence = str_replace(',', '.', $params["sequence"]); + if (!is_numeric($sequence)) + return $response->withJson(array('success'=>false, 'message'=>getMLText("invalid_sequence"), 'data'=>''), 400); + } else { + $dd = $mfolder->getDocuments('s'); + if(count($dd) > 1) + $sequence = $dd[count($dd)-1]->getSequence() + 1; + else + $sequence = 1.0; } - $file_info = reset($_FILES); + if(isset($params['expdate'])) { + $tmp = explode('-', $params["expdate"]); + if(count($tmp) != 3) + return $response->withJson(array('success'=>false, 'message'=>getMLText('malformed_expiration_date'), 'data'=>''), 400); + $expires = mktime(0,0,0, $tmp[1], $tmp[2], $tmp[0]); + } else + $expires = 0; + $version_comment = isset($params['version_comment']) ? $params['version_comment'] : ''; + $reqversion = (isset($params['reqversion']) && (int) $params['reqversion'] > 1) ? (int) $params['reqversion'] : 1; + $origfilename = isset($params['origfilename']) ? $params['origfilename'] : null; + $categories = isset($params["categories"]) ? $params["categories"] : array(); + $cats = array(); + foreach($categories as $catid) { + if($cat = $dms->getDocumentCategory($catid)) + $cats[] = $cat; + } + $attributes = isset($params["attributes"]) ? $params["attributes"] : array(); + foreach($attributes as $attrdefid=>$attribute) { + if($attrdef = $dms->getAttributeDefinition($attrdefid)) { + if($attribute) { + if(!$attrdef->validate($attribute)) { + return $response->withJson(array('success'=>false, 'message'=>getAttributeValidationText($attrdef->getValidationError(), $attrdef->getName(), $attribute), 'data'=>''), 400); + } + } elseif($attrdef->getMinValues() > 0) { + return $response->withJson(array('success'=>false, 'message'=>getMLText("attr_min_values", array("attrname"=>$attrdef->getName())), 'data'=>''), 400); + } + } + } + if (count($uploadedFiles) == 0) { + return $response->withJson(array('success'=>false, 'message'=>'No file detected', 'data'=>''), 400); + } + $file_info = array_pop($uploadedFiles); if ($origfilename == null) - $origfilename = $file_info['name']; + $origfilename = $file_info->getClientFilename(); if (trim($docname) == '') $docname = $origfilename; - $temp = $file_info['tmp_name']; + $temp = $file_info->file; $finfo = finfo_open(FILEINFO_MIME_TYPE); $userfiletype = finfo_file($finfo, $temp); $fileType = ".".pathinfo($origfilename, PATHINFO_EXTENSION); finfo_close($finfo); - $res = $mfolder->addDocument($docname, '', 0, $userobj, $keywords, array(), $temp, $origfilename ? $origfilename : basename($temp), $fileType, $userfiletype, 0); + $res = $mfolder->addDocument($docname, $comment, $expires, $userobj, $keywords, $cats, $temp, $origfilename ? $origfilename : basename($temp), $fileType, $userfiletype, $sequence, array(), array(), $reqversion, $version_comment, $attributes); // addDocumentCategories($res, $categories); // setDocumentAttributes($res, $attributes); unlink($temp); if($res) { $doc = $res[0]; - $rec = array('id'=>(int)$doc->getId(), 'name'=>$doc->getName()); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'Upload succeded', 'data'=>$rec)); + $rec = array('id'=>(int)$doc->getId(), 'name'=>$doc->getName(), 'version'=>$doc->getLatestContent()->getVersion()); + return $response->withJson(array('success'=>true, 'message'=>'Upload succeded', 'data'=>$rec), 200); } else { - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Upload failed', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'Upload failed', 'data'=>''), 500); } } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); } } else { if($mfolder === null) - $app->response()->status(400); + $status=400; else - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No folder', 'data'=>'')); + $status=500; + return $response->withJson(array('success'=>false, 'message'=>'No folder', 'data'=>''), $status); + } +} /* }}} */ + +function updateDocument($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + + if(!$userobj) { + return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); + } + + if(!ctype_digit($args['id']) || $args['id'] == 0) { + return $response->withJson(array('success'=>false, 'message'=>'No document id given', 'data'=>''), 400); + } + + $document = $dms->getDocument($args['id']); + if($document) { + if ($document->getAccessMode($userobj, 'updateDocument') >= M_READWRITE) { + $params = $request->getParsedBody(); + $origfilename = isset($params['origfilename']) ? $params['origfilename'] : null; + $comment = isset($params['comment']) ? $params['comment'] : null; + $attributes = isset($params["attributes"]) ? $params["attributes"] : array(); + foreach($attributes as $attrdefid=>$attribute) { + if($attrdef = $dms->getAttributeDefinition($attrdefid)) { + if($attribute) { + if(!$attrdef->validate($attribute)) { + return $response->withJson(array('success'=>false, 'message'=>getAttributeValidationText($attrdef->getValidationError(), $attrdef->getName(), $attribute), 'data'=>''), 400); + } + } elseif($attrdef->getMinValues() > 0) { + return $response->withJson(array('success'=>false, 'message'=>getMLText("attr_min_values", array("attrname"=>$attrdef->getName())), 'data'=>''), 400); + } + } + } + $uploadedFiles = $request->getUploadedFiles(); + if (count($uploadedFiles) == 0) { + return $response->withJson(array('success'=>false, 'message'=>'No file detected', 'data'=>''), 400); + } + $file_info = array_pop($uploadedFiles); + if ($origfilename == null) + $origfilename = $file_info->getClientFilename(); + $temp = $file_info->file; + $finfo = finfo_open(FILEINFO_MIME_TYPE); + $userfiletype = finfo_file($finfo, $temp); + $fileType = ".".pathinfo($origfilename, PATHINFO_EXTENSION); + finfo_close($finfo); + $res=$document->addContent($comment, $userobj, $temp, $origfilename, $fileType, $userfiletype, array(), array(), 0, $attributes); + + unlink($temp); + if($res) { + $rec = array('id'=>(int)$document->getId(), 'name'=>$document->getName(), 'version'=>$document->getLatestContent()->getVersion()); + return $response->withJson(array('success'=>true, 'message'=>'Upload succeded', 'data'=>$rec), 200); + } else { + return $response->withJson(array('success'=>false, 'message'=>'Upload failed', 'data'=>''), 500); + } + } else { + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + } + } else { + return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), 400); } } /* }}} */ /** * Old upload method which uses put instead of post */ -function uploadDocumentPut($id) { /* {{{ */ - global $app, $dms, $userobj; +function uploadDocumentPut($request, $response, $args) { /* {{{ */ + global $dms, $userobj; if(!$userobj) { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Not logged in', 'data'=>'')); - return; + return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); } - if(!ctype_digit($id) || $id == 0) { - $app->response()->status(400); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'id is 0', 'data'=>'')); - return; + if(!ctype_digit($args['id']) || $args['id'] == 0) { + return $response->withJson(array('success'=>false, 'message'=>'No document id given', 'data'=>''), 400); } - $mfolder = $dms->getFolder($id); + $mfolder = $dms->getFolder($args['id']); if($mfolder) { if ($mfolder->getAccessMode($userobj, 'addDocument') >= M_READWRITE) { - $docname = $app->request()->get('name'); - $origfilename = $app->request()->get('origfilename'); - $content = $app->getInstance()->request()->getBody(); + $params = $request->getQueryParams(); + $docname = isset($params['name']) ? $params['name'] : ''; + $keywords = isset($params['keywords']) ? $params['keywords'] : ''; + $origfilename = isset($params['origfilename']) ? $params['origfilename'] : null; + $content = $request->getBody(); $temp = tempnam('/tmp', 'lajflk'); $handle = fopen($temp, "w"); fwrite($handle, $content); @@ -667,64 +692,52 @@ function uploadDocumentPut($id) { /* {{{ */ if($res) { $doc = $res[0]; $rec = array('id'=>(int)$doc->getId(), 'name'=>$doc->getName()); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'Upload succeded', 'data'=>$rec)); + return $response->withJson(array('success'=>true, 'message'=>'Upload succeded', 'data'=>$rec), 200); } else { - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Upload failed', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'Upload failed', 'data'=>''), 500); } } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); } } else { if($mfolder === null) - $app->response()->status(400); + $status=400; else - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No folder', 'data'=>'')); + $status=500; + return $response->withJson(array('success'=>false, 'message'=>'No folder', 'data'=>''), $status); } } /* }}} */ -function uploadDocumentFile($documentId) { /* {{{ */ - global $app, $dms, $userobj; +function uploadDocumentFile($request, $response, $args) { /* {{{ */ + global $dms, $userobj; if(!$userobj) { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Not logged in', 'data'=>'')); - return; + return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); } - if(!ctype_digit($documentId) || $documentId == 0) { - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'id is 0', 'data'=>'')); - return; + if(!ctype_digit($args['id']) || $args['id'] == 0) { + return $response->withJson(array('success'=>false, 'message'=>'No document id given', 'data'=>''), 400); } - $document = $dms->getDocument($documentId); + $document = $dms->getDocument($args['id']); if($document) { if ($document->getAccessMode($userobj, 'addDocumentFile') >= M_READWRITE) { - $docname = $app->request()->params('name'); - $keywords = $app->request()->params('keywords'); - $origfilename = $app->request()->params('origfilename'); - $comment = $app->request()->params('comment'); - $version = $app->request()->params('version') == '' ? 0 : $app->request()->params('version'); - $public = $app->request()->params('public') == '' ? 'false' : $app->request()->params('public'); - if (count($_FILES) == 0) { - $app->response()->status(400); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No file detected', 'data'=>'')); - return; + $uploadedFiles = $request->getUploadedFiles(); + $params = $request->getParsedBody(); + $docname = $params['name']; + $keywords = isset($params['keywords']) ? $params['keywords'] : ''; + $origfilename = $params['origfilename']; + $comment = isset($params['comment']) ? $params['comment'] : ''; + $version = empty($params['version']) ? 0 : $params['version']; + $public = empty($params['public']) ? 'false' : $params['public']; + if (count($uploadedFiles) == 0) { + return $response->withJson(array('success'=>false, 'message'=>'No file detected', 'data'=>''), 400); } - $file_info = reset($_FILES); + $file_info = array_pop($uploadedFiles); if ($origfilename == null) - $origfilename = $file_info['name']; + $origfilename = $file_info->getClientFilename(); if (trim($docname) == '') $docname = $origfilename; - $temp = $file_info['tmp_name']; + $temp = $file_info->file; $finfo = finfo_open(FILEINFO_MIME_TYPE); $userfiletype = finfo_file($finfo, $temp); $fileType = ".".pathinfo($origfilename, PATHINFO_EXTENSION); @@ -734,175 +747,181 @@ function uploadDocumentFile($documentId) { /* {{{ */ $fileType, $userfiletype, $version, $public); unlink($temp); if($res) { - $app->response()->status(201); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'Upload succeded', 'data'=>$res)); + return $response->withJson(array('success'=>true, 'message'=>'Upload succeded', 'data'=>$res), 201); } else { - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Upload failed', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'Upload failed', 'data'=>''), 500); } } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); } } else { if($document === null) - $app->response()->status(400); + $status=400; else - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No such document', 'data'=>'')); + $status=500; + return $response->withJson(array('success'=>false, 'message'=>'No such document', 'data'=>''), $status); } } /* }}} */ -function getDocument($id) { /* {{{ */ - global $app, $dms, $userobj; - $document = $dms->getDocument($id); +function addDocumentLink($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + + if(!$userobj) { + return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); + } + + if(!ctype_digit($args['id']) || $args['id'] == 0) { + return $response->withJson(array('success'=>false, 'message'=>'No source document given', 'data'=>''), 400); + return; + } + $sourcedoc = $dms->getDocument($args['id']); + $targetdoc = $dms->getDocument($args['documentid']); + if($sourcedoc && $targetdoc) { + if($sourcedoc->getAccessMode($userobj, 'addDocumentLink') >= M_READ) { + $params = $request->getParsedBody(); + $public = !isset($params['public']) ? true : false; + if ($sourcedoc->addDocumentLink($targetdoc->getId(), $userobj->getID(), $public)){ + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 201); + } else { + return $response->withJson(array('success'=>false, 'message'=>'Could not create document link', 'data'=>''), 500); + } + } else { + return $response->withJson(array('success'=>false, 'message'=>'No access on source document', 'data'=>''), 403); + } + } else { + return $response->withJson(array('success'=>false, 'message'=>'Could not find source or target document', 'data'=>''), 500); + } +} /* }}} */ + +function getDocument($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + $document = $dms->getDocument($args['id']); if($document) { if ($document->getAccessMode($userobj) >= M_READ) { $lc = $document->getLatestContent(); if($lc) { $data = __getLatestVersionData($lc); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$data)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); } } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); } } else { if($document === null) - $app->response()->status(400); + $status=400; else - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No document', 'data'=>'')); + $status=500; + return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); } } /* }}} */ -function deleteDocument($id) { /* {{{ */ - global $app, $dms, $userobj; - $document = $dms->getDocument($id); +function deleteDocument($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + $document = $dms->getDocument($args['id']); if($document) { if ($document->getAccessMode($userobj, 'deleteDocument') >= M_READWRITE) { if($document->remove()) { - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>'')); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); } else { - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Error removing document', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'Error removing document', 'data'=>''), 500); } } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); } } else { if($document === null) - $app->response()->status(400); + $status=400; else - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No document', 'data'=>'')); + $status=500; + return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); } } /* }}} */ -function moveDocument($id, $folderid) { /* {{{ */ - global $app, $dms, $userobj; - $document = $dms->getDocument($id); +function moveDocument($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + $document = $dms->getDocument($args['id']); if($document) { if ($document->getAccessMode($userobj, 'moveDocument') >= M_READ) { - if($folder = $dms->getFolder($folderid)) { + if($folder = $dms->getFolder($args['folderid'])) { if($folder->getAccessMode($userobj, 'moveDocument') >= M_READWRITE) { if($document->setFolder($folder)) { - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>'')); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); } else { - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Error moving document', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'Error moving document', 'data'=>''), 500); } } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access on destination folder', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access on destination folder', 'data'=>''), 403); } } else { if($folder === null) - $app->response()->status(400); + $status=400; else - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No destination folder', 'data'=>'')); + $status=500; + return $response->withJson(array('success'=>false, 'message'=>'No destination folder', 'data'=>''), $status); } } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); } } else { if($document === null) - $app->response()->status(400); + $status=400; else - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No document', 'data'=>'')); + $status=500; + return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); } } /* }}} */ -function getDocumentContent($id) { /* {{{ */ - global $app, $dms, $userobj; - $document = $dms->getDocument($id); +function getDocumentContent($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + $document = $dms->getDocument($args['id']); if($document) { if ($document->getAccessMode($userobj) >= M_READ) { $lc = $document->getLatestContent(); if($lc) { - if (pathinfo($document->getName(), PATHINFO_EXTENSION) == $lc->getFileType()) - $filename = $document->getName(); - else - $filename = $document->getName().$lc->getFileType(); + if (pathinfo($document->getName(), PATHINFO_EXTENSION) == $lc->getFileType()) + $filename = $document->getName(); + else + $filename = $document->getName().$lc->getFileType(); - $app->response()->header('Content-Type', $lc->getMimeType()); - $app->response()->header("Content-Disposition", "filename=\"" . $filename . "\""); - $app->response()->header("Content-Length", filesize($dms->contentDir . $lc->getPath())); - $app->response()->header("Expires", "0"); - $app->response()->header("Cache-Control", "no-cache, must-revalidate"); - $app->response()->header("Pragma", "no-cache"); + $file = $dms->contentDir . $lc->getPath(); + if(!($fh = @fopen($file, 'rb'))) { + return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>''), 500); + } + $stream = new \Slim\Http\Stream($fh); // create a stream instance for the response body + + return $response->withHeader('Content-Type', $lc->getMimeType()) + ->withHeader('Content-Description', 'File Transfer') + ->withHeader('Content-Transfer-Encoding', 'binary') + ->withHeader('Content-Disposition', 'attachment; filename="' . $filename . '"') + ->withHeader('Content-Length', filesize($dms->contentDir . $lc->getPath())) + ->withHeader('Expires', '0') + ->withHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0') + ->withHeader('Pragma', 'no-cache') + ->withBody($stream); sendFile($dms->contentDir . $lc->getPath()); } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); } } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); } } else { if($document === null) - $app->response()->status(400); + $status=400; else - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No document', 'data'=>'')); + $status=500; + return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); } } /* }}} */ -function getDocumentVersions($id) { /* {{{ */ - global $app, $dms, $userobj; - $document = $dms->getDocument($id); +function getDocumentVersions($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + $document = $dms->getDocument($args['id']); if($document) { if ($document->getAccessMode($userobj) >= M_READ) { @@ -917,66 +936,95 @@ function getDocumentVersions($id) { /* {{{ */ 'comment'=>$lc->getComment(), ); } - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$recs)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$recs), 200); } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); } } else { if($document === null) - $app->response()->status(400); + $status=400; else - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No document', 'data'=>'')); + $status=500; + return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); } } /* }}} */ -function getDocumentVersion($id, $version) { /* {{{ */ - global $app, $dms, $userobj; - $document = $dms->getDocument($id); +function getDocumentVersion($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + $document = $dms->getDocument($args['id']); if($document) { if ($document->getAccessMode($userobj) >= M_READ) { - $lc = $document->getContentByVersion($version); + $lc = $document->getContentByVersion($args['version']); if($lc) { - if (pathinfo($document->getName(), PATHINFO_EXTENSION) == $lc->getFileType()) - $filename = $document->getName(); - else - $filename = $document->getName().$lc->getFileType(); - $app->response()->header('Content-Type', $lc->getMimeType()); - $app->response()->header("Content-Disposition", "filename=\"" . $filename . "\""); - $app->response()->header("Content-Length", filesize($dms->contentDir . $lc->getPath())); - $app->response()->header("Expires", "0"); - $app->response()->header("Cache-Control", "no-cache, must-revalidate"); - $app->response()->header("Pragma", "no-cache"); + if (pathinfo($document->getName(), PATHINFO_EXTENSION) == $lc->getFileType()) + $filename = $document->getName(); + else + $filename = $document->getName().$lc->getFileType(); - sendFile($dms->contentDir . $lc->getPath()); + $file = $dms->contentDir . $lc->getPath(); + if(!($fh = @fopen($file, 'rb'))) { + return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>''), 500); + } + $stream = new \Slim\Http\Stream($fh); // create a stream instance for the response body + + return $response->withHeader('Content-Type', $lc->getMimeType()) + ->withHeader('Content-Description', 'File Transfer') + ->withHeader('Content-Transfer-Encoding', 'binary') + ->withHeader('Content-Disposition', 'attachment; filename="' . $filename . '"') + ->withHeader('Content-Length', filesize($dms->contentDir . $lc->getPath())) + ->withHeader('Expires', '0') + ->withHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0') + ->withHeader('Pragma', 'no-cache') + ->withBody($stream); + + sendFile($dms->contentDir . $lc->getPath()); } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No such version', 'data'=>''), 400); } } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); } } else { if($document === null) - $app->response()->status(400); + $status=400; else - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No document', 'data'=>'')); + $status=500; + return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); } } /* }}} */ -function getDocumentFiles($id) { /* {{{ */ - global $app, $dms, $userobj; - $document = $dms->getDocument($id); +function updateDocumentVersion($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + $document = $dms->getDocument($args['id']); + + if($document) { + if ($document->getAccessMode($userobj) >= M_READ) { + $lc = $document->getContentByVersion($args['version']); + if($lc) { + $params = $request->getParsedBody(); + if (isset($params['comment'])) { + $lc->setComment($params['comment']); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); + } + } else { + return $response->withJson(array('success'=>false, 'message'=>'No such version', 'data'=>''), 400); + } + } else { + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + } + } else { + if($document === null) + $status=400; + else + $status=500; + return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); + } +} /* }}} */ + +function getDocumentFiles($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + $document = $dms->getDocument($args['id']); if($document) { if ($document->getAccessMode($userobj) >= M_READ) { @@ -991,56 +1039,59 @@ function getDocumentFiles($id) { /* {{{ */ 'comment'=>$file->getComment(), ); } - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$recs)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$recs), 200); } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); } } else { if($document === null) - $app->response()->status(400); + $status=400; else - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No document', 'data'=>'')); + $status=500; + return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); } } /* }}} */ -function getDocumentFile($id, $fileid) { /* {{{ */ - global $app, $dms, $userobj; - $document = $dms->getDocument($id); +function getDocumentFile($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + $document = $dms->getDocument($args['id']); if($document) { if ($document->getAccessMode($userobj) >= M_READ) { - $file = $document->getDocumentFile($fileid); - $app->response()->header('Content-Type', $file->getMimeType()); - $app->response()->header("Content-Disposition", "filename=\"" . $document->getName().$file->getFileType() . "\""); - $app->response()->header("Content-Length", filesize($dms->contentDir . $file->getPath())); - $app->response()->header("Expires", "0"); - $app->response()->header("Cache-Control", "no-cache, must-revalidate"); - $app->response()->header("Pragma", "no-cache"); + $lc = $document->getDocumentFile($args['fileid']); - sendFile($dms->contentDir . $file->getPath()); + $file = $dms->contentDir . $lc->getPath(); + if(!($fh = @fopen($file, 'rb'))) { + return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>''), 500); + } + $stream = new \Slim\Http\Stream($fh); // create a stream instance for the response body + + return $response->withHeader('Content-Type', $lc->getMimeType()) + ->withHeader('Content-Description', 'File Transfer') + ->withHeader('Content-Transfer-Encoding', 'binary') + ->withHeader('Content-Disposition', 'attachment; filename="' . $document->getName() . $lc->getFileType() . '"') + ->withHeader('Content-Length', filesize($dms->contentDir . $lc->getPath())) + ->withHeader('Expires', '0') + ->withHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0') + ->withHeader('Pragma', 'no-cache') + ->withBody($stream); + + sendFile($dms->contentDir . $lc->getPath()); } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); } } else { if($document === null) - $app->response()->status(400); + $status=400; else - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No document', 'data'=>'')); + $status=500; + return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); } } /* }}} */ -function getDocumentLinks($id) { /* {{{ */ - global $app, $dms, $userobj; - $document = $dms->getDocument($id); +function getDocumentLinks($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + $document = $dms->getDocument($args['id']); if($document) { if ($document->getAccessMode($userobj) >= M_READ) { @@ -1053,26 +1104,22 @@ function getDocumentLinks($id) { /* {{{ */ 'public'=>$link->isPublic(), ); } - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$recs)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$recs), 200); } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); } } else { if($document === null) - $app->response()->status(400); + $status=400; else - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No document', 'data'=>'')); + $status=500; + return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); } } /* }}} */ -function getDocumentAttributes($id) { /* {{{ */ - global $app, $dms, $userobj; - $document = $dms->getDocument($id); +function getDocumentAttributes($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + $document = $dms->getDocument($args['id']); if($document) { if ($document->getAccessMode($userobj) >= M_READ) { @@ -1085,130 +1132,116 @@ function getDocumentAttributes($id) { /* {{{ */ 'name'=>$attribute->getAttributeDefinition()->getName(), ); } - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$recs)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$recs), 200); } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); } } else { if($document === null) - $app->response()->status(400); + $status=400; else - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No document', 'data'=>'')); + $status=500; + return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); } } /* }}} */ -function getDocumentPreview($id, $version=0, $width=0) { /* {{{ */ - global $app, $dms, $userobj, $settings; +function getDocumentPreview($request, $response, $args) { /* {{{ */ + global $dms, $userobj, $settings; require_once "SeedDMS/Preview.php"; - $document = $dms->getDocument($id); + $document = $dms->getDocument($args['id']); if($document) { if ($document->getAccessMode($userobj) >= M_READ) { - if($version) - $object = $document->getContentByVersion($version); + if($args['version']) + $object = $document->getContentByVersion($args['version']); else $object = $document->getLatestContent(); if(!$object) exit; - if(!empty($width)) - $previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir, $width); + if(!empty($args['width'])) + $previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir, $args['width']); else $previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir); if(!$previewer->hasPreview($object)) $previewer->createPreview($object); - $app->response()->header('Content-Type', 'image/png'); - $app->response()->header("Content-Disposition", "filename=\"preview-" . $document->getID()."-".$object->getVersion()."-".$width.".png" . "\""); - $app->response()->header("Content-Length", $previewer->getFilesize($object)); -// $app->response()->header("Expires", "0"); -// $app->response()->header("Cache-Control", "no-cache, must-revalidate"); -// $app->response()->header("Pragma", "no-cache"); - $previewer->getPreview($object); + $file = $previewer->getFileName($object, $args['width']).".png"; + if(!($fh = @fopen($file, 'rb'))) { + return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>''), 500); + } + $stream = new \Slim\Http\Stream($fh); // create a stream instance for the response body + + return $response->withHeader('Content-Type', 'image/png') + ->withHeader('Content-Description', 'File Transfer') + ->withHeader('Content-Transfer-Encoding', 'binary') + ->withHeader('Content-Disposition', 'attachment; filename=preview-"' . $document->getID() . "-" . $object->getVersion() . "-" . $width . ".png" . '"') + ->withHeader('Content-Length', $previewer->getFilesize($object)) + ->withBody($stream); } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); } } else { if($document === null) - $app->response()->status(400); + $status=400; else - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No document', 'data'=>'')); + $status=500; + return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); } } /* }}} */ -function removeDocumentCategory($id, $categoryId) { /* {{{ */ - global $app, $dms, $userobj; - $document = $dms->getDocument($id); - $category = $dms->getDocumentCategory($categoryId); +function removeDocumentCategory($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + $document = $dms->getDocument($args['id']); + $category = $dms->getDocumentCategory($args['categoryId']); if($document && $category) { if ($document->getAccessMode($userobj, 'removeDocumentCategory') >= M_READWRITE) { $ret = $document->removeCategories(array($category)); - - $app->response()->header('Content-Type', 'application/json'); if ($ret) - echo json_encode(array('success'=>true, 'message'=>'Deleted category successfully.', 'data'=>'')); + return $response->withJson(array('success'=>true, 'message'=>'Deleted category successfully.', 'data'=>''), 200); else - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>'')); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); } } else { - if($document === null || $category === null) - $app->response()->status(400); - else - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No such document', 'data'=>'')); + if(!$document) + return $response->withJson(array('success'=>false, 'message'=>'No such document', 'data'=>''), 400); + if(!$category) + return $response->withJson(array('success'=>false, 'message'=>'No such category', 'data'=>''), 400); + return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>''), 500); } } /* }}} */ -function removeDocumentCategories($id) { /* {{{ */ - global $app, $dms, $userobj; - $document = $dms->getDocument($id); +function removeDocumentCategories($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + $document = $dms->getDocument($args['id']); if($document) { if ($document->getAccessMode($userobj, 'removeDocumentCategory') >= M_READWRITE) { - $app->response()->header('Content-Type', 'application/json'); if($document->setCategories(array())) - echo json_encode(array('success'=>true, 'message'=>'Deleted categories successfully.', 'data'=>'')); + return $response->withJson(array('success'=>true, 'message'=>'Deleted categories successfully.', 'data'=>''), 200); else - echo json_encode(array('success'=>false, 'message'=>'', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>''), 200); } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No access', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); } } else { if($document === null) - $app->response()->status(400); + $status=400; else - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No such document', 'data'=>'')); + $status=500; + return $response->withJson(array('success'=>false, 'message'=>'No such document', 'data'=>''), $status); } } /* }}} */ -function getAccount() { /* {{{ */ - global $app, $dms, $userobj; +function getAccount($request, $response) { /* {{{ */ + global $dms, $userobj; if($userobj) { - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>__getUserData($userobj))); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>__getUserData($userobj)), 200); } else { - $app->response()->status(403); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Not logged in', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); } } /* }}} */ @@ -1218,17 +1251,23 @@ function getAccount() { /* {{{ */ * If the request parameter 'mode' is set to 'typeahead', it will * return a list of words only. */ -function doSearch() { /* {{{ */ - global $app, $dms, $userobj; +function doSearch($request, $response) { /* {{{ */ + global $dms, $userobj; - $querystr = $app->request()->get('query'); - $mode = $app->request()->get('mode'); - if(!$limit = $app->request()->get('limit')) + $params = $request->getQueryParams(); + $querystr = $params['query']; + $mode = isset($params['mode']) ? $params['mode'] : ''; + if(!isset($params['limit']) || !$limit = $params['limit']) $limit = 5; - $resArr = $dms->search($querystr); + if(!isset($params['offset']) || !$offset = $params['offset']) + $offset = 0; + if(!isset($params['searchin']) || !$searchin = explode(",",$params['searchin'])) + $searchin = array(); + if(!isset($params['objects']) || !$objects = $params['objects']) + $objects = 0x3; + $resArr = $dms->search($querystr, $limit, $offset, 'AND', $searchin, null, null, array(), array(), array(), array(), array(), array(), array(), $objects); if($resArr === false) { - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array()); + return $response->withJson(array(), 200); } $entries = array(); $count = 0; @@ -1285,9 +1324,7 @@ function doSearch() { /* {{{ */ if($recs) // array_unshift($recs, array('type'=>'', 'id'=>0, 'name'=>$querystr, 'comment'=>'')); array_unshift($recs, ' '.$querystr); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode($recs); - //echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$recs)); + return $response->withJson($recs, 200); break; default: $recs = array(); @@ -1303,8 +1340,7 @@ function doSearch() { /* {{{ */ $recs[] = __getFolderData($folder); } } - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$recs)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$recs)); break; } } /* }}} */ @@ -1313,12 +1349,13 @@ function doSearch() { /* {{{ */ * Search for documents/folders with a given attribute=value * */ -function doSearchByAttr() { /* {{{ */ - global $app, $dms, $userobj; +function doSearchByAttr($request, $response) { /* {{{ */ + global $dms, $userobj; - $attrname = $app->request()->get('name'); - $query = $app->request()->get('value'); - if(!$limit = $app->request()->get('limit')) + $params = $request->getQueryParams(); + $attrname = $params['name']; + $query = $params['value']; + if(empty($params['limit']) || !$limit = $params['limit']) $limit = 50; $attrdef = $dms->getAttributeDefinitionByName($attrname); $entries = array(); @@ -1352,86 +1389,84 @@ function doSearchByAttr() { /* {{{ */ $recs[] = __getFolderData($folder); } } - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$recs)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$recs), 200); } /* }}} */ -function checkIfAdmin() { /* {{{ */ - global $app, $dms, $userobj; +function checkIfAdmin($request, $response) { /* {{{ */ + global $dms, $userobj; if(!$userobj) { - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Not logged in', 'data'=>'')); - return; + return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 200); } if(!$userobj->isAdmin()) { - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'You must be logged in with an administrator account to access this resource', 'data'=>'')); - return; + return $response->withJson(array('success'=>false, 'message'=>'You must be logged in with an administrator account to access this resource', 'data'=>''), 200); } return true; } /* }}} */ -function getUsers() { /* {{{ */ - global $app, $dms, $userobj; +function getUsers($request, $response) { /* {{{ */ + global $dms, $userobj; - checkIfAdmin(); + $check = checkIfAdmin($request, $response); + if($check !== true) + return $check; $users = $dms->getAllUsers(); $data = []; foreach($users as $u) $data[] = __getUserData($u); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$data)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); } /* }}} */ -function createUser() { /* {{{ */ - global $app, $dms, $userobj; +function createUser($request, $response) { /* {{{ */ + global $dms, $userobj; - checkIfAdmin(); + $check = checkIfAdmin($request, $response); + if($check !== true) + return $check; - $userName = $app->request()->post('user'); - $password = $app->request()->post('pass'); - $fullname = $app->request()->post('name'); - $email = $app->request()->post('email'); - $language = $app->request()->post('language'); - $theme = $app->request()->post('theme'); - $comment = $app->request()->post('comment'); - $role = $app->request()->post('role'); + $params = $request->getParsedBody(); + if(empty(trim($params['user']))) { + return $response->withJson(array('success'=>false, 'message'=>'Missing user login', 'data'=>''), 500); + } + $userName = $params['user']; + $password = isset($params['pass']) ? $params['pass'] : ''; + if(empty(trim($params['name']))) { + return $response->withJson(array('success'=>false, 'message'=>'Missing full user name', 'data'=>''), 500); + } + $fullname = $params['name']; + $email = isset($params['email']) ? $params['email'] : ''; + $language = isset($params['language']) ? $params['language'] : null;; + $theme = isset($params['theme']) ? $params['theme'] : null; + $comment = isset($params['comment']) ? $params['comment'] : null; + $role = isset($params['role']) ? $params['role'] : null; $roleid = $role == 'admin' ? SeedDMS_Core_User::role_admin : ($role == 'guest' ? SeedDMS_Core_User::role_guest : SeedDMS_Core_User::role_user); $newAccount = $dms->addUser($userName, $password, $fullname, $email, $language, $theme, $comment, $roleid); if ($newAccount === false) { - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Account could not be created, maybe it already exists', 'data'=>'')); - return; + return $response->withJson(array('success'=>false, 'message'=>'Account could not be created, maybe it already exists', 'data'=>''), 500); } $result = __getUserData($newAccount); - $app->response()->status(201); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$result)); - return; + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$result), 201); } /* }}} */ -function deleteUser($id) { /* {{{ */ - global $app, $dms, $userobj; - checkIfAdmin(); +function deleteUser($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + $check = checkIfAdmin($request, $response); + if($check !== true) + return $check; - $app->response()->header('Content-Type', 'application/json'); - if($user = $dms->getUser($id)) { + if($user = $dms->getUser($args['id'])) { if($result = $user->remove($userobj, $userobj)) { - echo json_encode(array('success'=>$result, 'message'=>'', 'data'=>'')); + return $response->withJson(array('success'=>$result, 'message'=>'', 'data'=>''), 200); } else { - $app->response()->status(500); - echo json_encode(array('success'=>$result, 'message'=>'Could not delete user', 'data'=>'')); + return $response->withJson(array('success'=>$result, 'message'=>'Could not delete user', 'data'=>''), 500); } } else { - $app->response()->status(404); - echo json_encode(array('success'=>false, 'message'=>'No such user', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No such user', 'data'=>''), 404); } } /* }}} */ @@ -1440,125 +1475,134 @@ function deleteUser($id) { /* {{{ */ * * @param $id The user name or numerical identifier */ -function changeUserPassword($id) { /* {{{ */ - global $app, $dms, $userobj; +function changeUserPassword($request, $response, $args) { /* {{{ */ + global $dms, $userobj; - checkIfAdmin(); + $check = checkIfAdmin($request, $response); + if($check !== true) + return $check; - if ($app->request()->put('password') == null) - { - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'You must supply a new password', 'data'=>'')); - return; + $params = $request->getParsedBody(); + if ($params['password'] == null) { + return $response->withJson(array('success'=>false, 'message'=>'You must supply a new password', 'data'=>''), 200); } - $newPassword = $app->request()->put('password'); + $newPassword = $params['password']; - if(ctype_digit($id)) - $account = $dms->getUser($id); + if(ctype_digit($args['id'])) + $account = $dms->getUser($args['id']); else { - $account = $dms->getUserByLogin($id); + $account = $dms->getUserByLogin($args['id']); } /** * User not found */ if (!$account) { - $app->response()->status(404); + return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>'User not found.'), 404); return; } $operation = $account->setPwd($newPassword); if (!$operation){ - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'', 'data'=>'Could not change password.')); - return; + return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>'Could not change password.'), 404); } - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>'')); - - return; + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); } /* }}} */ -function getUserById($id) { /* {{{ */ - global $app, $dms, $userobj; - checkIfAdmin(); - if(ctype_digit($id)) - $account = $dms->getUser($id); +function getUserById($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + $check = checkIfAdmin($request, $response); + if($check !== true) + return $check; + if(ctype_digit($args['id'])) + $account = $dms->getUser($args['id']); else { - $account = $dms->getUserByLogin($id); + $account = $dms->getUserByLogin($args['id']); } if($account) { $data = __getUserData($account); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$data)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); } else { - $app->response()->status(404); + return $response->withStatus(404); } } /* }}} */ -function setDisabledUser($id) { /* {{{ */ - global $app, $dms, $userobj; - checkIfAdmin(); - if ($app->request()->put('disable') == null) { - $app->response()->status(400); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'You must supply a disabled state', 'data'=>'')); - return; +function setDisabledUser($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + $check = checkIfAdmin($request, $response); + if($check !== true) + return $check; + $params = $request->getParsedBody(); + if (!isset($params['disable'])) { + return $response->withJson(array('success'=>false, 'message'=>'You must supply a disabled state', 'data'=>''), 400); } $isDisabled = false; - $status = $app->request()->put('disable'); + $status = $params['disable']; if ($status == 'true' || $status == '1') { $isDisabled = true; } - if(ctype_digit($id)) - $account = $dms->getUser($id); + if(ctype_digit($args['id'])) + $account = $dms->getUser($args['id']); else { - $account = $dms->getUserByLogin($id); + $account = $dms->getUserByLogin($args['id']); } if($account) { $account->setDisabled($isDisabled); $data = __getUserData($account); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$data)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); } else { - $app->response()->status(404); + return $response->withStatus(404); } } /* }}} */ -function createGroup() { /* {{{ */ - global $app, $dms, $userobj; - checkIfAdmin(); - $groupName = $app->request()->post('name'); - $comment = $app->request()->post('comment'); +function getGroups($request, $response) { /* {{{ */ + global $dms, $userobj; + + $check = checkIfAdmin($request, $response); + if($check !== true) + return $check; + + $groups = $dms->getAllGroups(); + $data = []; + foreach($groups as $u) + $data[] = __getGroupData($u); + + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); +} /* }}} */ + +function createGroup($request, $response) { /* {{{ */ + global $dms, $userobj; + $check = checkIfAdmin($request, $response); + if($check !== true) + return $check; + $params = $request->getParsedBody(); + $groupName = $params['name']; + $comment = $params['comment']; $newGroup = $dms->addGroup($groupName, $comment); if ($newGroup === false) { - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Group could not be created, maybe it already exists', 'data'=>'')); - return; + return $response->withJson(array('success'=>false, 'message'=>'Group could not be created, maybe it already exists', 'data'=>''), 500); } $result = array('id'=>(int)$newGroup->getID()); - $app->response()->status(201); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$result)); - return; + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$result), 201); } /* }}} */ -function getGroup($id) { /* {{{ */ - global $app, $dms, $userobj; - checkIfAdmin(); - if(ctype_digit($id)) - $group = $dms->getGroup($id); +function getGroup($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + $check = checkIfAdmin($request, $response); + if($check !== true) + return $check; + if(ctype_digit($args['id'])) + $group = $dms->getGroup($args['id']); else { - $group = $dms->getGroupByName($id); + $group = $dms->getGroupByName($args['id']); } if($group) { $data = __getGroupData($group); @@ -1566,30 +1610,29 @@ function getGroup($id) { /* {{{ */ foreach ($group->getUsers() as $user) { $data['users'][] = array('id' => (int)$user->getID(), 'login' => $user->getLogin()); } - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$data)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); } else { - $app->response()->status(404); + return $response->withStatus(404); } } /* }}} */ -function changeGroupMembership($id, $operationType) { /* {{{ */ - global $app, $dms, $userobj; - checkIfAdmin(); +function changeGroupMembership($request, $response, $args, $operationType) { /* {{{ */ + global $dms, $userobj; + $check = checkIfAdmin($request, $response); + if($check !== true) + return $check; - if(ctype_digit($id)) - $group = $dms->getGroup($id); + if(ctype_digit($args['id'])) + $group = $dms->getGroup($args['id']); else { - $group = $dms->getGroupByName($id); + $group = $dms->getGroupByName($args['id']); } - if ($app->request()->put('userid') == null) - { - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Please PUT the userid', 'data'=>'')); - return; + $params = $request->getParsedBody(); + if (empty($params['userid'])) { + return $response->withJson(array('success'=>false, 'message'=>'Missing userid', 'data'=>''), 200); } - $userId = $app->request()->put('userid'); + $userId = $params['userid']; if(ctype_digit($userId)) $user = $dms->getUser($userId); else { @@ -1597,7 +1640,7 @@ function changeGroupMembership($id, $operationType) { /* {{{ */ } if (!($group && $user)) { - $app->response()->status(404); + return $response->withStatus(404); } $operationResult = false; @@ -1613,15 +1656,12 @@ function changeGroupMembership($id, $operationType) { /* {{{ */ if ($operationResult === false) { - $app->response()->header('Content-Type', 'application/json'); $message = 'Could not add user to the group.'; if ($operationType == 'remove') { $message = 'Could not remove user from group.'; } - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Something went wrong. ' . $message, 'data'=>'')); - return; + return $response->withJson(array('success'=>false, 'message'=>'Something went wrong. ' . $message, 'data'=>''), 200); } $data = __getGroupData($group); @@ -1629,39 +1669,39 @@ function changeGroupMembership($id, $operationType) { /* {{{ */ foreach ($group->getUsers() as $userObj) { $data['users'][] = array('id' => (int)$userObj->getID(), 'login' => $userObj->getLogin()); } - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$data)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); } /* }}} */ -function addUserToGroup($id) { /* {{{ */ - changeGroupMembership($id, 'add'); +function addUserToGroup($request, $response, $args) { /* {{{ */ + return changeGroupMembership($request, $response, $args, 'add'); } /* }}} */ -function removeUserFromGroup($id) { /* {{{ */ - changeGroupMembership($id, 'remove'); +function removeUserFromGroup($request, $response, $args) { /* {{{ */ + return changeGroupMembership($request, $response, $args, 'remove'); } /* }}} */ -function setFolderInheritsAccess($id) { /* {{{ */ - global $app, $dms, $userobj; - checkIfAdmin(); - if ($app->request()->put('enable') == null) +function setFolderInheritsAccess($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + $check = checkIfAdmin($request, $response); + if($check !== true) + return $check; + $params = $request->getParsedBody(); + if (empty($params['enable'])) { - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'You must supply an "enable" value', 'data'=>'')); - return; + return $response->withJson(array('success'=>false, 'message'=>'You must supply an "enable" value', 'data'=>''), 200); } $inherit = false; - $status = $app->request()->put('enable'); + $status = $params['enable']; if ($status == 'true' || $status == '1') { $inherit = true; } - if(ctype_digit($id)) - $folder = $dms->getFolder($id); + if(ctype_digit($args['id'])) + $folder = $dms->getFolder($args['id']); else { - $folder = $dms->getFolderByName($id); + $folder = $dms->getFolderByName($args['id']); } if($folder) { @@ -1671,61 +1711,58 @@ function setFolderInheritsAccess($id) { /* {{{ */ // reread from db $folder = $dms->getFolder($folderId); $success = ($folder->inheritsAccess() == $inherit); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>$success, 'message'=>'', 'data'=>$data)); + return $response->withJson(array('success'=>$success, 'message'=>'', 'data'=>$data), 200); } else { - $app->response()->status(404); + return $response->withStatus(404); } } /* }}} */ -function addUserAccessToFolder($id) { /* {{{ */ - changeFolderAccess($id, 'add', 'user'); +function addUserAccessToFolder($request, $response, $args) { /* {{{ */ + return changeFolderAccess($request, $response, $args, 'add', 'user'); } /* }}} */ -function addGroupAccessToFolder($id) { /* {{{ */ - changeFolderAccess($id, 'add', 'group'); +function addGroupAccessToFolder($request, $response, $args) { /* {{{ */ + return changeFolderAccess($request, $response, $args, 'add', 'group'); } /* }}} */ -function removeUserAccessFromFolder($id) { /* {{{ */ - changeFolderAccess($id, 'remove', 'user'); +function removeUserAccessFromFolder($request, $response, $args) { /* {{{ */ + return changeFolderAccess($request, $response, $args, 'remove', 'user'); } /* }}} */ -function removeGroupAccessFromFolder($id) { /* {{{ */ - changeFolderAccess($id, 'remove', 'group'); +function removeGroupAccessFromFolder($request, $response, $args) { /* {{{ */ + return changeFolderAccess($request, $response, $args, 'remove', 'group'); } /* }}} */ -function changeFolderAccess($id, $operationType, $userOrGroup) { /* {{{ */ - global $app, $dms, $userobj; - checkIfAdmin(); +function changeFolderAccess($request, $response, $args, $operationType, $userOrGroup) { /* {{{ */ + global $dms, $userobj; + $check = checkIfAdmin($request, $response); + if($check !== true) + return $check; - if(ctype_digit($id)) - $folder = $dms->getfolder($id); + if(ctype_digit($args['id'])) + $folder = $dms->getfolder($args['id']); else { - $folder = $dms->getfolderByName($id); + $folder = $dms->getfolderByName($args['id']); } if (!$folder) { - $app->response()->status(404); - return; + return $response->withStatus(404); } - $userOrGroupIdInput = $app->request()->put('id'); + $params = $request->getParsedBody(); + $userOrGroupIdInput = $params['id']; if ($operationType == 'add') { - if ($app->request()->put('id') == null) + if ($params['id'] == null) { - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Please PUT the user or group Id', 'data'=>'')); - return; + return $response->withJson(array('success'=>false, 'message'=>'Please PUT the user or group Id', 'data'=>''), 200); } - if ($app->request()->put('mode') == null) + if ($params['mode'] == null) { - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Please PUT the access mode', 'data'=>'')); - return; + return $response->withJson(array('success'=>false, 'message'=>'Please PUT the access mode', 'data'=>''), 200); } - $modeInput = $app->request()->put('mode'); + $modeInput = $params['mode']; $mode = M_NONE; if ($modeInput == 'read') @@ -1761,8 +1798,7 @@ function changeFolderAccess($id, $operationType, $userOrGroup) { /* {{{ */ $userOrGroupObj = $dms->getGroup($userOrGroupIdInput); } if (!$userOrGroupObj) { - $app->response()->status(404); - return; + return $response->withStatus(404); } $userOrGroupId = $userOrGroupObj->getId(); @@ -1788,106 +1824,86 @@ function changeFolderAccess($id, $operationType, $userOrGroup) { /* {{{ */ if ($operationResult === false) { - $app->response()->header('Content-Type', 'application/json'); $message = 'Could not add user/group access to this folder.'; if ($operationType == 'remove') { $message = 'Could not remove user/group access from this folder.'; } - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Something went wrong. ' . $message, 'data'=>'')); - return; + return $response->withJson(array('success'=>false, 'message'=>'Something went wrong. ' . $message, 'data'=>''), 200); } $data = array(); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$data)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); } /* }}} */ -function getCategories() { /* {{{ */ - global $app, $dms, $userobj; +function getCategories($request, $response) { /* {{{ */ + global $dms, $userobj; if(false === ($categories = $dms->getDocumentCategories())) { - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Could not get categories', 'data'=>null)); - return; + return $response->withJson(array('success'=>false, 'message'=>'Could not get categories', 'data'=>null), 500); } $data = []; foreach($categories as $category) $data[] = ['id' => (int)$category->getId(), 'name' => $category->getName()]; - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$data)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); } /* }}} */ -function getCategory($id) { /* {{{ */ - global $app, $dms, $userobj; +function getCategory($request, $response, $args) { /* {{{ */ + global $dms, $userobj; - if(!ctype_digit($id)) { - $app->response()->status(400); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'No such category', 'data'=>'')); - return; + if(!ctype_digit($args['id'])) { + return $response->withJson(array('success'=>false, 'message'=>'No such category', 'data'=>''), 400); } - $category = $dms->getDocumentCategory($id); + $category = $dms->getDocumentCategory($args['id']); if($category) { $data = array(); $data['id'] = (int)$category->getId(); $data['name'] = $category->getName(); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$data)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); } else { - $app->response()->status(404); + return $response->withStatus(404); } } /* }}} */ -function createCategory() { /* {{{ */ - global $app, $dms, $userobj; - checkIfAdmin(); +function createCategory($request, $response) { /* {{{ */ + global $dms, $userobj; + $check = checkIfAdmin($request, $response); + if($check !== true) + return $check; - $category = $app->request()->params("category"); - if ($category == null) { - $app->response()->status(400); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Need a category.', 'data'=>'')); - return; + $params = $request->getParsedBody(); + if (empty($params['category'])) { + return $response->withJson(array('success'=>false, 'message'=>'Need a category.', 'data'=>''), 400); } - $catobj = $dms->getDocumentCategoryByName($category); + $catobj = $dms->getDocumentCategoryByName($params['category']); if($catobj) { - $app->response()->status(409); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Category already exists', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'Category already exists', 'data'=>''), 409); } else { - if($data = $dms->addDocumentCategory($category)) { - $app->response()->status(201); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>array('id'=>(int)$data->getID()))); + if($data = $dms->addDocumentCategory($params['category'])) { + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>array('id'=>(int)$data->getID())), 201); } else { - $app->response()->status(500); - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'Could not add category', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'Could not add category', 'data'=>''), 500); } } } /* }}} */ -function deleteCategory($id) { /* {{{ */ - global $app, $dms, $userobj; - checkIfAdmin(); +function deleteCategory($request, $response, $args) { /* {{{ */ + global $dms, $userobj; + $check = checkIfAdmin($request, $response); + if($check !== true) + return $check; - $app->response()->header('Content-Type', 'application/json'); - if($category = $dms->getDocumentCategory($id)) { + if($category = $dms->getDocumentCategory($args['id'])) { if($result = $category->remove()) { - echo json_encode(array('success'=>$result, 'message'=>'', 'data'=>'')); + return $response->withJson(array('success'=>$result, 'message'=>'', 'data'=>''), 200); } else { - $app->response()->status(500); - echo json_encode(array('success'=>$result, 'message'=>'Could not delete category', 'data'=>'')); + return $response->withJson(array('success'=>$result, 'message'=>'Could not delete category', 'data'=>''), 500); } } else { - $app->response()->status(404); - echo json_encode(array('success'=>false, 'message'=>'No such category', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'No such category', 'data'=>''), 404); } } /* }}} */ @@ -1896,54 +1912,48 @@ function deleteCategory($id) { /* {{{ */ * * @param $id The user name or numerical identifier */ -function changeCategoryName($id) { /* {{{ */ - global $app, $dms, $userobj; +function changeCategoryName($request, $response, $args) { /* {{{ */ + global $dms, $userobj; - checkIfAdmin(); + $check = checkIfAdmin($request, $response); + if($check !== true) + return $check; - if ($app->request()->put('name') == null) + $params = $request->getParsedBody(); + if (empty($params['name'])) { - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'You must supply a new name', 'data'=>'')); - return; + return $response->withJson(array('success'=>false, 'message'=>'You must supply a new name', 'data'=>''), 200); } - $newname = $app->request()->put('name'); + $newname = $params['name']; $category = null; - if(ctype_digit($id)) - $category = $dms->getDocumentCategory($id); + if(ctype_digit($args['id'])) + $category = $dms->getDocumentCategory($args['id']); /** * Category not found */ if (!$category) { - $app->response()->status(404); - return; + return $response->withStatus(404); } if (!$category->setName($newname)) { - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'', 'data'=>'Could not change name.')); - return; + return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>'Could not change name.'), 200); } - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>'')); - - return; + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); } /* }}} */ -function getAttributeDefinitions() { /* {{{ */ - global $app, $dms, $userobj; +function getAttributeDefinitions($request, $response) { /* {{{ */ + global $dms, $userobj; $attrdefs = $dms->getAllAttributeDefinitions(); $data = []; foreach($attrdefs as $attrdef) $data[] = ['id' => (int)$attrdef->getId(), 'name' => $attrdef->getName(), 'type'=>(int)$attrdef->getType(), 'objtype'=>(int)$attrdef->getObjType(), 'min'=>(int)$attrdef->getMinValues(), 'max'=>(int)$attrdef->getMaxValues(), 'multiple'=>$attrdef->getMultipleValues()?true:false, 'valueset'=>$attrdef->getValueSetAsArray()]; - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>$data)); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); } /* }}} */ /** @@ -1951,86 +1961,66 @@ function getAttributeDefinitions() { /* {{{ */ * * @param $id The user name or numerical identifier */ -function changeAttributeDefinitionName($id) { /* {{{ */ - global $app, $dms, $userobj; +function changeAttributeDefinitionName($request, $response, $args) { /* {{{ */ + global $dms, $userobj; - checkIfAdmin(); + $check = checkIfAdmin($request, $response); + if($check !== true) + return $check; - if ($app->request()->put('name') == null) - { - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'You must supply a new name', 'data'=>'')); - return; + $params = $request->getParsedBody(); + if ($params['name'] == null) { + return $response->withJson(array('success'=>false, 'message'=>'You must supply a new name', 'data'=>''), 200); } - $newname = $app->request()->put('name'); + $newname = $params['name']; $attrdef = null; - if(ctype_digit($id)) - $attrdef = $dms->getAttributeDefinition($id); + if(ctype_digit($args['id'])) + $attrdef = $dms->getAttributeDefinition($args['id']); /** * Category not found */ if (!$attrdef) { - $app->response()->status(404); - return; + return $response->withStatus(404); } if (!$attrdef->setName($newname)) { - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>false, 'message'=>'', 'data'=>'Could not change name.')); + return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>'Could not change name.'), 200); return; } - $app->response()->header('Content-Type', 'application/json'); - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>'')); - - return; + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); } /* }}} */ -function clearFolderAccessList($id) { /* {{{ */ - global $app, $dms, $userobj; - checkIfAdmin(); +function clearFolderAccessList($request, $response, $args) { /* {{{ */ + global $dms, $userobj; - if(ctype_digit($id)) - $folder = $dms->getFolder($id); + $check = checkIfAdmin($request, $response); + if($check !== true) + return $check; + + if(ctype_digit($args['id'])) + $folder = $dms->getFolder($args['id']); else { - $folder = $dms->getFolderByName($id); + $folder = $dms->getFolderByName($args['id']); } if (!$folder) { - $app->response()->status(404); - return; + return $response->withStatus(404); } - $app->response()->header('Content-Type', 'application/json'); if (!$folder->clearAccessList()) { - echo json_encode(array('success'=>false, 'message'=>'Something went wrong. Could not clear access list for this folder.', 'data'=>'')); + return $response->withJson(array('success'=>false, 'message'=>'Something went wrong. Could not clear access list for this folder.', 'data'=>''), 200); } - echo json_encode(array('success'=>true, 'message'=>'', 'data'=>'')); + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); } /* }}} */ -function echoData() { /* {{{ */ - global $app; - - echo $app->request->getBody(); +function echoData($request, $response) { /* {{{ */ + echo $request->getBody(); } /* }}} */ //$app = new Slim(array('mode'=>'development', '_session.handler'=>null)); -$app = new \Slim\Slim(array('mode'=>'production', '_session.handler'=>null)); - -$app->configureMode('production', function () use ($app) { - $app->config(array( - 'log.enable' => false, - 'debug' => false - )); -}); - -$app->configureMode('development', function () use ($app) { - $app->config(array( - 'log.enable' => true, - 'debug' => true - )); -}); +$app = new \Slim\App(); // use post for create operation // use get for retrieval operation @@ -2042,56 +2032,60 @@ $app->get('/account', 'getAccount'); $app->get('/search', 'doSearch'); $app->get('/searchbyattr', 'doSearchByAttr'); $app->get('/folder/', 'getFolder'); -$app->get('/folder/:id', 'getFolder'); -$app->post('/folder/:id/move/:folderid', 'moveFolder'); -$app->delete('/folder/:id', 'deleteFolder'); -$app->get('/folder/:id/children', 'getFolderChildren'); -$app->get('/folder/:id/parent', 'getFolderParent'); -$app->get('/folder/:id/path', 'getFolderPath'); -$app->get('/folder/:id/attributes', 'getFolderAttributes'); -$app->post('/folder/:id/createfolder', 'createFolder'); -$app->put('/folder/:id/document', 'uploadDocumentPut'); -$app->post('/folder/:id/document', 'uploadDocument'); -$app->get('/document/:id', 'getDocument'); -$app->post('/document/:id/attachment', 'uploadDocumentFile'); -$app->delete('/document/:id', 'deleteDocument'); -$app->post('/document/:id/move/:folderid', 'moveDocument'); -$app->get('/document/:id/content', 'getDocumentContent'); -$app->get('/document/:id/versions', 'getDocumentVersions'); -$app->get('/document/:id/version/:version', 'getDocumentVersion'); -$app->get('/document/:id/files', 'getDocumentFiles'); -$app->get('/document/:id/file/:fileid', 'getDocumentFile'); -$app->get('/document/:id/links', 'getDocumentLinks'); -$app->get('/document/:id/attributes', 'getDocumentAttributes'); -$app->get('/document/:id/preview/:version/:width', 'getDocumentPreview'); -$app->delete('/document/:id/categories', 'removeDocumentCategories'); -$app->delete('/document/:id/category/:categoryId', 'removeDocumentCategory'); +$app->get('/folder/{id}', 'getFolder'); +$app->post('/folder/{id}/move/{folderid}', 'moveFolder'); +$app->delete('/folder/{id}', 'deleteFolder'); +$app->get('/folder/{id}/children', 'getFolderChildren'); +$app->get('/folder/{id}/parent', 'getFolderParent'); +$app->get('/folder/{id}/path', 'getFolderPath'); +$app->get('/folder/{id}/attributes', 'getFolderAttributes'); +$app->post('/folder/{id}/createfolder', 'createFolder'); +$app->put('/folder/{id}/document', 'uploadDocumentPut'); +$app->post('/folder/{id}/document', 'uploadDocument'); +$app->get('/document/{id}', 'getDocument'); +$app->post('/document/{id}/attachment', 'uploadDocumentFile'); +$app->post('/document/{id}/update', 'updateDocument'); +$app->delete('/document/{id}', 'deleteDocument'); +$app->post('/document/{id}/move/{folderid}', 'moveDocument'); +$app->get('/document/{id}/content', 'getDocumentContent'); +$app->get('/document/{id}/versions', 'getDocumentVersions'); +$app->get('/document/{id}/version/{version}', 'getDocumentVersion'); +$app->put('/document/{id}/version/{version}', 'updateDocumentVersion'); +$app->get('/document/{id}/files', 'getDocumentFiles'); +$app->get('/document/{id}/file/{fileid}', 'getDocumentFile'); +$app->get('/document/{id}/links', 'getDocumentLinks'); +$app->post('/document/{id}/link/{documentid}', 'addDocumentLink'); +$app->get('/document/{id}/attributes', 'getDocumentAttributes'); +$app->get('/document/{id}/preview/{version}/{width}', 'getDocumentPreview'); +$app->delete('/document/{id}/categories', 'removeDocumentCategories'); +$app->delete('/document/{id}/category/{categoryId}', 'removeDocumentCategory'); $app->put('/account/fullname', 'setFullName'); $app->put('/account/email', 'setEmail'); $app->get('/account/documents/locked', 'getLockedDocuments'); $app->get('/users', 'getUsers'); -$app->delete('/users/:id', 'deleteUser'); +$app->delete('/users/{id}', 'deleteUser'); $app->post('/users', 'createUser'); -$app->get('/users/:id', 'getUserById'); -$app->put('/users/:id/disable', 'setDisabledUser'); -$app->put('/users/:id/password', 'changeUserPassword'); +$app->get('/users/{id}', 'getUserById'); +$app->put('/users/{id}/disable', 'setDisabledUser'); +$app->put('/users/{id}/password', 'changeUserPassword'); $app->post('/groups', 'createGroup'); -$app->get('/groups/:id', 'getGroup'); -$app->put('/groups/:id/addUser', 'addUserToGroup'); -$app->put('/groups/:id/removeUser', 'removeUserFromGroup'); -$app->put('/folder/:id/setInherit', 'setFolderInheritsAccess'); -$app->put('/folder/:id/access/group/add', 'addGroupAccessToFolder'); // -$app->put('/folder/:id/access/user/add', 'addUserAccessToFolder'); // -$app->put('/folder/:id/access/group/remove', 'removeGroupAccessFromFolder'); -$app->put('/folder/:id/access/user/remove', 'removeUserAccessFromFolder'); -$app->put('/folder/:id/access/clear', 'clearFolderAccessList'); +$app->get('/groups', 'getGroups'); +$app->get('/groups/{id}', 'getGroup'); +$app->put('/groups/{id}/addUser', 'addUserToGroup'); +$app->put('/groups/{id}/removeUser', 'removeUserFromGroup'); +$app->put('/folder/{id}/setInherit', 'setFolderInheritsAccess'); +$app->put('/folder/{id}/access/group/add', 'addGroupAccessToFolder'); // +$app->put('/folder/{id}/access/user/add', 'addUserAccessToFolder'); // +$app->put('/folder/{id}/access/group/remove', 'removeGroupAccessFromFolder'); +$app->put('/folder/{id}/access/user/remove', 'removeUserAccessFromFolder'); +$app->put('/folder/{id}/access/clear', 'clearFolderAccessList'); $app->get('/categories', 'getCategories'); -$app->get('/categories/:id', 'getCategory'); -$app->delete('/categories/:id', 'deleteCategory'); +$app->get('/categories/{id}', 'getCategory'); +$app->delete('/categories/{id}', 'deleteCategory'); $app->post('/categories', 'createCategory'); -$app->put('/categories/:id/name', 'changeCategoryName'); +$app->put('/categories/{id}/name', 'changeCategoryName'); $app->get('/attributedefinitions', 'getAttributeDefinitions'); -$app->put('/attributedefinitions/:id/name', 'changeAttributeDefinitionName'); +$app->put('/attributedefinitions/{id}/name', 'changeAttributeDefinitionName'); $app->any('/echo', 'echoData'); $app->run(); diff --git a/styles/bootstrap/application.js b/styles/bootstrap/application.js index 4c22dc38d..47599c115 100644 --- a/styles/bootstrap/application.js +++ b/styles/bootstrap/application.js @@ -847,7 +847,7 @@ $(document).ready(function() { /* {{{ */ attr_rel = $(e.srcElement).attr('rel'); if(typeof attr_rel == 'undefined') return; - $(e.target).parent().css('border', '2px dashed #0B85A1'); + $(e.target).parent().css('border', '1px dashed #0B85A1'); e.stopPropagation(); e.preventDefault(); }); @@ -869,7 +869,7 @@ $(document).ready(function() { /* {{{ */ attr_rel = $(e.target).attr('rel'); if(typeof attr_rel == 'undefined') return; - $(e.target).parent().css('border', '0px solid white'); + $(e.target).parent().css('border', '1px solid white'); target_type = attr_rel.split("_")[0]; target_id = attr_rel.split("_")[1]; var source_info = JSON.parse(e.originalEvent.dataTransfer.getData("text")); diff --git a/styles/bootstrap/cytoscape/LICENSE b/styles/bootstrap/cytoscape/LICENSE deleted file mode 100644 index 313c076b7..000000000 --- a/styles/bootstrap/cytoscape/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2016 The Cytoscape Consortium - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the “Software”), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/styles/bootstrap/cytoscape/cytoscape-grid-guide.js b/styles/bootstrap/cytoscape/cytoscape-grid-guide.js index 50946c510..5d9acc259 100644 --- a/styles/bootstrap/cytoscape/cytoscape-grid-guide.js +++ b/styles/bootstrap/cytoscape/cytoscape-grid-guide.js @@ -1,11 +1,1011 @@ -(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o=0; --s) { + var n = n_stack[s] + if(d_stack[s] <= 0) { + n_stack[s] = new RBNode(n._color, n.key, n.value, n_stack[s+1], n.right, n._count+1) + } else { + n_stack[s] = new RBNode(n._color, n.key, n.value, n.left, n_stack[s+1], n._count+1) + } + } + //Rebalance tree using rotations + //console.log("start insert", key, d_stack) + for(var s=n_stack.length-1; s>1; --s) { + var p = n_stack[s-1] + var n = n_stack[s] + if(p._color === BLACK || n._color === BLACK) { + break + } + var pp = n_stack[s-2] + if(pp.left === p) { + if(p.left === n) { + var y = pp.right + if(y && y._color === RED) { + //console.log("LLr") + p._color = BLACK + pp.right = repaint(BLACK, y) + pp._color = RED + s -= 1 + } else { + //console.log("LLb") + pp._color = RED + pp.left = p.right + p._color = BLACK + p.right = pp + n_stack[s-2] = p + n_stack[s-1] = n + recount(pp) + recount(p) + if(s >= 3) { + var ppp = n_stack[s-3] + if(ppp.left === pp) { + ppp.left = p + } else { + ppp.right = p + } + } + break + } + } else { + var y = pp.right + if(y && y._color === RED) { + //console.log("LRr") + p._color = BLACK + pp.right = repaint(BLACK, y) + pp._color = RED + s -= 1 + } else { + //console.log("LRb") + p.right = n.left + pp._color = RED + pp.left = n.right + n._color = BLACK + n.left = p + n.right = pp + n_stack[s-2] = n + n_stack[s-1] = p + recount(pp) + recount(p) + recount(n) + if(s >= 3) { + var ppp = n_stack[s-3] + if(ppp.left === pp) { + ppp.left = n + } else { + ppp.right = n + } + } + break + } + } + } else { + if(p.right === n) { + var y = pp.left + if(y && y._color === RED) { + //console.log("RRr", y.key) + p._color = BLACK + pp.left = repaint(BLACK, y) + pp._color = RED + s -= 1 + } else { + //console.log("RRb") + pp._color = RED + pp.right = p.left + p._color = BLACK + p.left = pp + n_stack[s-2] = p + n_stack[s-1] = n + recount(pp) + recount(p) + if(s >= 3) { + var ppp = n_stack[s-3] + if(ppp.right === pp) { + ppp.right = p + } else { + ppp.left = p + } + } + break + } + } else { + var y = pp.left + if(y && y._color === RED) { + //console.log("RLr") + p._color = BLACK + pp.left = repaint(BLACK, y) + pp._color = RED + s -= 1 + } else { + //console.log("RLb") + p.left = n.right + pp._color = RED + pp.right = n.left + n._color = BLACK + n.right = p + n.left = pp + n_stack[s-2] = n + n_stack[s-1] = p + recount(pp) + recount(p) + recount(n) + if(s >= 3) { + var ppp = n_stack[s-3] + if(ppp.right === pp) { + ppp.right = n + } else { + ppp.left = n + } + } + break + } + } + } + } + //Return new tree + n_stack[0]._color = BLACK + return new RedBlackTree(cmp, n_stack[0]) +} + + +//Visit all nodes inorder +function doVisitFull(visit, node) { + if(node.left) { + var v = doVisitFull(visit, node.left) + if(v) { return v } + } + var v = visit(node.key, node.value) + if(v) { return v } + if(node.right) { + return doVisitFull(visit, node.right) + } +} + +//Visit half nodes in order +function doVisitHalf(lo, compare, visit, node) { + var l = compare(lo, node.key) + if(l <= 0) { + if(node.left) { + var v = doVisitHalf(lo, compare, visit, node.left) + if(v) { return v } + } + var v = visit(node.key, node.value) + if(v) { return v } + } + if(node.right) { + return doVisitHalf(lo, compare, visit, node.right) + } +} + +//Visit all nodes within a range +function doVisit(lo, hi, compare, visit, node) { + var l = compare(lo, node.key) + var h = compare(hi, node.key) + var v + if(l <= 0) { + if(node.left) { + v = doVisit(lo, hi, compare, visit, node.left) + if(v) { return v } + } + if(h > 0) { + v = visit(node.key, node.value) + if(v) { return v } + } + } + if(h > 0 && node.right) { + return doVisit(lo, hi, compare, visit, node.right) + } +} + + +proto.forEach = function rbTreeForEach(visit, lo, hi) { + if(!this.root) { + return + } + switch(arguments.length) { + case 1: + return doVisitFull(visit, this.root) + break + + case 2: + return doVisitHalf(lo, this._compare, visit, this.root) + break + + case 3: + if(this._compare(lo, hi) >= 0) { + return + } + return doVisit(lo, hi, this._compare, visit, this.root) + break + } +} + +//First item in list +Object.defineProperty(proto, "begin", { + get: function() { + var stack = [] + var n = this.root + while(n) { + stack.push(n) + n = n.left + } + return new RedBlackTreeIterator(this, stack) + } +}) + +//Last item in list +Object.defineProperty(proto, "end", { + get: function() { + var stack = [] + var n = this.root + while(n) { + stack.push(n) + n = n.right + } + return new RedBlackTreeIterator(this, stack) + } +}) + +//Find the ith item in the tree +proto.at = function(idx) { + if(idx < 0) { + return new RedBlackTreeIterator(this, []) + } + var n = this.root + var stack = [] + while(true) { + stack.push(n) + if(n.left) { + if(idx < n.left._count) { + n = n.left + continue + } + idx -= n.left._count + } + if(!idx) { + return new RedBlackTreeIterator(this, stack) + } + idx -= 1 + if(n.right) { + if(idx >= n.right._count) { + break + } + n = n.right + } else { + break + } + } + return new RedBlackTreeIterator(this, []) +} + +proto.ge = function(key) { + var cmp = this._compare + var n = this.root + var stack = [] + var last_ptr = 0 + while(n) { + var d = cmp(key, n.key) + stack.push(n) + if(d <= 0) { + last_ptr = stack.length + } + if(d <= 0) { + n = n.left + } else { + n = n.right + } + } + stack.length = last_ptr + return new RedBlackTreeIterator(this, stack) +} + +proto.gt = function(key) { + var cmp = this._compare + var n = this.root + var stack = [] + var last_ptr = 0 + while(n) { + var d = cmp(key, n.key) + stack.push(n) + if(d < 0) { + last_ptr = stack.length + } + if(d < 0) { + n = n.left + } else { + n = n.right + } + } + stack.length = last_ptr + return new RedBlackTreeIterator(this, stack) +} + +proto.lt = function(key) { + var cmp = this._compare + var n = this.root + var stack = [] + var last_ptr = 0 + while(n) { + var d = cmp(key, n.key) + stack.push(n) + if(d > 0) { + last_ptr = stack.length + } + if(d <= 0) { + n = n.left + } else { + n = n.right + } + } + stack.length = last_ptr + return new RedBlackTreeIterator(this, stack) +} + +proto.le = function(key) { + var cmp = this._compare + var n = this.root + var stack = [] + var last_ptr = 0 + while(n) { + var d = cmp(key, n.key) + stack.push(n) + if(d >= 0) { + last_ptr = stack.length + } + if(d < 0) { + n = n.left + } else { + n = n.right + } + } + stack.length = last_ptr + return new RedBlackTreeIterator(this, stack) +} + +//Finds the item with key if it exists +proto.find = function(key) { + var cmp = this._compare + var n = this.root + var stack = [] + while(n) { + var d = cmp(key, n.key) + stack.push(n) + if(d === 0) { + return new RedBlackTreeIterator(this, stack) + } + if(d <= 0) { + n = n.left + } else { + n = n.right + } + } + return new RedBlackTreeIterator(this, []) +} + +//Removes item with key from tree +proto.remove = function(key) { + var iter = this.find(key) + if(iter) { + return iter.remove() + } + return this +} + +//Returns the item at `key` +proto.get = function(key) { + var cmp = this._compare + var n = this.root + while(n) { + var d = cmp(key, n.key) + if(d === 0) { + return n.value + } + if(d <= 0) { + n = n.left + } else { + n = n.right + } + } + return +} + +//Iterator for red black tree +function RedBlackTreeIterator(tree, stack) { + this.tree = tree + this._stack = stack +} + +var iproto = RedBlackTreeIterator.prototype + +//Test if iterator is valid +Object.defineProperty(iproto, "valid", { + get: function() { + return this._stack.length > 0 + } +}) + +//Node of the iterator +Object.defineProperty(iproto, "node", { + get: function() { + if(this._stack.length > 0) { + return this._stack[this._stack.length-1] + } + return null + }, + enumerable: true +}) + +//Makes a copy of an iterator +iproto.clone = function() { + return new RedBlackTreeIterator(this.tree, this._stack.slice()) +} + +//Swaps two nodes +function swapNode(n, v) { + n.key = v.key + n.value = v.value + n.left = v.left + n.right = v.right + n._color = v._color + n._count = v._count +} + +//Fix up a double black node in a tree +function fixDoubleBlack(stack) { + var n, p, s, z + for(var i=stack.length-1; i>=0; --i) { + n = stack[i] + if(i === 0) { + n._color = BLACK + return + } + //console.log("visit node:", n.key, i, stack[i].key, stack[i-1].key) + p = stack[i-1] + if(p.left === n) { + //console.log("left child") + s = p.right + if(s.right && s.right._color === RED) { + //console.log("case 1: right sibling child red") + s = p.right = cloneNode(s) + z = s.right = cloneNode(s.right) + p.right = s.left + s.left = p + s.right = z + s._color = p._color + n._color = BLACK + p._color = BLACK + z._color = BLACK + recount(p) + recount(s) + if(i > 1) { + var pp = stack[i-2] + if(pp.left === p) { + pp.left = s + } else { + pp.right = s + } + } + stack[i-1] = s + return + } else if(s.left && s.left._color === RED) { + //console.log("case 1: left sibling child red") + s = p.right = cloneNode(s) + z = s.left = cloneNode(s.left) + p.right = z.left + s.left = z.right + z.left = p + z.right = s + z._color = p._color + p._color = BLACK + s._color = BLACK + n._color = BLACK + recount(p) + recount(s) + recount(z) + if(i > 1) { + var pp = stack[i-2] + if(pp.left === p) { + pp.left = z + } else { + pp.right = z + } + } + stack[i-1] = z + return + } + if(s._color === BLACK) { + if(p._color === RED) { + //console.log("case 2: black sibling, red parent", p.right.value) + p._color = BLACK + p.right = repaint(RED, s) + return + } else { + //console.log("case 2: black sibling, black parent", p.right.value) + p.right = repaint(RED, s) + continue + } + } else { + //console.log("case 3: red sibling") + s = cloneNode(s) + p.right = s.left + s.left = p + s._color = p._color + p._color = RED + recount(p) + recount(s) + if(i > 1) { + var pp = stack[i-2] + if(pp.left === p) { + pp.left = s + } else { + pp.right = s + } + } + stack[i-1] = s + stack[i] = p + if(i+1 < stack.length) { + stack[i+1] = n + } else { + stack.push(n) + } + i = i+2 + } + } else { + //console.log("right child") + s = p.left + if(s.left && s.left._color === RED) { + //console.log("case 1: left sibling child red", p.value, p._color) + s = p.left = cloneNode(s) + z = s.left = cloneNode(s.left) + p.left = s.right + s.right = p + s.left = z + s._color = p._color + n._color = BLACK + p._color = BLACK + z._color = BLACK + recount(p) + recount(s) + if(i > 1) { + var pp = stack[i-2] + if(pp.right === p) { + pp.right = s + } else { + pp.left = s + } + } + stack[i-1] = s + return + } else if(s.right && s.right._color === RED) { + //console.log("case 1: right sibling child red") + s = p.left = cloneNode(s) + z = s.right = cloneNode(s.right) + p.left = z.right + s.right = z.left + z.right = p + z.left = s + z._color = p._color + p._color = BLACK + s._color = BLACK + n._color = BLACK + recount(p) + recount(s) + recount(z) + if(i > 1) { + var pp = stack[i-2] + if(pp.right === p) { + pp.right = z + } else { + pp.left = z + } + } + stack[i-1] = z + return + } + if(s._color === BLACK) { + if(p._color === RED) { + //console.log("case 2: black sibling, red parent") + p._color = BLACK + p.left = repaint(RED, s) + return + } else { + //console.log("case 2: black sibling, black parent") + p.left = repaint(RED, s) + continue + } + } else { + //console.log("case 3: red sibling") + s = cloneNode(s) + p.left = s.right + s.right = p + s._color = p._color + p._color = RED + recount(p) + recount(s) + if(i > 1) { + var pp = stack[i-2] + if(pp.right === p) { + pp.right = s + } else { + pp.left = s + } + } + stack[i-1] = s + stack[i] = p + if(i+1 < stack.length) { + stack[i+1] = n + } else { + stack.push(n) + } + i = i+2 + } + } + } +} + +//Removes item at iterator from tree +iproto.remove = function() { + var stack = this._stack + if(stack.length === 0) { + return this.tree + } + //First copy path to node + var cstack = new Array(stack.length) + var n = stack[stack.length-1] + cstack[cstack.length-1] = new RBNode(n._color, n.key, n.value, n.left, n.right, n._count) + for(var i=stack.length-2; i>=0; --i) { + var n = stack[i] + if(n.left === stack[i+1]) { + cstack[i] = new RBNode(n._color, n.key, n.value, cstack[i+1], n.right, n._count) + } else { + cstack[i] = new RBNode(n._color, n.key, n.value, n.left, cstack[i+1], n._count) + } + } + + //Get node + n = cstack[cstack.length-1] + //console.log("start remove: ", n.value) + + //If not leaf, then swap with previous node + if(n.left && n.right) { + //console.log("moving to leaf") + + //First walk to previous leaf + var split = cstack.length + n = n.left + while(n.right) { + cstack.push(n) + n = n.right + } + //Copy path to leaf + var v = cstack[split-1] + cstack.push(new RBNode(n._color, v.key, v.value, n.left, n.right, n._count)) + cstack[split-1].key = n.key + cstack[split-1].value = n.value + + //Fix up stack + for(var i=cstack.length-2; i>=split; --i) { + n = cstack[i] + cstack[i] = new RBNode(n._color, n.key, n.value, n.left, cstack[i+1], n._count) + } + cstack[split-1].left = cstack[split] + } + //console.log("stack=", cstack.map(function(v) { return v.value })) + + //Remove leaf node + n = cstack[cstack.length-1] + if(n._color === RED) { + //Easy case: removing red leaf + //console.log("RED leaf") + var p = cstack[cstack.length-2] + if(p.left === n) { + p.left = null + } else if(p.right === n) { + p.right = null + } + cstack.pop() + for(var i=0; i 0) { + return this._stack[this._stack.length-1].key + } + return + }, + enumerable: true +}) + +//Returns value +Object.defineProperty(iproto, "value", { + get: function() { + if(this._stack.length > 0) { + return this._stack[this._stack.length-1].value + } + return + }, + enumerable: true +}) + + +//Returns the position of this iterator in the sorted list +Object.defineProperty(iproto, "index", { + get: function() { + var idx = 0 + var stack = this._stack + if(stack.length === 0) { + var r = this.tree.root + if(r) { + return r._count + } + return 0 + } else if(stack[stack.length-1].left) { + idx = stack[stack.length-1].left._count + } + for(var s=stack.length-2; s>=0; --s) { + if(stack[s+1] === stack[s].right) { + ++idx + if(stack[s].left) { + idx += stack[s].left._count + } + } + } + return idx + }, + enumerable: true +}) + +//Advances iterator to next element in list +iproto.next = function() { + var stack = this._stack + if(stack.length === 0) { + return + } + var n = stack[stack.length-1] + if(n.right) { + n = n.right + while(n) { + stack.push(n) + n = n.left + } + } else { + stack.pop() + while(stack.length > 0 && stack[stack.length-1].right === n) { + n = stack[stack.length-1] + stack.pop() + } + } +} + +//Checks if iterator is at end of tree +Object.defineProperty(iproto, "hasNext", { + get: function() { + var stack = this._stack + if(stack.length === 0) { + return false + } + if(stack[stack.length-1].right) { + return true + } + for(var s=stack.length-1; s>0; --s) { + if(stack[s-1].left === stack[s]) { + return true + } + } + return false + } +}) + +//Update value +iproto.update = function(value) { + var stack = this._stack + if(stack.length === 0) { + throw new Error("Can't update empty node!") + } + var cstack = new Array(stack.length) + var n = stack[stack.length-1] + cstack[cstack.length-1] = new RBNode(n._color, n.key, value, n.left, n.right, n._count) + for(var i=stack.length-2; i>=0; --i) { + n = stack[i] + if(n.left === stack[i+1]) { + cstack[i] = new RBNode(n._color, n.key, n.value, cstack[i+1], n.right, n._count) + } else { + cstack[i] = new RBNode(n._color, n.key, n.value, n.left, cstack[i+1], n._count) + } + } + return new RedBlackTree(this.tree._compare, cstack[0]) +} + +//Moves iterator backward one element +iproto.prev = function() { + var stack = this._stack + if(stack.length === 0) { + return + } + var n = stack[stack.length-1] + if(n.left) { + n = n.left + while(n) { + stack.push(n) + n = n.right + } + } else { + stack.pop() + while(stack.length > 0 && stack[stack.length-1].left === n) { + n = stack[stack.length-1] + stack.pop() + } + } +} + +//Checks if iterator is at start of tree +Object.defineProperty(iproto, "hasPrev", { + get: function() { + var stack = this._stack + if(stack.length === 0) { + return false + } + if(stack[stack.length-1].left) { + return true + } + for(var s=stack.length-1; s>0; --s) { + if(stack[s-1].right === stack[s]) { + return true + } + } + return false + } +}) + +//Default comparison function +function defaultCompare(a, b) { + if(a < b) { + return -1 + } + if(a > b) { + return 1 + } + return 0 +} + +//Build a tree +function createRBTree(compare) { + return new RedBlackTree(compare || defaultCompare, null) +} +},{}],2:[function(require,module,exports){ +module.exports = function (cytoscape, cy, $, apiRegistered) { + + // Needed because parent nodes cannot be moved in Cytoscape.js < v3.2 function moveTopDown(node, dx, dy) { var nodes = node.union(node.descendants()); - nodes.positions(function (i, node) { + nodes.filter(":childless").positions(function (node, i) { + if(typeof node === "number") { + node = i; + } var pos = node.position(); return { x: pos.x + dx, @@ -19,7 +1019,11 @@ module.exports = function (cytoscape, $) { for (var i = 0; i < nodes.length; i++) { nodesMap[nodes[i].id()] = true; } - var roots = nodes.filter(function (i, ele) { + var roots = nodes.filter(function (ele, i) { + if(typeof ele === "number") { + ele = i; + } + var parent = ele.parent()[0]; while(parent != null){ if(nodesMap[parent.id()]){ @@ -34,50 +1038,58 @@ module.exports = function (cytoscape, $) { } - cytoscape( "collection", "align", function (horizontal, vertical, alignTo) { + // If extension api functions are not registed to cytoscape yet register them here. + // Note that ideally these functions should not be directly registered to core from cytoscape.js + // extensions + if ( !apiRegistered ) { - var eles = getTopMostNodes(this.nodes(":visible")); + cytoscape( "collection", "align", function (horizontal, vertical, alignTo) { - var modelNode = alignTo ? alignTo : eles[0]; + var eles = getTopMostNodes(this.nodes(":visible")); - eles = eles.not(modelNode); + var modelNode = alignTo ? alignTo : eles[0]; - horizontal = horizontal ? horizontal : "none"; - vertical = vertical ? vertical : "none"; + eles = eles.not(modelNode); + + horizontal = horizontal ? horizontal : "none"; + vertical = vertical ? vertical : "none"; - // 0 for center - var xFactor = 0; - var yFactor = 0; + // 0 for center + var xFactor = 0; + var yFactor = 0; - if (vertical == "left") - xFactor = -1; - else if (vertical == "right") - xFactor = 1; + if (vertical == "left") + xFactor = -1; + else if (vertical == "right") + xFactor = 1; - if (horizontal == "top") - yFactor = -1; - else if (horizontal == "bottom") - yFactor = 1; + if (horizontal == "top") + yFactor = -1; + else if (horizontal == "bottom") + yFactor = 1; - for (var i = 0; i < eles.length; i++) { - var node = eles[i]; - var oldPos = $.extend({}, node.position()); - var newPos = $.extend({}, node.position()); + for (var i = 0; i < eles.length; i++) { + var node = eles[i]; + var oldPos = $.extend({}, node.position()); + var newPos = $.extend({}, node.position()); - if (vertical != "none") - newPos.x = modelNode.position("x") + xFactor * (modelNode.width() - node.width()) / 2; + if (vertical != "none") + newPos.x = modelNode.position("x") + xFactor * (modelNode.outerWidth() - node.outerWidth()) / 2; - if (horizontal != "none") - newPos.y = modelNode.position("y") + yFactor * (modelNode.height() - node.height()) / 2; + if (horizontal != "none") + newPos.y = modelNode.position("y") + yFactor * (modelNode.outerHeight() - node.outerHeight()) / 2; - moveTopDown(node, newPos.x - oldPos.x, newPos.y - oldPos.y); - } + moveTopDown(node, newPos.x - oldPos.x, newPos.y - oldPos.y); + } + + return this; + }); + + } - return this; - }); if (cy.undoRedo) { function getNodePositions() { @@ -97,7 +1109,10 @@ module.exports = function (cytoscape, $) { function returnToPositions(nodesData) { var currentPositions = {}; - cy.nodes().positions(function (i, ele) { + cy.nodes().positions(function (ele, i) { + if(typeof ele === "number") { + ele = i; + } currentPositions[ele.id()] = { x: ele.position("x"), y: ele.position("y") @@ -112,7 +1127,7 @@ module.exports = function (cytoscape, $) { return currentPositions } - var ur = cy.undoRedo(); + var ur = cy.undoRedo(null, true); ur.action("align", function (args) { @@ -135,7 +1150,8 @@ module.exports = function (cytoscape, $) { }; -},{}],2:[function(require,module,exports){ + +},{}],3:[function(require,module,exports){ var debounce = (function(){ /** @@ -374,123 +1390,6 @@ var debounce = (function(){ })(); module.exports = debounce; -},{}],3:[function(require,module,exports){ -module.exports = function (cy, snap) { - - var discreteDrag = {}; - - var attachedNode; - var draggedNodes; - - var startPos; - var endPos; - - - discreteDrag.onTapStartNode = function (e) { - if (e.cyTarget.selected()) - draggedNodes = e.cy.$(":selected"); - else - draggedNodes = e.cyTarget; - - startPos = e.cyPosition; - - attachedNode = e.cyTarget; - attachedNode.lock(); - attachedNode.trigger("grab"); - cy.on("tapdrag", onTapDrag); - cy.on("tapend", onTapEndNode); - - }; - - var onTapEndNode = function (e) { - //attachedNode.trigger("free"); - cy.off("tapdrag", onTapDrag); - cy.off("tapend", onTapEndNode); - attachedNode.unlock(); - e.preventDefault(); - }; - - var getDist = function () { - return { - x: endPos.x - startPos.x, - y: endPos.y - startPos.y - } - }; - - function getTopMostNodes(nodes) { - var nodesMap = {}; - - for (var i = 0; i < nodes.length; i++) { - nodesMap[nodes[i].id()] = true; - } - - var roots = nodes.filter(function (i, ele) { - var parent = ele.parent()[0]; - while (parent != null) { - if (nodesMap[parent.id()]) { - return false; - } - parent = parent.parent()[0]; - } - return true; - }); - - return roots; - } - - var moveNodesTopDown = function (nodes, dx, dy) { - -/* - console.log(nodes.map(function (e) { - return e.id(); - })); - for (var i = 0; i < nodes.length; i++) { - var node = nodes[i]; - var pos = node.position(); - - if (!node.isParent()) { - node.position({ - x: pos.x + dx, - y: pos.y + dy - }); - console.log(node.id() + " " + dx + " " + dy); - } - - moveNodesTopDown(nodes.children(), dx, dy); - } -*/ - }; - - var onTapDrag = function (e) { - - var nodePos = attachedNode.position(); - endPos = e.cyPosition; - endPos = snap.snapPos(endPos); - var dist = getDist(); - if (dist.x != 0 || dist.y != 0) { - attachedNode.unlock(); - //var topMostNodes = getTopMostNodes(draggedNodes); - var nodes = draggedNodes.union(draggedNodes.descendants()); - - nodes.positions(function (i, node) { - var pos = node.position(); - return snap.snapPos({ - x: pos.x + dist.x, - y: pos.y + dist.y - }); - }); - - startPos = endPos; - attachedNode.lock(); - attachedNode.trigger("drag"); - } - - }; - - return discreteDrag; - - -}; },{}],4:[function(require,module,exports){ module.exports = function (opts, cy, $, debounce) { @@ -506,9 +1405,21 @@ module.exports = function (opts, cy, $, debounce) { var ctx = $canvas[ 0 ].getContext( '2d' ); $container.append( $canvas ); - var drawGrid = function() { - clearDrawing(); + var resetCanvas = function () { + $canvas + .attr('height', 0) + .attr('width', 0) + .css( { + 'position': 'absolute', + 'top': 0, + 'left': 0, + 'z-index': options.gridStackOrder + }); + }; + resetCanvas(); + + var drawGrid = function() { var zoom = cy.zoom(); var canvasWidth = $container.width(); var canvasHeight = $container.height(); @@ -517,46 +1428,33 @@ module.exports = function (opts, cy, $, debounce) { var initialValueX = pan.x%increment; var initialValueY = pan.y%increment; - ctx.strokeStyle = options.strokeStyle; + ctx.strokeStyle = options.gridColor; ctx.lineWidth = options.lineWidth; - if(options.zoomDash) { - var zoomedDash = options.lineDash.slice(); + var data = '\t\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n'; - for(var i = 0; i < zoomedDash.length; i++) { - zoomedDash[ i ] = options.lineDash[ i ]*zoom; - } - ctx.setLineDash( zoomedDash ); - } else { - ctx.setLineDash( options.lineDash ); - } - - if(options.panGrid) { - ctx.lineDashOffset = -pan.y; - } else { - ctx.lineDashOffset = 0; - } - - for(var i = initialValueX; i < canvasWidth; i += increment) { - ctx.beginPath(); - ctx.moveTo( i, 0 ); - ctx.lineTo( i, canvasHeight ); - ctx.stroke(); - } - - if(options.panGrid) { - ctx.lineDashOffset = -pan.x; - } else { - ctx.lineDashOffset = 0; - } - - for(var i = initialValueY; i < canvasHeight; i += increment) { - ctx.beginPath(); - ctx.moveTo( 0, i ); - ctx.lineTo( canvasWidth, i ); - ctx.stroke(); - } + var img = new Image(); + data = encodeURIComponent(data); + + img.onload = function () { + clearDrawing(); + ctx.drawImage(img, 0, 0); + }; + + img.src = "data:image/svg+xml," + data; }; + var clearDrawing = function() { var width = $container.width(); var height = $container.height(); @@ -597,483 +1495,1417 @@ module.exports = function (opts, cy, $, debounce) { return { initCanvas: resizeCanvas, resizeCanvas: resizeCanvas, + resetCanvas: resetCanvas, clearCanvas: clearDrawing, drawGrid: drawGrid, changeOptions: changeOptions, sizeCanvas: drawGrid }; }; + },{}],5:[function(require,module,exports){ -module.exports = function (cy, snap, resize, discreteDrag, drawGrid, guidelines, parentPadding, $) { +module.exports = function (cy, snap, resize, snapToGridDuringDrag, drawGrid, guidelines, parentPadding, $, opts) { - var feature = function (func) { - return function (enable) { - func(enable); - }; - }; + var feature = function (func) { + return function (enable) { + func(enable); + }; + }; - var controller = { - discreteDrag: new feature(setDiscreteDrag), - resize: new feature(setResize), - snapToGrid: new feature(setSnapToGrid), - drawGrid: new feature(setDrawGrid), - guidelines: new feature(setGuidelines), - parentPadding: new feature(setParentPadding) - }; + var controller = { + snapToGridDuringDrag: new feature(setDiscreteDrag), + resize: new feature(setResize), + snapToGridOnRelease: new feature(setSnapToGrid), + drawGrid: new feature(setDrawGrid), + guidelines: new feature(setGuidelines), + parentPadding: new feature(setParentPadding) + }; - function applyToCyTarget(func, allowParent) { - return function (e) { - if (!e.cyTarget.is(":parent") || allowParent) - func(e.cyTarget); - } - } + function applyToCyTarget(func, allowParent) { + return function (e) { + var cyTarget = e.target || e.cyTarget; + if (!cyTarget.is(":parent") || allowParent) + func(cyTarget); + } + } - function applyToActiveNodes(func, allowParent) { - return function (e) { - if (!e.cyTarget.is(":parent") || allowParent) - if (e.cyTarget.selected()) - func(e.cyTarget, e.cy.$(":selected")); - else - func(e.cyTarget, e.cyTarget); - } - } - - function applyToAllNodesButNoParent(func) { - return function () { - cy.nodes().not(":parent").each(function (i, ele) { - func(ele); - }); - }; - } - function applyToAllNodes(func) { - return function () { - cy.nodes().each(function (i, ele) { - func(ele); - }); - }; - } - - function eventStatus(enable) { - return enable ? "on" : "off"; - } - - - // Discrete Drag - function setDiscreteDrag(enable) { - cy[eventStatus(enable)]("tapstart", "node", discreteDrag.onTapStartNode); - } - - // Resize - var resizeAllNodes = applyToAllNodesButNoParent(resize.resizeNode); - var resizeNode = applyToCyTarget(resize.resizeNode); - var recoverAllNodeDimensions = applyToAllNodesButNoParent(resize.recoverNodeDimensions); - - function setResize(enable) { - cy[eventStatus(enable)]("ready", resizeAllNodes); - // cy[eventStatus(enable)]("style", "node", resizeNode); - enable ? resizeAllNodes() : recoverAllNodeDimensions(); - } - - // Snap To Grid - var snapAllNodes = applyToAllNodes(snap.snapNodesTopDown); - var recoverSnapAllNodes = applyToAllNodes(snap.recoverSnapNode); - var snapCyTarget = applyToCyTarget(snap.snapNode, true); - - function setSnapToGrid(enable) { - cy[eventStatus(enable)]("add", "node", snapCyTarget); - cy[eventStatus(enable)]("ready", snapAllNodes); - - cy[eventStatus(enable)]("free", "node", snap.onFreeNode); - - if (enable) { - snapAllNodes(); - } else { - recoverSnapAllNodes(); - } - } - - // Draw Grid - var drawGridOnZoom = function () { - if (currentOptions.zoomDash) drawGrid.drawGrid() - }; - var drawGridOnPan = function () { - if (currentOptions.panGrid) drawGrid.drawGrid() - }; - - function setDrawGrid(enable) { - cy[eventStatus(enable)]('zoom', drawGridOnZoom); - cy[eventStatus(enable)]('pan', drawGridOnPan); - cy[eventStatus(enable)]('ready', drawGrid.resizeCanvas); - - if (enable) { - drawGrid.initCanvas(); - $(window).on('resize', drawGrid.resizeCanvas); - } else { - drawGrid.clearCanvas(); - $(window).off('resize', drawGrid.resizeCanvas); - } - } - - // Guidelines - - function setGuidelines(enable) { - cy[eventStatus(enable)]('zoom', guidelines.onZoom); - cy[eventStatus(enable)]('drag', "node", guidelines.onDragNode); - cy[eventStatus(enable)]('grab', "node", guidelines.onGrabNode); - cy[eventStatus(enable)]('free', "node", guidelines.onFreeNode); - - } - - // Parent Padding - var setAllParentPaddings = function (enable) { - parentPadding.setPaddingOfParent(cy.nodes(":parent"), enable); - }; - var enableParentPadding = function (node) { - parentPadding.setPaddingOfParent(node, true); - }; - - - function setParentPadding(enable) { - - setAllParentPaddings(enable); - - cy[eventStatus(enable)]('ready', setAllParentPaddings); - cy[eventStatus(enable)]("add", "node:parent", applyToCyTarget(enableParentPadding, true)); - } - - // Sync with options: Enables/disables changed via options. - var latestOptions = {}; - var currentOptions; - - var specialOpts = { - drawGrid: ["gridSpacing", "zoomDash", "panGrid", "gridStackOrder", "strokeStyle", "lineWidth", "lineDash"], - guidelines: ["gridSpacing", "guidelinesStackOrder", "guidelinesTolerance", "guidelinesStyle"], - resize: ["gridSpacing"], - parentPadding: ["gridSpacing", "parentSpacing"], - snapToGrid: ["gridSpacing"] - }; - - function syncWithOptions(options) { - currentOptions = $.extend(true, {}, options); - for (var key in options) - if (latestOptions[key] != options[key]) - if (controller.hasOwnProperty(key)) { - controller[key](options[key]); - } else { - for (var optsKey in specialOpts) { - var opts = specialOpts[optsKey]; - if (opts.indexOf(key) >= 0) { - if(optsKey == "drawGrid") { - drawGrid.changeOptions(options); - if (options.drawGrid) - drawGrid.resizeCanvas(); - } - - if (optsKey == "snapToGrid"){ - snap.changeOptions(options); - if (options.snapToGrid) - snapAllNodes(); - } - - if(optsKey == "guidelines") - guidelines.changeOptions(options); - - if (optsKey == "resize") { - resize.changeOptions(options); - if (options.resize) - resizeAllNodes(); - } - - if (optsKey == "parentPadding") - parentPadding.changeOptions(options); - - - } - } + function applyToAllNodesButNoParent(func) { + return function () { + cy.nodes().not(":parent").each(function (ele, i) { + if(typeof ele === "number") { + ele = i; } - latestOptions = $.extend(true, latestOptions, options); - } + + func(ele); + }); + }; + } + function applyToAllNodes(func) { + return function () { + cy.nodes().each(function (ele, i) { + if(typeof ele === "number") { + ele = i; + } + + func(ele); + }); + }; + } - return { - init: syncWithOptions, - syncWithOptions: syncWithOptions - }; + function eventStatus(enable) { + return enable ? "on" : "off"; + } + + + // Discrete Drag + function setDiscreteDrag(enable) { + cy[eventStatus(enable)]("tapstart", "node", snapToGridDuringDrag.onTapStartNode); + } + + // Resize + var resizeAllNodes = applyToAllNodesButNoParent(resize.resizeNode); + var resizeNode = applyToCyTarget(resize.resizeNode); + var recoverAllNodeDimensions = applyToAllNodesButNoParent(resize.recoverNodeDimensions); + + function setResize(enable) { + cy[eventStatus(enable)]("ready", resizeAllNodes); + // cy[eventStatus(enable)]("style", "node", resizeNode); + enable ? resizeAllNodes() : recoverAllNodeDimensions(); + } + + // Snap To Grid + var snapAllNodes = applyToAllNodes(snap.snapNodesTopDown); + var recoverSnapAllNodes = applyToAllNodes(snap.recoverSnapNode); + var snapCyTarget = applyToCyTarget(snap.snapNode, true); + + function setSnapToGrid(enable) { + cy[eventStatus(enable)]("add", "node", snapCyTarget); + cy[eventStatus(enable)]("ready", snapAllNodes); + + cy[eventStatus(enable)]("free", "node", snap.onFreeNode); + + if (enable) { + snapAllNodes(); + } else { + recoverSnapAllNodes(); + } + } + + // Draw Grid + var drawGridOnZoom = function () { + if (currentOptions.zoomDash) drawGrid.drawGrid() + }; + var drawGridOnPan = function () { + if (currentOptions.panGrid) drawGrid.drawGrid() + }; + + function setDrawGrid(enable) { + cy[eventStatus(enable)]('zoom', drawGridOnZoom); + cy[eventStatus(enable)]('pan', drawGridOnPan); + + if (enable) { + drawGrid.initCanvas(); + $(window).on('resize', drawGrid.resizeCanvas); + } else { + drawGrid.clearCanvas(); + drawGrid.resetCanvas(); + $(window).off('resize', drawGrid.resizeCanvas); + } + } + + // Guidelines + var activeTopMostNodes = null; + var guidelinesGrabHandler = function(e){ + var cyTarget = e.target || e.cyTarget; + var nodes = cyTarget.selected() ? e.cy.$(":selected") : cyTarget; + activeTopMostNodes = guidelines.getTopMostNodes(nodes.nodes()); + guidelines.lines.init(activeTopMostNodes); + } + var guidelinesDragHandler = function(e){ + if (this.id() == activeTopMostNodes.id()){ + guidelines.lines.update(activeTopMostNodes); + + if (currentOptions.snapToAlignmentLocationDuringDrag) + guidelines.lines.snapToAlignmentLocation(activeTopMostNodes); + } + }; + var guidelinesFreeHandler = function(e){ + if (currentOptions.snapToAlignmentLocationOnRelease) + guidelines.lines.snapToAlignmentLocation(activeTopMostNodes); + + guidelines.lines.destroy(); + activeTopMostNodes = null; + }; + var guidelinesWindowResizeHandler = function(e){ + guidelines.lines.resize(); + }; + var guidelinesTapHandler = function(e){ + guidelines.getMousePos(e); + }; + var guidelinesPanHandler = function(e){ + if (activeTopMostNodes){ + guidelines.setMousePos(cy.pan()); + guidelines.lines.init(activeTopMostNodes); + } + } + function setGuidelines(enable) { + if (enable){ + guidelines.resizeCanvas(); + cy.on("tapstart", "node", guidelinesTapHandler); + cy.on("grab", guidelinesGrabHandler); + cy.on("pan", guidelinesPanHandler); + cy.on("drag", "node", guidelinesDragHandler); + cy.on("free", guidelinesFreeHandler); + $(window).on("resize", guidelinesWindowResizeHandler); + } + else{ + cy.off("tapstart", "node", guidelinesTapHandler); + cy.off("grab", guidelinesGrabHandler); + cy.off("pan", guidelinesPanHandler); + cy.off("drag", "node", guidelinesDragHandler); + cy.off("free", guidelinesFreeHandler); + guidelines.resetCanvas(); + $(window).off("resize", guidelinesWindowResizeHandler); + } + } + + // Parent Padding + var setAllParentPaddings = function (enable) { + parentPadding.setPaddingOfParent(cy.nodes(":parent"), enable); + }; + var enableParentPadding = function (node) { + parentPadding.setPaddingOfParent(node, true); + }; + + + function setParentPadding(enable) { + + setAllParentPaddings(enable); + + cy[eventStatus(enable)]('ready', setAllParentPaddings); + cy[eventStatus(enable)]("add", "node:parent", applyToCyTarget(enableParentPadding, true)); + } + + // Sync with options: Enables/disables changed via options. + var latestOptions = {}; + var currentOptions; + + var specialOpts = { + drawGrid: ["gridSpacing", "zoomDash", "panGrid", "gridStackOrder", "gridColor", "lineWidth", "lineDash"], + guidelines: ["gridSpacing", "guidelinesStackOrder", "guidelinesTolerance", "guidelinesStyle", "distributionGuidelines", "range", "minDistRange", "geometricGuidelineRange"], + resize: ["gridSpacing"], + parentPadding: ["gridSpacing", "parentSpacing"], + snapToGridOnRelease: ["gridSpacing"] + }; + + function syncWithOptions(options) { + currentOptions = $.extend(true, {}, options); + options.guidelines = options.initPosAlignment || options.distributionGuidelines || options.geometricGuideline; + for (var key in options) + if (latestOptions[key] != options[key]) + if (controller.hasOwnProperty(key)) { + controller[key](options[key]); + } else { + for (var optsKey in specialOpts) { + var opts = specialOpts[optsKey]; + if (opts.indexOf(key) >= 0) { + if(optsKey == "drawGrid") { + drawGrid.changeOptions(options); + if (options.drawGrid) + drawGrid.resizeCanvas(); + } + + if (optsKey == "snapToGridOnRelease"){ + snap.changeOptions(options); + if (options.snapToGridOnRelease) + snapAllNodes(); + } + + if(optsKey == "guidelines") + guidelines.changeOptions(options); + + if (optsKey == "resize") { + resize.changeOptions(options); + if (options.resize) + resizeAllNodes(); + } + + if (optsKey == "parentPadding") + parentPadding.changeOptions(options); + + + } + } + } + latestOptions = $.extend(true, latestOptions, options); + } + + return { + init: syncWithOptions, + syncWithOptions: syncWithOptions + }; }; + },{}],6:[function(require,module,exports){ module.exports = function (opts, cy, $, debounce) { - var options = opts; - var changeOptions = function (opts) { - options = opts; - }; + var RBTree = require("functional-red-black-tree"); - function calcDistance(p1, p2) { - return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2)); - } - - function getExtraDim(node, paddingDim) { + var options = opts; - } + var changeOptions = function (opts) { + options = opts; - var dims = function (node) { + // RBTree always returns null, when low == high + // to avoid this: + if (options.guidelinesTolerance == 0) + options.guidelinesTolerance = 0.001; + }; - var pos = node.renderedPosition(); - var width = node.renderedWidth(); - var height = node.renderedHeight(); - var padding = { - left: Number(node.renderedStyle("padding-left").replace("px", "")), - right: Number(node.renderedStyle("padding-right").replace("px", "")), - top: Number(node.renderedStyle("padding-top").replace("px", "")), - bottom: Number(node.renderedStyle("padding-bottom").replace("px", "")) - }; + var getCyScratch = function () { + var sc = cy.scratch("_guidelines"); + if (!sc) + sc = cy.scratch("_guidelines", {}); - this.horizontal = { - center: pos.x, - left: pos.x - (padding.left + width / 2), - right: pos.x + (padding.right + width / 2) - }; + return sc; + }; - this.vertical = { - center: pos.y, - top: pos.y - (padding.top + height / 2), - bottom: pos.y + (padding.bottom + height / 2) - }; + /* Resize canvas */ + var resizeCanvas = debounce(function () { + clearDrawing(); + $canvas + .attr('height', $container.height()) + .attr('width', $container.width()) + .css({ + 'position': 'absolute', + 'top': 0, + 'left': 0, + 'z-index': options.guidelinesStackOrder + }); + setTimeout(function () { + var canvasBb = $canvas.offset(); + var containerBb = $container.offset(); - return this; - }; + $canvas + .attr('height', $container.height()) + .attr('width', $container.width()) + .css({ + 'top': -( canvasBb.top - containerBb.top ), + 'left': -( canvasBb.left - containerBb.left ) + }); + }, 0); + }, 250); - var $canvas = $(''); - var $container = $(cy.container()); - var ctx = $canvas[0].getContext('2d'); - $container.append($canvas); + /* Clear canvas */ + var clearDrawing = function () { + var width = $container.width(); + var height = $container.height(); + ctx.clearRect(0, 0, width, height); + }; - $canvas - .attr('height', $container.height()) - .attr('width', $container.width()) - .css({ - 'position': 'absolute', - 'top': 0, - 'left': 0, - 'z-index': options.guidelinesStackOrder - }); + /* Create a canvas */ + var $canvas = $(''); + var $container = $(cy.container()); + var ctx = $canvas[0].getContext('2d'); + $container.append($canvas); - var canvasBb = $canvas.offset(); - var containerBb = $container.offset(); + var resetCanvas = function () { + $canvas + .attr('height', 0) + .attr('width', 0) + .css( { + 'position': 'absolute', + 'top': 0, + 'left': 0, + 'z-index': options.gridStackOrder + }); + }; - $canvas - .attr( 'height', $container.height() ) - .attr( 'width', $container.width() ) - .css( { - 'top': -( canvasBb.top - containerBb.top ), - 'left': -( canvasBb.left - containerBb.left ) - } ); - var clearDrawing = function () { - var width = $container.width(); - var height = $container.height(); + resetCanvas(); - ctx.clearRect(0, 0, width, height); - }; + /* Global variables */ + var VTree = null; + var HTree = null; + var nodeInitPos; + var excludedNodes; + var lines = {}; + var panInitPos = {}; + var alignedLocations = {"h" : null, "v" : null}; + /** + * Get positions of sides of a node + * @param node : a node + * @return : object of positions + */ + lines.getDims = function (node) { + var pos = node.renderedPosition(); + var width = node.renderedWidth(); + var height = node.renderedHeight(); + var padding = { + left: Number(node.renderedStyle("padding-left").replace("px", "")), + right: Number(node.renderedStyle("padding-right").replace("px", "")), + top: Number(node.renderedStyle("padding-top").replace("px", "")), + bottom: Number(node.renderedStyle("padding-bottom").replace("px", "")) + }; - var pickedNode; + return { + horizontal: { + center: (pos.x), + left: Math.round(pos.x - (padding.left + width / 2)), + right: Math.round(pos.x + (padding.right + width / 2)) + }, + vertical: { + center: (pos.y), + top: Math.round(pos.y - (padding.top + height / 2)), + bottom: Math.round(pos.y + (padding.bottom + height / 2)) + } + }; + }; - function onGrabNode(e) { - pickedNode = e.cyTarget; - onDragNode(e); - } + /** + * Initialize trees and initial position of node + * @param activeNodes : top most active nodes + */ + lines.init = function (activeNodes) { + VTree = RBTree(); + HTree = RBTree(); + // TODO: seperate initialization of nodeInitPos + // not necessary to init trees when geometric and distribution alignments are disabled, + // but reference guideline is enables + if (!nodeInitPos){ + panInitPos.x = cy.pan("x"); panInitPos.y = cy.pan("y"); + nodeInitPos = activeNodes.renderedPosition(); + } - var onDragNode = debounce(function(e) { - if (pickedNode) { - var node = pickedNode; - - var mainDims = new dims(node); - - var cy = e.cy; - var nearests = { - horizontal: { - distance: Number.MAX_VALUE - }, - vertical: { - distance: Number.MAX_VALUE - } - }; - - cy.nodes(":visible").not(node.ancestors()).not(node.descendants()).not(node).each(function (i, ele) { - var nodeDims = new dims(ele); - - - for (var dim in mainDims) { - var mainDim = mainDims[dim]; - var nodeDim = nodeDims[dim]; - var otherDim = dim == "horizontal" ? "y" : "x"; - var eitherDim = otherDim == "x" ? "y" : "x"; - for (var key in mainDim) { - for (var key2 in nodeDim) { - if (Math.abs(mainDim[key] - nodeDim[key2]) < options.guidelinesTolerance) { - var distance = calcDistance(node.renderedPosition(), ele.renderedPosition()); - if (nearests[dim].distance > distance) { - - nearests[dim] = { - to: ele.id(), - toPos: {}, - from: node.id(), - fromPos: {}, - distance: distance - }; - nearests[dim].fromPos[eitherDim] = mainDim[key]; - nearests[dim].fromPos[otherDim] = node.renderedPosition(otherDim); - nearests[dim].toPos[eitherDim] = nodeDim[key2]; - nearests[dim].toPos[otherDim] = ele.renderedPosition(otherDim); - } - } - // console.log(key + " of " + node.id() + " -> " + key2 + " of " + ele.id()) - } - } - } - }); - - clearDrawing(); - for (var key in nearests) { - var item = nearests[key]; - if (item.from) { - ctx.beginPath(); - ctx.moveTo(item.fromPos.x, item.fromPos.y); - ctx.lineTo(item.toPos.x, item.toPos.y); - - ctx.setLineDash(options.guidelinesStyle.lineDash); - for (var styleKey in options.guidelinesStyle) - ctx[styleKey] = options.guidelinesStyle[styleKey]; - - ctx.stroke(); - } + var nodes = cy.nodes(":visible"); + excludedNodes = activeNodes.union(activeNodes.ancestors()); + excludedNodes = excludedNodes.union(activeNodes.descendants()); + nodes.not(excludedNodes).each(function (node, i) { + if(typeof node === "number") { + node = i; } + var dims = lines.getDims(node); - } - }, 0, true); + ["left", "center", "right"].forEach(function (val) { + var hKey = dims.horizontal[val]; + if (HTree.get(hKey)) + HTree.get(hKey).push(node); + else + HTree = HTree.insert(hKey, [node]); + }); - function onFreeNode() { - pickedNode = undefined; - clearDrawing(); - } + ["top", "center", "bottom"].forEach(function (val) { + var vKey = dims.vertical[val]; + if (VTree.get(vKey)) + VTree.get(vKey).push(node); + else + VTree = VTree.insert(vKey, [node]); + }); - return { - onDragNode: onDragNode, - onZoom: onDragNode, - onGrabNode: onGrabNode, - onFreeNode: onFreeNode, - changeOptions: changeOptions - } + }); + ctx.lineWidth=options.lineWidth; + lines.update(activeNodes); + }; + /* Destroy gobal variables */ + lines.destroy = function () { + lines.clear(); + VTree = null; HTree = null; + nodeInitPos = null; + mouseInitPos = {}; + alignedLocations = {"h" : null, "v" : null}; + if (nodeToAlign){ + nodeToAlign.unlock(); + nodeToAlign = undefined; + } + }; + + lines.clear = clearDrawing; + + /** + * Draw straight line + * @param from : initial position + * @param to : final position + * @param color : color of the line + * @param lineStyle : whether line is solid or dashed + */ + lines.drawLine = function (from, to, color, lineStyle) { + ctx.setLineDash(lineStyle); + ctx.beginPath(); + ctx.moveTo(from.x, from.y); + ctx.lineTo(to.x, to.y); + ctx.strokeStyle = color; + ctx.stroke(); + }; + + /** + * Draw an arrow + * @param position : position of the arrow + * @param type : type/directşon of the arrow + */ + lines.drawArrow = function(position, type){ + if (type == "right"){ + // right arrow + ctx.setLineDash([]); + ctx.beginPath(); + ctx.moveTo(position.x-5, position.y-5); + ctx.lineTo(position.x, position.y); + ctx.lineTo(position.x-5, position.y+5); + ctx.stroke(); + } + else if (type == "left"){ + // left arrow + ctx.setLineDash([]); + ctx.beginPath(); + ctx.moveTo(position.x+5, position.y-5); + ctx.lineTo(position.x, position.y); + ctx.lineTo(position.x+5, position.y+5); + ctx.stroke(); + } + else if (type == "top"){ + // up arrow + ctx.setLineDash([]); + ctx.beginPath(); + ctx.moveTo(position.x-5, position.y+5); + ctx.lineTo(position.x, position.y); + ctx.lineTo(position.x+5, position.y+5); + ctx.stroke(); + } + else if (type == "bottom"){ + // down arrow + ctx.setLineDash([]); + ctx.beginPath(); + ctx.moveTo(position.x-5, position.y-5); + ctx.lineTo(position.x, position.y); + ctx.lineTo(position.x+5, position.y-5); + ctx.stroke(); + } + + } + + /** + * Draw a cross - x + * @param position : position of the cross + */ + lines.drawCross = function(position){ + ctx.setLineDash([]); + ctx.beginPath(); + ctx.moveTo(position.x - 5, position.y + 5); + ctx.lineTo(position.x + 5, position.y - 5); + ctx.moveTo(position.x - 5, position.y - 5); + ctx.lineTo(position.x + 5, position.y + 5); + ctx.stroke(); + }; + + /** + * Calculate the amount of offset for distribution guidelines + * @param nodes - list of nodes + * @param type - horizontal or vertical + */ + calculateOffset = function(nodes, type){ + var minNode = nodes[0], min = lines.getDims(minNode)[type]["center"]; + var maxNode = nodes[0], max = lines.getDims(maxNode)[type]["center"]; + + for (var i = 0; i < nodes.length; i++){ + var node = nodes[i]; + if (lines.getDims(node)[type]["center"] < min){ + min = lines.getDims(node)[type]["center"]; minNode = node; + } + if (lines.getDims(node)[type]["center"] > max){ + max = lines.getDims(node)[type]["center"]; maxNode = node; + } + } + + if (type == "horizontal") + var offset = (min + max) / 2 < lines.getDims(nodes[1])[type]["center"] ? max + (0.5*maxNode.width() + options.guidelinesStyle.distGuidelineOffset)*cy.zoom() : min - (0.5*minNode.width() + options.guidelinesStyle.distGuidelineOffset)*cy.zoom(); + else + var offset = (min + max) / 2 < lines.getDims(nodes[1])[type]["center"] ? max + (0.5*maxNode.height() + options.guidelinesStyle.distGuidelineOffset)*cy.zoom() : min - (0.5*minNode.height() + options.guidelinesStyle.distGuidelineOffset)*cy.zoom(); + + return offset; + } + /** Guidelines for horizontally distributed alignment + * @param: node the node to be aligned + */ + lines.horizontalDistribution = function(node){ + // variables + var leftNode = null, rightNode = null; + var nodeDim = lines.getDims(node); + var Xcenter = nodeDim["horizontal"]["center"]; + var Ycenter = nodeDim["vertical"]["center"]; + // Find nodes in range and check if they align + HTree.forEach(function(key, nodes){ + + for (var i = 0; i < nodes.length; i++){ + var left = nodes[i]; + var leftDim = lines.getDims(left); + if (Math.abs(leftDim["vertical"]["center"] - nodeDim["vertical"]["center"]) < options.guidelinesStyle.range*cy.zoom()){ + if ((leftDim["horizontal"]["right"]) == key && + nodeDim["horizontal"]["left"] - leftDim["horizontal"]["right"] > options.guidelinesStyle.minDistRange){ + var ripo = Math.round(2*Xcenter)-key; + HTree.forEach(function($, rightNodes){ + for (var j = 0; j < rightNodes.length; j++){ + var right = rightNodes[j]; + if (Math.abs(lines.getDims(right)["vertical"]["center"] - Ycenter) < options.guidelinesStyle.range*cy.zoom()){ + if (Math.abs(ripo - lines.getDims(right)["horizontal"]["left"]) < 2*options.guidelinesTolerance){ + leftNode = left; rightNode = right; + } + } + } + }, ripo - options.guidelinesTolerance, ripo + options.guidelinesTolerance); + } + } + } + }, Xcenter - options.guidelinesStyle.range*cy.zoom(), Xcenter); + + // Draw the lines + if (leftNode){ + alignedLocations.hd = Xcenter - (lines.getDims(rightNode)["horizontal"]["left"] + lines.getDims(leftNode)["horizontal"]["right"]) / 2.0; + if (!options.geometricGuideline || alignedLocations.h == null || Math.abs(alignedLocations.h) > Math.abs(alignedLocations.hd)){ + alignedLocations.h = alignedLocations.hd; + } + var offset = calculateOffset([leftNode, node, rightNode], "vertical"); + + lines.drawLine({ + x: lines.getDims(leftNode)["horizontal"]["right"], + y: offset + }, { + x: nodeDim["horizontal"]["left"], + y: offset + }, options.guidelinesStyle.horizontalDistColor, options.guidelinesStyle.horizontalDistLine); + + lines.drawLine({ + x: lines.getDims(rightNode)["horizontal"]["left"], + y: offset + }, { + x: nodeDim["horizontal"]["right"], + y: offset + }, options.guidelinesStyle.horizontalDistColor, options.guidelinesStyle.horizontalDistLine); + + lines.drawLine({ + x: lines.getDims(leftNode)["horizontal"]["right"], + y: offset + }, { + x: lines.getDims(leftNode)["horizontal"]["right"], + y: lines.getDims(leftNode)["vertical"]["center"] + }, options.guidelinesStyle.horizontalDistColor, options.guidelinesStyle.horizontalDistLine); + + lines.drawLine({ + x: lines.getDims(rightNode)["horizontal"]["left"], + y: offset + }, { + x: lines.getDims(rightNode)["horizontal"]["left"], + y: lines.getDims(rightNode)["vertical"]["center"] + }, options.guidelinesStyle.horizontalDistColor, options.guidelinesStyle.horizontalDistLine); + + lines.drawLine({ + x: nodeDim["horizontal"]["left"], + y: offset + }, { + x: nodeDim["horizontal"]["left"], + y: Ycenter + }, options.guidelinesStyle.horizontalDistColor, options.guidelinesStyle.horizontalDistLine); + + lines.drawLine({ + x: nodeDim["horizontal"]["right"], + y: offset + }, { + x: nodeDim["horizontal"]["right"], + y: Ycenter + }, options.guidelinesStyle.horizontalDistColor, options.guidelinesStyle.horizontalDistLine); + + lines.drawArrow({ + x: lines.getDims(leftNode)["horizontal"]["right"], + y: offset}, "left"); + + lines.drawArrow({ + x: nodeDim["horizontal"]["left"], + y: offset}, "right"); + + lines.drawArrow({ + x: nodeDim["horizontal"]["right"], + y: offset}, "left"); + + lines.drawArrow({ + x: lines.getDims(rightNode)["horizontal"]["left"], + y: offset}, "right"); + + } + else{ + var state = lines.horizontalDistributionNext(node,"left" ); + + if (!state) + lines.horizontalDistributionNext(node,"right" ); + } + } + + /** Guidelines for horizontally distributed alignment + * @param: node the node to be aligned + */ + lines.verticalDistribution = function(node){ + // variables + var belowNode = null, aboveNode = null; + var nodeDim = lines.getDims(node); + var Xcenter = nodeDim["horizontal"]["center"]; + var Ycenter = nodeDim["vertical"]["center"]; + // Find nodes in range and check if they align + VTree.forEach(function(key, nodes){ + + for (var i = 0; i < nodes.length; i++){ + var below = nodes[i]; + var belowDim = lines.getDims(below); + if (Math.abs(belowDim["horizontal"]["center"] - nodeDim["horizontal"]["center"]) < options.guidelinesStyle.range*cy.zoom()){ + if (belowDim["vertical"]["bottom"] == key && + nodeDim["vertical"]["top"] - belowDim["vertical"]["bottom"] > options.guidelinesStyle.minDistRange){ + var abpo = Math.round((2*Ycenter)-key); + VTree.forEach(function($, aboveNodes){ + //if (aboveNodes){ + for (var j = 0; j < aboveNodes.length; j++){ + var above = aboveNodes[j]; + if (Math.abs(lines.getDims(above)["horizontal"]["center"] - Xcenter) < options.guidelinesStyle.range*cy.zoom()){ + if (Math.abs(abpo - lines.getDims(above)["vertical"]["top"]) < 2*options.guidelinesTolerance){ + belowNode = below; aboveNode = above; + } + } + } + //} + }, abpo - options.guidelinesTolerance, abpo + options.guidelinesTolerance); + } + } + } + }, Ycenter - options.guidelinesStyle.range*cy.zoom(), Ycenter); + + if (belowNode){ + alignedLocations.vd = Ycenter - (lines.getDims(belowNode)["vertical"]["bottom"] + lines.getDims(aboveNode)["vertical"]["top"]) / 2.0; + if (!options.geometricGuideline || alignedLocations.v == null || Math.abs(alignedLocations.v) > Math.abs(alignedLocations.vd)){ + alignedLocations.v = alignedLocations.vd; + } + var offset = calculateOffset([belowNode, node, aboveNode], "horizontal"); + lines.drawLine({ + y: lines.getDims(belowNode)["vertical"]["bottom"],//renderedPosition("x"), + x: offset + }, { + y: nodeDim["vertical"]["top"], + x: offset + }, options.guidelinesStyle.verticalDistColor, options.guidelinesStyle.verticalDistLine); + + lines.drawLine({ + y: lines.getDims(aboveNode)["vertical"]["top"],//renderedPosition("x"), + x: offset + }, { + y: nodeDim["vertical"]["bottom"], + x: offset + }, options.guidelinesStyle.verticalDistColor, options.guidelinesStyle.verticalDistLine); + + lines.drawLine({ + y: lines.getDims(belowNode)["vertical"]["bottom"],//renderedPosition("x"), + x: offset + }, { + y: lines.getDims(belowNode)["vertical"]["bottom"], + x: lines.getDims(belowNode)["horizontal"]["center"] + }, options.guidelinesStyle.verticalDistColor, options.guidelinesStyle.verticalDistLine); + + lines.drawLine({ + y: lines.getDims(aboveNode)["vertical"]["top"],//renderedPosition("x"), + x: offset + }, { + y: lines.getDims(aboveNode)["vertical"]["top"], + x: lines.getDims(aboveNode)["horizontal"]["center"] + }, options.guidelinesStyle.verticalDistColor, options.guidelinesStyle.verticalDistLine); + + lines.drawLine({ + y: nodeDim["vertical"]["bottom"],//renderedPosition("x"), + x: offset + }, { + y: nodeDim["vertical"]["bottom"],//renderedPosition("x"), + x: Xcenter + }, options.guidelinesStyle.verticalDistColor, options.guidelinesStyle.verticalDistLine); + + lines.drawLine({ + y: nodeDim["vertical"]["top"],//renderedPosition("x"), + x: offset + }, { + y: nodeDim["vertical"]["top"],//renderedPosition("x"), + x: Xcenter + }, options.guidelinesStyle.verticalDistColor, options.guidelinesStyle.verticalDistLine); + + lines.drawArrow({ + x: offset, + y: lines.getDims(belowNode)["vertical"]["bottom"]}, "top"); + + lines.drawArrow({ + x: offset, + y: nodeDim["vertical"]["top"]}, "bottom"); + + lines.drawArrow({ + x: offset, + y: lines.getDims(aboveNode)["vertical"]["top"]}, "bottom"); + + lines.drawArrow({ + x: offset, + y: nodeDim["vertical"]["bottom"]}, "top"); + } + else{ + var state = lines.verticalDistributionNext(node,"below" ); + + if (!state) + lines.verticalDistributionNext(node,"above" ); + } + } + + /** + * Find geometric alignment lines and draw them + * @param type: horizontal or vertical + * @param node: the node to be aligned + */ + lines.searchForLine = function (type, node) { + + // variables + var position, target, center, axis, otherAxis, Tree, closestKey; + var dims = lines.getDims(node)[type]; + var targetKey = Number.MAX_SAFE_INTEGER; + + // initialize Tree + if ( type == "horizontal"){ + Tree = HTree; + axis = "y"; + otherAxis = "x"; + alignedLocations.h = null; + } else{ + Tree = VTree; + axis = "x"; + otherAxis = "y"; + alignedLocations.v = null; + } + + center = node.renderedPosition(axis); + // check if node aligned in any dimension: + // {center, left, right} or {center, top, bottom} + for (var dimKey in dims) { + position = dims[dimKey]; + + // find the closest alignment in range of tolerance + Tree.forEach(function (exKey, nodes) { + for (var i = 0; i < nodes.length; i++){ + var n = nodes[i]; + if (options.centerToEdgeAlignment || (dimKey != "center" && n.renderedPosition(otherAxis) != exKey) || (dimKey == "center" && n.renderedPosition(otherAxis) == exKey)){ + var dif = Math.abs(center - n.renderedPosition(axis)); + if ( dif < targetKey && dif < options.guidelinesStyle.geometricGuidelineRange*cy.zoom()){ + target = n; + targetKey = dif; + closestKey = exKey; + } + } + } + }, position - Number(options.guidelinesTolerance), position + Number(options.guidelinesTolerance)); + + // if alignment found, draw lines and break + if (target) { + targetKey = lines.getDims(node)[type][dimKey]; + + // Draw horizontal or vertical alignment line + if (type == "horizontal") { + alignedLocations.h = targetKey - closestKey; + lines.drawLine({ + x: targetKey, + y: node.renderedPosition("y") + }, { + x: targetKey, + y: target.renderedPosition("y") + }, options.guidelinesStyle.strokeStyle, options.guidelinesStyle.lineDash); + } else { + alignedLocations.v = targetKey - closestKey; + lines.drawLine({ + x: node.renderedPosition("x"), + y: targetKey + }, { + x: target.renderedPosition("x"), + y: targetKey + }, options.guidelinesStyle.strokeStyle, options.guidelinesStyle.lineDash); + } + break; + } + } + }; + + lines.horizontalDistributionNext = function(node, type){ + + // variables + var leftNode = null, rightNode = null; + var nodeDim = lines.getDims(node); + var Xcenter = nodeDim["horizontal"]["center"]; + var Ycenter = nodeDim["vertical"]["center"]; + var side = "right", otherSide = "left"; + var lowerBound = Xcenter; + if (type == "left"){ + side = "left"; otherSide = "right"; + var lowerBound = Xcenter - options.guidelinesStyle.range*cy.zoom(); + } + + var compare = { + "left": function (x, y) { return y - x > options.guidelinesStyle.minDistRange}, + "right": function (x, y) { return x - y > options.guidelinesStyle.minDistRange} + } + + // Find nodes in range and check if they align + HTree.forEach(function(key, nodes){ + for (var i = 0; i < nodes.length; i++){ + var left = nodes[i]; + var leftDim = lines.getDims(left); + if (Math.abs(leftDim["vertical"]["center"] - nodeDim["vertical"]["center"]) < options.guidelinesStyle.range*cy.zoom()){ + if ((leftDim["horizontal"][otherSide]) == key && + compare[type](leftDim["horizontal"][otherSide], nodeDim["horizontal"][side])){ + var ll = leftDim["horizontal"][side]-(nodeDim["horizontal"][side] - key); + HTree.forEach(function($, rightNodes){ + for (var j = 0; j < rightNodes.length; j++){ + var right = rightNodes[j]; + if (Math.abs(lines.getDims(right)["vertical"]["center"] - Ycenter) < options.guidelinesStyle.range*cy.zoom()){ + if (Math.abs(ll - lines.getDims(right)["horizontal"][otherSide]) < 2*options.guidelinesTolerance){ + leftNode = left; rightNode = right; + } + } + } + }, ll - options.guidelinesTolerance, ll + options.guidelinesTolerance); + } + } + } + }, lowerBound, lowerBound + options.guidelinesStyle.range*cy.zoom()); + + // Draw the lines + if (leftNode){ + alignedLocations.hd =(lines.getDims(node)["horizontal"][side] - lines.getDims(leftNode)["horizontal"][otherSide]) - (lines.getDims(leftNode)["horizontal"][side] - lines.getDims(rightNode)["horizontal"][otherSide]); + if (!options.geometricGuideline || alignedLocations.h == null || Math.abs(alignedLocations.h) > Math.abs(alignedLocations.hd)){ + alignedLocations.h = alignedLocations.hd; + } + + lines.drawDH(node, leftNode, rightNode, type); + return true; + } + else if (!options.geometricGuideline){ + alignedLocations.h = null; + } + return false; + + } + + lines.drawDH = function(node, leftNode, rightNode, type){ + var Ycenter = lines.getDims(node)["vertical"]["center"]; + var side = "right", otherSide = "left"; + if (type == "left"){ + side = "left"; otherSide = "right"; + } + var offset = calculateOffset([leftNode, node, rightNode], "vertical"); + + lines.drawLine({ + x: lines.getDims(leftNode)["horizontal"][otherSide], + y: offset + }, { + x: lines.getDims(node)["horizontal"][side], + y: offset + }, options.guidelinesStyle.horizontalDistColor, options.guidelinesStyle.horizontalDistLine); + + lines.drawLine({ + x: lines.getDims(node)["horizontal"][side], + y: offset + }, { + x: lines.getDims(node)["horizontal"][side], + y: Ycenter,//lines.getDims(leftNode)["vertical"]["center"] + }, options.guidelinesStyle.horizontalDistColor, options.guidelinesStyle.horizontalDistLine); + + lines.drawLine({ + x: lines.getDims(rightNode)["horizontal"][otherSide], + y: offset + }, { + x: lines.getDims(leftNode)["horizontal"][side], + y: offset + }, options.guidelinesStyle.horizontalDistColor, options.guidelinesStyle.horizontalDistLine); + lines.drawLine({ + x: lines.getDims(rightNode)["horizontal"][otherSide], + y: offset + }, { + x: lines.getDims(rightNode)["horizontal"][otherSide], + y: lines.getDims(rightNode)["vertical"]["center"] + }, options.guidelinesStyle.horizontalDistColor, options.guidelinesStyle.horizontalDistLine); + + lines.drawLine({ + x: lines.getDims(leftNode)["horizontal"][otherSide], + y: offset + }, { + x: lines.getDims(leftNode)["horizontal"][otherSide], + y: lines.getDims(leftNode)["vertical"]["center"] + }, options.guidelinesStyle.horizontalDistColor, options.guidelinesStyle.horizontalDistLine); + + lines.drawLine({ + x: lines.getDims(leftNode)["horizontal"][side], + y: offset + }, { + x: lines.getDims(leftNode)["horizontal"][side], + y: lines.getDims(leftNode)["vertical"]["center"] + }, options.guidelinesStyle.horizontalDistColor, options.guidelinesStyle.horizontalDistLine); + + + lines.drawArrow({ + x: lines.getDims(node)["horizontal"][side], + y: offset}, otherSide); + + lines.drawArrow({ + x: lines.getDims(leftNode)["horizontal"][otherSide], + y: offset}, side); + + lines.drawArrow({ + x: lines.getDims(leftNode)["horizontal"][side], + y: offset}, otherSide); + + lines.drawArrow({ + x: lines.getDims(rightNode)["horizontal"][otherSide], + y: offset}, side); + + } + + lines.verticalDistributionNext = function(node, type){ + // variables + var belowNode = null, aboveNode = null; + var nodeDim = lines.getDims(node); + var Xcenter = nodeDim["horizontal"]["center"]; + var Ycenter = nodeDim["vertical"]["center"]; + var side = "top", otherSide = "bottom"; + var lowerBound = Ycenter - options.guidelinesStyle.range*cy.zoom(); + if (type == "above"){ + side = "bottom"; otherSide = "top"; + lowerBound = Ycenter; + } + + var compare = { + "below": function (x, y) { return y - x > options.guidelinesStyle.minDistRange}, + "above": function (x, y) { return x - y > options.guidelinesStyle.minDistRange} + } + // Find nodes in range and check if they align + VTree.forEach(function(key, nodes){ + for (var i = 0; i < nodes.length; i++){ + var below = nodes[i]; + var belowDim = lines.getDims(below); + if (Math.abs(belowDim["horizontal"]["center"] - nodeDim["horizontal"]["center"]) < options.guidelinesStyle.range*cy.zoom()){ + if (belowDim["vertical"][otherSide] == key && + compare[type](belowDim["vertical"][otherSide], nodeDim["vertical"][side])){ + var ll = belowDim["vertical"][side]-(nodeDim["vertical"][side]-key); + VTree.forEach(function($, aboveNodes){ + for (var j = 0; j < aboveNodes.length; j++){ + var above = aboveNodes[j]; + if (Math.abs(lines.getDims(above)["horizontal"]["center"] - Xcenter) < options.guidelinesStyle.range*cy.zoom()){ + if (Math.abs(ll - lines.getDims(above)["vertical"][otherSide]) < 2*options.guidelinesTolerance){ + belowNode = below; aboveNode = above; + } + } + } + }, ll - options.guidelinesTolerance, ll + options.guidelinesTolerance); + } + } + } + }, lowerBound, lowerBound+options.guidelinesStyle.range*cy.zoom()); + + if (belowNode){ + alignedLocations.vd =(lines.getDims(node)["vertical"][side] - lines.getDims(belowNode)["vertical"][otherSide]) - (lines.getDims(belowNode)["vertical"][side] - lines.getDims(aboveNode)["vertical"][otherSide]); + if (!options.geometricGuideline || alignedLocations.v == null || Math.abs(alignedLocations.v) > Math.abs(alignedLocations.vd)){ + alignedLocations.v = alignedLocations.vd; + } + lines.drawDV(node, belowNode, aboveNode, type); + return true; + } + else if (!options.geometricGuideline){ + alignedLocations.v = null; + } + return false; + } + + + + lines.drawDV = function(node, belowNode, aboveNode, type){ + var nodeDim = lines.getDims(node); + var Xcenter = nodeDim["horizontal"]["center"]; + var side = "top", otherSide = "bottom"; + if (type == "above"){ + side = "bottom"; otherSide = "top"; + } + + var offset = calculateOffset([belowNode, node, aboveNode], "horizontal"); + lines.drawLine({ + x: offset, + y: nodeDim["vertical"][side] + }, { + x: offset, + y: lines.getDims(belowNode)["vertical"][otherSide] + }, options.guidelinesStyle.verticalDistColor, options.guidelinesStyle.verticalDistLine); + + lines.drawLine({ + x: offset, + y: lines.getDims(belowNode)["vertical"][side] + }, { + x: offset, + y: lines.getDims(aboveNode)["vertical"][otherSide] + }, options.guidelinesStyle.verticalDistColor, options.guidelinesStyle.verticalDistLine); + + lines.drawLine({ + x: Xcenter, + y: nodeDim["vertical"][side] + }, { + x: offset, + y: nodeDim["vertical"][side] + }, options.guidelinesStyle.verticalDistColor, options.guidelinesStyle.verticalDistLine); + + lines.drawLine({ + x: lines.getDims(belowNode)["horizontal"]["center"], + y: lines.getDims(belowNode)["vertical"][otherSide] + }, { + x: offset, + y: lines.getDims(belowNode)["vertical"][otherSide] + }, options.guidelinesStyle.verticalDistColor, options.guidelinesStyle.verticalDistLine); + + lines.drawLine({ + x: lines.getDims(belowNode)["horizontal"]["center"], + y: lines.getDims(belowNode)["vertical"][side] + }, { + x: offset, + y: lines.getDims(belowNode)["vertical"][side] + }, options.guidelinesStyle.verticalDistColor, options.guidelinesStyle.verticalDistLine); + + lines.drawLine({ + x: offset,//lines.getDims(aboveNode)["horizontal"]["center"], + y: lines.getDims(aboveNode)["vertical"][otherSide] + }, { + x: lines.getDims(aboveNode)["horizontal"]["center"], + y: lines.getDims(aboveNode)["vertical"][otherSide] + }, options.guidelinesStyle.verticalDistColor, options.guidelinesStyle.verticalDistLine); + + lines.drawArrow({ + x: offset, + y: nodeDim["vertical"][side]}, otherSide); + + lines.drawArrow({ + x: offset, + y: lines.getDims(belowNode)["vertical"][otherSide]}, side); + + lines.drawArrow({ + x: offset, + y: lines.getDims(belowNode)["vertical"][side]}, otherSide); + + lines.drawArrow({ + x: offset, + y: lines.getDims(aboveNode)["vertical"][otherSide]}, side); + + } + lines.update = function (activeNodes) { + lines.clear(); + + if (options.initPosAlignment){ + mouseLine(activeNodes); + } + + activeNodes.each(function (node, i) { + if(typeof node === "number") { + node = i; + } + if (options.geometricGuideline){ + lines.searchForLine("horizontal", node); + lines.searchForLine("vertical", node); + } + + if (options.distributionGuidelines){ + lines.horizontalDistribution(node); + lines.verticalDistribution(node); + } + }); + + }; + + lines.resize = function () { + resizeCanvas(); + }; + + function getTopMostNodes(nodes) { + var nodesMap = {}; + + for (var i = 0; i < nodes.length; i++) { + nodesMap[nodes[i].id()] = true; + } + + var roots = nodes.filter(function (ele, i) { + if(typeof ele === "number") { + ele = i; + } + + var parent = ele.parent()[0]; + while (parent != null) { + if (nodesMap[parent.id()]) { + return false; + } + parent = parent.parent()[0]; + } + return true; + }); + + return roots; + } + + var mouseInitPos = {}; + var mouseRelativePos = {}; + var getMousePos = function(e){ + mouseInitPos = e.renderedPosition || e.cyRenderedPosition; + mouseRelativePos.x = mouseInitPos.x; + mouseRelativePos.y = mouseInitPos.y; + } + var setMousePos = function(panCurrPos){ + mouseRelativePos.x += (panCurrPos.x - panInitPos.x); + mouseRelativePos.y += (panCurrPos.y - panInitPos.y); + panInitPos.x = panCurrPos.x; panInitPos.y = panCurrPos.y; + }; + var mouseLine = function(node){ + var nodeCurrentPos = node.renderedPosition(); + if (Math.abs(nodeInitPos.y - nodeCurrentPos.y) < options.guidelinesTolerance){ + lines.drawLine({ + "x" : mouseRelativePos.x, + "y" : mouseInitPos.y + }, { + "x" : nodeCurrentPos.x, + "y" : mouseInitPos.y + }, options.guidelinesStyle.initPosAlignmentColor, options.guidelinesStyle.initPosAlignmentLine); + if (mouseInitPos.y == mouseRelativePos.y){ + lines.drawCross(mouseRelativePos); + } + else{ + lines.drawCross(mouseInitPos); + } + } + else if (Math.abs(nodeInitPos.x - nodeCurrentPos.x) < options.guidelinesTolerance){ + lines.drawLine({ + "x" : mouseInitPos.x, + "y" : mouseRelativePos.y + }, { + "x" : mouseInitPos.x, + "y" : nodeCurrentPos.y + }, options.guidelinesStyle.initPosAlignmentColor, options.guidelinesStyle.initPosAlignmentLine); + if (mouseInitPos.x == mouseRelativePos.x){ + lines.drawCross(mouseRelativePos); + } + else{ + lines.drawCross(mouseInitPos); + } + } + } + + function moveNodes(positionDiff, nodes) { + // Get the descendants of top most nodes. Note that node.position() can move just the simple nodes. + var topMostNodes = getTopMostNodes(nodes); + var nodesToMove = topMostNodes.union(topMostNodes.descendants()); + + nodesToMove.filter(":childless").forEach(function(node, i) { + if(typeof node === "number") { + node = i; + } + var newPos = {x: positionDiff.x + node.renderedPosition("x"), + y: positionDiff.y + node.renderedPosition("y")}; + + node.renderedPosition(newPos); + }); + } + + var tappedNode; + cy.on("tapstart", "node", function(){tappedNode = this}); + + var currMousePos, oldMousePos = {"x": 0, "y": 0}; + cy.on("mousemove", function(e){ + currMousePos = e.renderedPosition || e.cyRenderedPosition; + if (nodeToAlign) + nodeToAlign.each(function (node, i){ + if(typeof node === "number") { + node = i; + } + if (node.locked() && (Math.abs(currMousePos.x - oldMousePos.x) > 2*options.guidelinesTolerance + || Math.abs(currMousePos.y - oldMousePos.y) > 2*options.guidelinesTolerance)){ + + node.unlock(); + var diff = {}; + diff.x = currMousePos.x - tappedNode.renderedPosition("x"); + diff.y = currMousePos.y - tappedNode.renderedPosition("y");; + moveNodes(diff, node); + }; + }); + + }); + var nodeToAlign; + lines.snapToAlignmentLocation = function(activeNodes){ + nodeToAlign = activeNodes; + activeNodes.each(function (node, i){ + if(typeof node === "number") { + node = i; + } + var newPos = node.renderedPosition(); + if (alignedLocations.h){ + oldMousePos = currMousePos; + newPos.x -= alignedLocations.h; + node.renderedPosition(newPos); + } + if (alignedLocations.v){ + oldMousePos = currMousePos; + newPos.y -= alignedLocations.v; + node.renderedPosition(newPos); + }; + if (alignedLocations.v || alignedLocations.h){ + alignedLocations.h = null; + alignedLocations.v = null; + nodeToAlign.lock(); + } + }); + lines.update(activeNodes); + } + + return { + changeOptions: changeOptions, + lines: lines, + getTopMostNodes: getTopMostNodes, + getMousePos: getMousePos, + setMousePos: setMousePos, + resizeCanvas: resizeCanvas, + resetCanvas: resetCanvas, + } }; -},{}],7:[function(require,module,exports){ + +},{"functional-red-black-tree":1}],7:[function(require,module,exports){ ;(function(){ 'use strict'; - // registers the extension on a cytoscape lib ref - var register = function( cytoscape ){ + // registers the extension on a cytoscape lib ref + var register = function(cytoscape, $){ - if( !cytoscape ){ return; } // can't register if cytoscape unspecified + if(!cytoscape || !$){ return; } // can't register if cytoscape unspecified + // flag that indicates if extension api functions are registed to cytoscape + // note that ideally these functions should not be directly registered to core from cytoscape.js + // extensions + var apiRegistered = false; - var options = { - // On/Off Modules - snapToGrid: true, // Snap to grid functionality - discreteDrag: true, // Discrete Drag - guidelines: true, // Guidelines on dragging nodes - resize: true, // Adjust node sizes to cell sizes - parentPadding: true, // Adjust parent sizes to cell sizes by padding - drawGrid: true, // Draw grid background + var defaults = { + // On/Off Modules + /* From the following four snap options, at most one should be true at a given time */ + snapToGridOnRelease: true, // Snap to grid on release + snapToGridDuringDrag: false, // Snap to grid during drag + snapToAlignmentLocationOnRelease: false, // Snap to alignment location on release + snapToAlignmentLocationDuringDrag: false, // Snap to alignment location during drag + distributionGuidelines: false, //Distribution guidelines + geometricGuideline: false, // Geometric guidelines + initPosAlignment: false, // Guideline to initial mouse position + centerToEdgeAlignment: false, // Center tı edge alignment + resize: false, // Adjust node sizes to cell sizes + parentPadding: false, // Adjust parent sizes to cell sizes by padding + drawGrid: true, // Draw grid background - // Other settings + // General + gridSpacing: 20, // Distance between the lines of the grid. + zoomDash: true, // Determines whether the size of the dashes should change when the drawing is zoomed in and out if grid is drawn. + panGrid: false, // Determines whether the grid should move then the user moves the graph if grid is drawn. + gridStackOrder: -1, // Namely z-index + gridColor: '#dedede', // Color of grid lines + lineWidth: 1.0, // Width of grid lines + guidelinesStackOrder: 4, // z-index of guidelines + guidelinesTolerance: 2.00, // Tolerance distance for rendered positions of nodes' interaction. + guidelinesStyle: { // Set ctx properties of line. Properties are here: + strokeStyle: "#8b7d6b", // color of geometric guidelines + geometricGuidelineRange: 400, // range of geometric guidelines + range: 100, // max range of distribution guidelines + minDistRange: 10, // min range for distribution guidelines + distGuidelineOffset: 10, // shift amount of distribution guidelines + horizontalDistColor: "#ff0000", // color of horizontal distribution alignment + verticalDistColor: "#00ff00", // color of vertical distribution alignment + initPosAlignmentColor: "#0000ff", // color of alignment to initial location + lineDash: [0, 0], // line style of geometric guidelines + horizontalDistLine: [0, 0], // line style of horizontal distribıtion guidelines + verticalDistLine: [0, 0], // line style of vertical distribıtion guidelines + initPosAlignmentLine: [0, 0], // line style of alignment to initial mouse position + }, - // General - gridSpacing: 20, // Distance between the lines of the grid. + // Parent Padding + parentSpacing: -1 // -1 to set paddings of parents to gridSpacing + }; + var _snapOnRelease = require("./snap_on_release"); + var _snapToGridDuringDrag = require("./snap_during_drag"); + var _drawGrid = require("./draw_grid"); + var _resize = require("./resize"); + var _eventsController = require("./events_controller"); + var _guidelines = require("./guidelines"); + var _parentPadding = require("./parentPadding"); + var _alignment = require("./alignment"); + var debounce = require("./debounce"); - // Draw Grid - zoomDash: true, // Determines whether the size of the dashes should change when the drawing is zoomed in and out if grid is drawn. - panGrid: true, // Determines whether the grid should move then the user moves the graph if grid is drawn. - gridStackOrder: -1, // Namely z-index - strokeStyle: '#dedede', // Color of grid lines - lineWidth: 1.0, // Width of grid lines - lineDash: [2.5, 4], // Defines style of dash. Read: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash + function getScratch(cy) { + if (!cy.scratch("_gridGuide")) { + cy.scratch("_gridGuide", { }); + } - // Guidelines - guidelinesStackOrder: 4, // z-index of guidelines - guidelinesTolerance: 2.00, // Tolerance distance for rendered positions of nodes' interaction. - guidelinesStyle: { // Set ctx properties of line. Properties are here: - strokeStyle: "#8b7d6b", - lineDash: [3, 5] - }, + return cy.scratch("_gridGuide"); + } - // Parent Padding - parentSpacing: -1 // -1 to set paddings of parents to gridSpacing - }; + cytoscape( 'core', 'gridGuide', function(opts){ + var cy = this; - var _snap = require("./snap"); - var _discreteDrag = require("./discrete_drag"); - var _drawGrid = require("./draw_grid"); - var _resize = require("./resize"); - var _eventsController = require("./events_controller"); - var _guidelines = require("./guidelines"); - var _parentPadding = require("./parentPadding"); - var _alignment = require("./alignment"); - var debounce = require("./debounce"); - var snap, resize, discreteDrag, drawGrid, eventsController, guidelines, parentPadding, alignment; + // access the scratch pad for cy + var scratchPad = getScratch(cy); - function getScratch() { - if (!cy.scratch("_gridGuide")) { - cy.scratch("_gridGuide", { }); + // extend the already existing options for the instance or the default options + var options = $.extend(true, {}, scratchPad.options || defaults, opts); - } - return cy.scratch("_gridGuide"); - } + // reset the options for the instance + scratchPad.options = options; - cytoscape( 'core', 'gridGuide', function(opts){ - var cy = this; - $.extend(true, options, opts); + if (!scratchPad.initialized) { - if (!getScratch().initialized) { - snap = _snap(options.gridSpacing); - resize = _resize(options.gridSpacing); - discreteDrag = _discreteDrag(cy, snap); - drawGrid = _drawGrid(options, cy, $, debounce); - guidelines = _guidelines(options, cy, $, debounce); - parentPadding = _parentPadding(options, cy); + var snap, resize, snapToGridDuringDrag, drawGrid, eventsController, guidelines, parentPadding, alignment; - eventsController = _eventsController(cy, snap, resize, discreteDrag, drawGrid, guidelines, parentPadding, $); + snap = _snapOnRelease(cy, options.gridSpacing); + resize = _resize(options.gridSpacing); + snapToGridDuringDrag = _snapToGridDuringDrag(cy, snap); + drawGrid = _drawGrid(options, cy, $, debounce); + guidelines = _guidelines(options, cy, $, debounce); + parentPadding = _parentPadding(options, cy); - alignment = _alignment(cytoscape, $); + eventsController = _eventsController(cy, snap, resize, snapToGridDuringDrag, drawGrid, guidelines, parentPadding, $, options); - eventsController.init(options); - getScratch().initialized = true; - } else - eventsController.syncWithOptions(options); + alignment = _alignment(cytoscape, cy, $, apiRegistered); + // mark that api functions are registered to cytoscape + apiRegistered = true; - return this; // chainability - } ) ; + eventsController.init(options); + // init params in scratchPad + scratchPad.initialized = true; + scratchPad.eventsController = eventsController; + } + else { + var eventsController = scratchPad.eventsController; + eventsController.syncWithOptions(options); + } - }; + return this; // chainability + } ) ; - if( typeof module !== 'undefined' && module.exports ){ // expose as a commonjs module - module.exports = register; - } + }; - if( typeof define !== 'undefined' && define.amd ){ // expose as an amd/requirejs module - define('cytoscape-grid-guide', function(){ - return register; - }); - } + if( typeof module !== 'undefined' && module.exports ){ // expose as a commonjs module + module.exports = register; + } - if( typeof cytoscape !== 'undefined' ){ // expose to global cytoscape (i.e. window.cytoscape) - register( cytoscape ); - } + if( typeof define !== 'undefined' && define.amd ){ // expose as an amd/requirejs module + define('cytoscape-grid-guide', function(){ + return register; + }); + } + + if( typeof cytoscape !== 'undefined' && $ ){ // expose to global cytoscape (i.e. window.cytoscape) + register( cytoscape, $ ); + } })(); -},{"./alignment":1,"./debounce":2,"./discrete_drag":3,"./draw_grid":4,"./events_controller":5,"./guidelines":6,"./parentPadding":8,"./resize":9,"./snap":10}],8:[function(require,module,exports){ +},{"./alignment":2,"./debounce":3,"./draw_grid":4,"./events_controller":5,"./guidelines":6,"./parentPadding":8,"./resize":9,"./snap_during_drag":10,"./snap_on_release":11}],8:[function(require,module,exports){ module.exports = function (opts, cy) { var options = opts; @@ -1166,7 +2998,90 @@ module.exports = function (gridSpacing) { }; },{}],10:[function(require,module,exports){ -module.exports = function (gridSpacing) { +module.exports = function (cy, snap) { + + var snapToGridDuringDrag = {}; + + var attachedNode; + var draggedNodes; + + var startPos; + var endPos; + + snapToGridDuringDrag.onTapStartNode = function (e) { + // If user intends to do box selection, then return. Related issue #28 + if (e.originalEvent.altKey || e.originalEvent.ctrlKey + || e.originalEvent.metaKey || e.originalEvent.shiftKey){ + return; + } + + var cyTarget = e.target || e.cyTarget; + if (cyTarget.selected()) + draggedNodes = e.cy.$(":selected"); + else + draggedNodes = cyTarget; + + startPos = e.position || e.cyPosition; + + if (cyTarget.grabbable() && !cyTarget.locked()){ + attachedNode = cyTarget; + attachedNode.lock(); + //attachedNode.trigger("grab"); + cy.on("tapdrag", onTapDrag); + cy.on("tapend", onTapEndNode); + } + }; + + var onTapEndNode = function (e) { + //attachedNode.trigger("free"); + cy.off("tapdrag", onTapDrag); + cy.off("tapend", onTapEndNode); + attachedNode.unlock(); + e.preventDefault(); + }; + + var getDist = function () { + return { + x: endPos.x - startPos.x, + y: endPos.y - startPos.y + } + }; + + var onTapDrag = function (e) { + + var nodePos = attachedNode.position(); + endPos = e.position || e.cyPosition; + endPos = snap.snapPos(endPos); + var dist = getDist(); + if (dist.x != 0 || dist.y != 0) { + attachedNode.unlock(); + var nodes = draggedNodes.union(draggedNodes.descendants()); + + nodes.filter(":childless").positions(function (node, i) { + if(typeof node === "number") { + node = i; + } + var pos = node.position(); + return snap.snapPos({ + x: pos.x + dist.x, + y: pos.y + dist.y + }); + }); + + startPos = endPos; + attachedNode.lock(); + attachedNode.trigger("drag"); + } + + }; + + return snapToGridDuringDrag; + + +}; + +},{}],11:[function(require,module,exports){ +module.exports = function (cy, gridSpacing) { var snap = { }; @@ -1181,28 +3096,6 @@ module.exports = function (gridSpacing) { return node.scratch("_gridGuide"); }; - - function getTopMostNodes(nodes) { - var nodesMap = {}; - - for (var i = 0; i < nodes.length; i++) { - nodesMap[nodes[i].id()] = true; - } - - var roots = nodes.filter(function (i, ele) { - var parent = ele.parent()[0]; - while(parent != null){ - if(nodesMap[parent.id()]){ - return false; - } - parent = parent.parent()[0]; - } - return true; - }); - - return roots; - } - snap.snapPos = function (pos) { var newPos = { x: (Math.floor(pos.x / gridSpacing) + 0.5) * gridSpacing, @@ -1220,27 +3113,13 @@ module.exports = function (gridSpacing) { node.position(newPos); }; - function snapTopDown(nodes) { - - nodes.union(nodes.descendants()).positions(function (i, node) { - var pos = node.position(); - return snap.snapPos(pos); - }); - /* - for (var i = 0; i < nodes.length; i++) { - - if (!nodes[i].isParent()) - snap.snapNode(nodes[i]); - - snapTopDown(nodes.children()); - }*/ - - } - snap.snapNodesTopDown = function (nodes) { // getTOpMostNodes -> nodes cy.startBatch(); - nodes.union(nodes.descendants()).positions(function (i, node) { + nodes.union(nodes.descendants()).filter(":childless").positions(function (node, i) { + if(typeof node === "number") { + node = i; + } var pos = node.position(); return snap.snapPos(pos); }); @@ -1249,10 +3128,11 @@ module.exports = function (gridSpacing) { snap.onFreeNode = function (e) { var nodes; - if (e.cyTarget.selected()) + var cyTarget = e.target || e.cyTarget; + if (cyTarget.selected()) nodes = e.cy.$(":selected"); else - nodes = e.cyTarget; + nodes = cyTarget; snap.snapNodesTopDown(nodes); @@ -1273,4 +3153,5 @@ module.exports = function (gridSpacing) { }; + },{}]},{},[7]); diff --git a/styles/bootstrap/cytoscape/cytoscape.js b/styles/bootstrap/cytoscape/cytoscape.js index 8267b7f2b..1ba74803c 100644 --- a/styles/bootstrap/cytoscape/cytoscape.js +++ b/styles/bootstrap/cytoscape/cytoscape.js @@ -1,304 +1,6239 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.cytoscape = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 0; i--) { + if (arr[i] === ele) { + arr.splice(i, 1); + + if (!manyCopies) { + break; + } + } + } +}; + +util.clearArray = function (arr) { + arr.splice(0, arr.length); +}; + +util.push = function (arr, otherArr) { + for (var i = 0; i < otherArr.length; i++) { + var el = otherArr[i]; + + arr.push(el); + } +}; + +util.getPrefixedProperty = function (obj, propName, prefix) { + if (prefix) { + propName = this.prependCamel(prefix, propName); // e.g. (labelWidth, source) => sourceLabelWidth + } + + return obj[propName]; +}; + +util.setPrefixedProperty = function (obj, propName, prefix, value) { + if (prefix) { + propName = this.prependCamel(prefix, propName); // e.g. (labelWidth, source) => sourceLabelWidth + } + + obj[propName] = value; +}; + +[__webpack_require__(21), __webpack_require__(22), { memoize: __webpack_require__(13) }, __webpack_require__(23), __webpack_require__(24), __webpack_require__(25), __webpack_require__(27)].forEach(function (req) { + util.extend(util, req); +}); + +module.exports = util; + +/***/ }), +/* 2 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var math = {}; + +math.arePositionsSame = function (p1, p2) { + return p1.x === p2.x && p1.y === p2.y; +}; + +math.copyPosition = function (p) { + return { x: p.x, y: p.y }; +}; + +math.modelToRenderedPosition = function (p, zoom, pan) { + return { + x: p.x * zoom + pan.x, + y: p.y * zoom + pan.y + }; +}; + +math.renderedToModelPosition = function (p, zoom, pan) { + return { + x: (p.x - pan.x) / zoom, + y: (p.y - pan.y) / zoom + }; +}; + +math.array2point = function (arr) { + return { + x: arr[0], + y: arr[1] + }; +}; + +math.deg2rad = function (deg) { + return Math.PI * deg / 180; +}; + +math.getAngleFromDisp = function (dispX, dispY) { + return Math.atan2(dispY, dispX) - Math.PI / 2; +}; + +math.log2 = Math.log2 || function (n) { + return Math.log(n) / Math.log(2); +}; + +math.signum = function (x) { + if (x > 0) { + return 1; + } else if (x < 0) { + return -1; + } else { + return 0; + } +}; + +math.dist = function (p1, p2) { + return Math.sqrt(math.sqdist(p1, p2)); +}; + +math.sqdist = function (p1, p2) { + var dx = p2.x - p1.x; + var dy = p2.y - p1.y; + + return dx * dx + dy * dy; +}; + +// from http://en.wikipedia.org/wiki/Bézier_curve#Quadratic_curves +math.qbezierAt = function (p0, p1, p2, t) { + return (1 - t) * (1 - t) * p0 + 2 * (1 - t) * t * p1 + t * t * p2; +}; + +math.qbezierPtAt = function (p0, p1, p2, t) { + return { + x: math.qbezierAt(p0.x, p1.x, p2.x, t), + y: math.qbezierAt(p0.y, p1.y, p2.y, t) + }; +}; + +math.lineAt = function (p0, p1, t, d) { + var vec = { + x: p1.x - p0.x, + y: p1.y - p0.y + }; + + var vecDist = math.dist(p0, p1); + + var normVec = { + x: vec.x / vecDist, + y: vec.y / vecDist + }; + + t = t == null ? 0 : t; + + d = d != null ? d : t * vecDist; + + return { + x: p0.x + normVec.x * d, + y: p0.y + normVec.y * d + }; +}; + +math.lineAtDist = function (p0, p1, d) { + return math.lineAt(p0, p1, undefined, d); +}; + +// get angle at A via cosine law +math.triangleAngle = function (A, B, C) { + var a = math.dist(B, C); + var b = math.dist(A, C); + var c = math.dist(A, B); + + return Math.acos((a * a + b * b - c * c) / (2 * a * b)); +}; + +math.bound = function (min, val, max) { + return Math.max(min, Math.min(max, val)); +}; + +// makes a full bb (x1, y1, x2, y2, w, h) from implicit params +math.makeBoundingBox = function (bb) { + if (bb == null) { + return { + x1: Infinity, + y1: Infinity, + x2: -Infinity, + y2: -Infinity, + w: 0, + h: 0 + }; + } else if (bb.x1 != null && bb.y1 != null) { + if (bb.x2 != null && bb.y2 != null && bb.x2 >= bb.x1 && bb.y2 >= bb.y1) { + return { + x1: bb.x1, + y1: bb.y1, + x2: bb.x2, + y2: bb.y2, + w: bb.x2 - bb.x1, + h: bb.y2 - bb.y1 + }; + } else if (bb.w != null && bb.h != null && bb.w >= 0 && bb.h >= 0) { + return { + x1: bb.x1, + y1: bb.y1, + x2: bb.x1 + bb.w, + y2: bb.y1 + bb.h, + w: bb.w, + h: bb.h + }; + } + } +}; + +math.updateBoundingBox = function (bb1, bb2) { + // update bb1 with bb2 bounds + + bb1.x1 = Math.min(bb1.x1, bb2.x1); + bb1.x2 = Math.max(bb1.x2, bb2.x2); + bb1.w = bb1.x2 - bb1.x1; + + bb1.y1 = Math.min(bb1.y1, bb2.y1); + bb1.y2 = Math.max(bb1.y2, bb2.y2); + bb1.h = bb1.y2 - bb1.y1; +}; + +math.expandBoundingBoxByPoint = function (bb, x, y) { + bb.x1 = Math.min(bb.x1, x); + bb.x2 = Math.max(bb.x2, x); + bb.w = bb.x2 - bb.x1; + + bb.y1 = Math.min(bb.y1, y); + bb.y2 = Math.max(bb.y2, y); + bb.h = bb.y2 - bb.y1; +}; + +math.expandBoundingBox = function (bb, padding) { + bb.x1 -= padding; + bb.x2 += padding; + bb.y1 -= padding; + bb.y2 += padding; + bb.w = bb.x2 - bb.x1; + bb.h = bb.y2 - bb.y1; + + return bb; +}; + +math.boundingBoxesIntersect = function (bb1, bb2) { + // case: one bb to right of other + if (bb1.x1 > bb2.x2) { + return false; + } + if (bb2.x1 > bb1.x2) { + return false; + } + + // case: one bb to left of other + if (bb1.x2 < bb2.x1) { + return false; + } + if (bb2.x2 < bb1.x1) { + return false; + } + + // case: one bb above other + if (bb1.y2 < bb2.y1) { + return false; + } + if (bb2.y2 < bb1.y1) { + return false; + } + + // case: one bb below other + if (bb1.y1 > bb2.y2) { + return false; + } + if (bb2.y1 > bb1.y2) { + return false; + } + + // otherwise, must have some overlap + return true; +}; + +math.inBoundingBox = function (bb, x, y) { + return bb.x1 <= x && x <= bb.x2 && bb.y1 <= y && y <= bb.y2; +}; + +math.pointInBoundingBox = function (bb, pt) { + return this.inBoundingBox(bb, pt.x, pt.y); +}; + +math.boundingBoxInBoundingBox = function (bb1, bb2) { + return math.inBoundingBox(bb1, bb2.x1, bb2.y1) && math.inBoundingBox(bb1, bb2.x2, bb2.y2); +}; + +math.roundRectangleIntersectLine = function (x, y, nodeX, nodeY, width, height, padding) { + + var cornerRadius = this.getRoundRectangleRadius(width, height); + + var halfWidth = width / 2; + var halfHeight = height / 2; + + // Check intersections with straight line segments + var straightLineIntersections = void 0; + + // Top segment, left to right + { + var topStartX = nodeX - halfWidth + cornerRadius - padding; + var topStartY = nodeY - halfHeight - padding; + var topEndX = nodeX + halfWidth - cornerRadius + padding; + var topEndY = topStartY; + + straightLineIntersections = this.finiteLinesIntersect(x, y, nodeX, nodeY, topStartX, topStartY, topEndX, topEndY, false); + + if (straightLineIntersections.length > 0) { + return straightLineIntersections; + } + } + + // Right segment, top to bottom + { + var rightStartX = nodeX + halfWidth + padding; + var rightStartY = nodeY - halfHeight + cornerRadius - padding; + var rightEndX = rightStartX; + var rightEndY = nodeY + halfHeight - cornerRadius + padding; + + straightLineIntersections = this.finiteLinesIntersect(x, y, nodeX, nodeY, rightStartX, rightStartY, rightEndX, rightEndY, false); + + if (straightLineIntersections.length > 0) { + return straightLineIntersections; + } + } + + // Bottom segment, left to right + { + var bottomStartX = nodeX - halfWidth + cornerRadius - padding; + var bottomStartY = nodeY + halfHeight + padding; + var bottomEndX = nodeX + halfWidth - cornerRadius + padding; + var bottomEndY = bottomStartY; + + straightLineIntersections = this.finiteLinesIntersect(x, y, nodeX, nodeY, bottomStartX, bottomStartY, bottomEndX, bottomEndY, false); + + if (straightLineIntersections.length > 0) { + return straightLineIntersections; + } + } + + // Left segment, top to bottom + { + var leftStartX = nodeX - halfWidth - padding; + var leftStartY = nodeY - halfHeight + cornerRadius - padding; + var leftEndX = leftStartX; + var leftEndY = nodeY + halfHeight - cornerRadius + padding; + + straightLineIntersections = this.finiteLinesIntersect(x, y, nodeX, nodeY, leftStartX, leftStartY, leftEndX, leftEndY, false); + + if (straightLineIntersections.length > 0) { + return straightLineIntersections; + } + } + + // Check intersections with arc segments + var arcIntersections = void 0; + + // Top Left + { + var topLeftCenterX = nodeX - halfWidth + cornerRadius; + var topLeftCenterY = nodeY - halfHeight + cornerRadius; + arcIntersections = this.intersectLineCircle(x, y, nodeX, nodeY, topLeftCenterX, topLeftCenterY, cornerRadius + padding); + + // Ensure the intersection is on the desired quarter of the circle + if (arcIntersections.length > 0 && arcIntersections[0] <= topLeftCenterX && arcIntersections[1] <= topLeftCenterY) { + return [arcIntersections[0], arcIntersections[1]]; + } + } + + // Top Right + { + var topRightCenterX = nodeX + halfWidth - cornerRadius; + var topRightCenterY = nodeY - halfHeight + cornerRadius; + arcIntersections = this.intersectLineCircle(x, y, nodeX, nodeY, topRightCenterX, topRightCenterY, cornerRadius + padding); + + // Ensure the intersection is on the desired quarter of the circle + if (arcIntersections.length > 0 && arcIntersections[0] >= topRightCenterX && arcIntersections[1] <= topRightCenterY) { + return [arcIntersections[0], arcIntersections[1]]; + } + } + + // Bottom Right + { + var bottomRightCenterX = nodeX + halfWidth - cornerRadius; + var bottomRightCenterY = nodeY + halfHeight - cornerRadius; + arcIntersections = this.intersectLineCircle(x, y, nodeX, nodeY, bottomRightCenterX, bottomRightCenterY, cornerRadius + padding); + + // Ensure the intersection is on the desired quarter of the circle + if (arcIntersections.length > 0 && arcIntersections[0] >= bottomRightCenterX && arcIntersections[1] >= bottomRightCenterY) { + return [arcIntersections[0], arcIntersections[1]]; + } + } + + // Bottom Left + { + var bottomLeftCenterX = nodeX - halfWidth + cornerRadius; + var bottomLeftCenterY = nodeY + halfHeight - cornerRadius; + arcIntersections = this.intersectLineCircle(x, y, nodeX, nodeY, bottomLeftCenterX, bottomLeftCenterY, cornerRadius + padding); + + // Ensure the intersection is on the desired quarter of the circle + if (arcIntersections.length > 0 && arcIntersections[0] <= bottomLeftCenterX && arcIntersections[1] >= bottomLeftCenterY) { + return [arcIntersections[0], arcIntersections[1]]; + } + } + + return []; // if nothing +}; + +math.inLineVicinity = function (x, y, lx1, ly1, lx2, ly2, tolerance) { + var t = tolerance; + + var x1 = Math.min(lx1, lx2); + var x2 = Math.max(lx1, lx2); + var y1 = Math.min(ly1, ly2); + var y2 = Math.max(ly1, ly2); + + return x1 - t <= x && x <= x2 + t && y1 - t <= y && y <= y2 + t; +}; + +math.inBezierVicinity = function (x, y, x1, y1, x2, y2, x3, y3, tolerance) { + + var bb = { + x1: Math.min(x1, x3, x2) - tolerance, + x2: Math.max(x1, x3, x2) + tolerance, + y1: Math.min(y1, y3, y2) - tolerance, + y2: Math.max(y1, y3, y2) + tolerance + }; + + // if outside the rough bounding box for the bezier, then it can't be a hit + if (x < bb.x1 || x > bb.x2 || y < bb.y1 || y > bb.y2) { + // console.log('bezier out of rough bb') + return false; + } else { + // console.log('do more expensive check'); + return true; + } +}; +math.solveQuadratic = function (a, b, c, val) { + c -= val; + + var r = b * b - 4 * a * c; + + if (r < 0) { + return []; + } + + var sqrtR = Math.sqrt(r); + var denom = 2 * a; + var root1 = (-b + sqrtR) / denom; + var root2 = (-b - sqrtR) / denom; + + return [root1, root2]; +}; + +math.solveCubic = function (a, b, c, d, result) { + + // Solves a cubic function, returns root in form [r1, i1, r2, i2, r3, i3], where + // r is the real component, i is the imaginary component + + // An implementation of the Cardano method from the year 1545 + // http://en.wikipedia.org/wiki/Cubic_function#The_nature_of_the_roots + + b /= a; + c /= a; + d /= a; + + var discriminant = void 0, + q = void 0, + r = void 0, + dum1 = void 0, + s = void 0, + t = void 0, + term1 = void 0, + r13 = void 0; + + q = (3.0 * c - b * b) / 9.0; + r = -(27.0 * d) + b * (9.0 * c - 2.0 * (b * b)); + r /= 54.0; + + discriminant = q * q * q + r * r; + result[1] = 0; + term1 = b / 3.0; + + if (discriminant > 0) { + s = r + Math.sqrt(discriminant); + s = s < 0 ? -Math.pow(-s, 1.0 / 3.0) : Math.pow(s, 1.0 / 3.0); + t = r - Math.sqrt(discriminant); + t = t < 0 ? -Math.pow(-t, 1.0 / 3.0) : Math.pow(t, 1.0 / 3.0); + result[0] = -term1 + s + t; + term1 += (s + t) / 2.0; + result[4] = result[2] = -term1; + term1 = Math.sqrt(3.0) * (-t + s) / 2; + result[3] = term1; + result[5] = -term1; + return; + } + + result[5] = result[3] = 0; + + if (discriminant === 0) { + r13 = r < 0 ? -Math.pow(-r, 1.0 / 3.0) : Math.pow(r, 1.0 / 3.0); + result[0] = -term1 + 2.0 * r13; + result[4] = result[2] = -(r13 + term1); + return; + } + + q = -q; + dum1 = q * q * q; + dum1 = Math.acos(r / Math.sqrt(dum1)); + r13 = 2.0 * Math.sqrt(q); + result[0] = -term1 + r13 * Math.cos(dum1 / 3.0); + result[2] = -term1 + r13 * Math.cos((dum1 + 2.0 * Math.PI) / 3.0); + result[4] = -term1 + r13 * Math.cos((dum1 + 4.0 * Math.PI) / 3.0); + + return; +}; + +math.sqdistToQuadraticBezier = function (x, y, x1, y1, x2, y2, x3, y3) { + + // Find minimum distance by using the minimum of the distance + // function between the given point and the curve + + // This gives the coefficients of the resulting cubic equation + // whose roots tell us where a possible minimum is + // (Coefficients are divided by 4) + + var a = 1.0 * x1 * x1 - 4 * x1 * x2 + 2 * x1 * x3 + 4 * x2 * x2 - 4 * x2 * x3 + x3 * x3 + y1 * y1 - 4 * y1 * y2 + 2 * y1 * y3 + 4 * y2 * y2 - 4 * y2 * y3 + y3 * y3; + + var b = 1.0 * 9 * x1 * x2 - 3 * x1 * x1 - 3 * x1 * x3 - 6 * x2 * x2 + 3 * x2 * x3 + 9 * y1 * y2 - 3 * y1 * y1 - 3 * y1 * y3 - 6 * y2 * y2 + 3 * y2 * y3; + + var c = 1.0 * 3 * x1 * x1 - 6 * x1 * x2 + x1 * x3 - x1 * x + 2 * x2 * x2 + 2 * x2 * x - x3 * x + 3 * y1 * y1 - 6 * y1 * y2 + y1 * y3 - y1 * y + 2 * y2 * y2 + 2 * y2 * y - y3 * y; + + var d = 1.0 * x1 * x2 - x1 * x1 + x1 * x - x2 * x + y1 * y2 - y1 * y1 + y1 * y - y2 * y; + + // debug("coefficients: " + a / a + ", " + b / a + ", " + c / a + ", " + d / a); + + var roots = []; + + // Use the cubic solving algorithm + this.solveCubic(a, b, c, d, roots); + + var zeroThreshold = 0.0000001; + + var params = []; + + for (var index = 0; index < 6; index += 2) { + if (Math.abs(roots[index + 1]) < zeroThreshold && roots[index] >= 0 && roots[index] <= 1.0) { + params.push(roots[index]); + } + } + + params.push(1.0); + params.push(0.0); + + var minDistanceSquared = -1; + + var curX = void 0, + curY = void 0, + distSquared = void 0; + for (var i = 0; i < params.length; i++) { + curX = Math.pow(1.0 - params[i], 2.0) * x1 + 2.0 * (1 - params[i]) * params[i] * x2 + params[i] * params[i] * x3; + + curY = Math.pow(1 - params[i], 2.0) * y1 + 2 * (1.0 - params[i]) * params[i] * y2 + params[i] * params[i] * y3; + + distSquared = Math.pow(curX - x, 2) + Math.pow(curY - y, 2); + // debug('distance for param ' + params[i] + ": " + Math.sqrt(distSquared)); + if (minDistanceSquared >= 0) { + if (distSquared < minDistanceSquared) { + minDistanceSquared = distSquared; + } + } else { + minDistanceSquared = distSquared; + } + } + + return minDistanceSquared; +}; + +math.sqdistToFiniteLine = function (x, y, x1, y1, x2, y2) { + var offset = [x - x1, y - y1]; + var line = [x2 - x1, y2 - y1]; + + var lineSq = line[0] * line[0] + line[1] * line[1]; + var hypSq = offset[0] * offset[0] + offset[1] * offset[1]; + + var dotProduct = offset[0] * line[0] + offset[1] * line[1]; + var adjSq = dotProduct * dotProduct / lineSq; + + if (dotProduct < 0) { + return hypSq; + } + + if (adjSq > lineSq) { + return (x - x2) * (x - x2) + (y - y2) * (y - y2); + } + + return hypSq - adjSq; +}; + +math.pointInsidePolygonPoints = function (x, y, points) { + var x1 = void 0, + y1 = void 0, + x2 = void 0, + y2 = void 0; + var y3 = void 0; + + // Intersect with vertical line through (x, y) + var up = 0; + // let down = 0; + for (var i = 0; i < points.length / 2; i++) { + x1 = points[i * 2]; + y1 = points[i * 2 + 1]; + + if (i + 1 < points.length / 2) { + x2 = points[(i + 1) * 2]; + y2 = points[(i + 1) * 2 + 1]; + } else { + x2 = points[(i + 1 - points.length / 2) * 2]; + y2 = points[(i + 1 - points.length / 2) * 2 + 1]; + } + + if (x1 == x && x2 == x) { + // then ignore + } else if (x1 >= x && x >= x2 || x1 <= x && x <= x2) { + + y3 = (x - x1) / (x2 - x1) * (y2 - y1) + y1; + + if (y3 > y) { + up++; + } + + // if( y3 < y ){ + // down++; + // } + } else { + continue; + } + } + + if (up % 2 === 0) { + return false; + } else { + return true; + } +}; + +math.pointInsidePolygon = function (x, y, basePoints, centerX, centerY, width, height, direction, padding) { + + //let direction = arguments[6]; + var transformedPoints = new Array(basePoints.length); + + // Gives negative angle + var angle = void 0; + + if (direction[0] != null) { + angle = Math.atan(direction[1] / direction[0]); + + if (direction[0] < 0) { + angle = angle + Math.PI / 2; + } else { + angle = -angle - Math.PI / 2; + } + } else { + angle = direction; + } + + var cos = Math.cos(-angle); + var sin = Math.sin(-angle); + + // console.log("base: " + basePoints); + for (var i = 0; i < transformedPoints.length / 2; i++) { + transformedPoints[i * 2] = width / 2 * (basePoints[i * 2] * cos - basePoints[i * 2 + 1] * sin); + + transformedPoints[i * 2 + 1] = height / 2 * (basePoints[i * 2 + 1] * cos + basePoints[i * 2] * sin); + + transformedPoints[i * 2] += centerX; + transformedPoints[i * 2 + 1] += centerY; + } + + var points = void 0; + + if (padding > 0) { + var expandedLineSet = this.expandPolygon(transformedPoints, -padding); + + points = this.joinLines(expandedLineSet); + } else { + points = transformedPoints; + } + + return math.pointInsidePolygonPoints(x, y, points); +}; + +math.joinLines = function (lineSet) { + + var vertices = new Array(lineSet.length / 2); + + var currentLineStartX = void 0, + currentLineStartY = void 0, + currentLineEndX = void 0, + currentLineEndY = void 0; + var nextLineStartX = void 0, + nextLineStartY = void 0, + nextLineEndX = void 0, + nextLineEndY = void 0; + + for (var i = 0; i < lineSet.length / 4; i++) { + currentLineStartX = lineSet[i * 4]; + currentLineStartY = lineSet[i * 4 + 1]; + currentLineEndX = lineSet[i * 4 + 2]; + currentLineEndY = lineSet[i * 4 + 3]; + + if (i < lineSet.length / 4 - 1) { + nextLineStartX = lineSet[(i + 1) * 4]; + nextLineStartY = lineSet[(i + 1) * 4 + 1]; + nextLineEndX = lineSet[(i + 1) * 4 + 2]; + nextLineEndY = lineSet[(i + 1) * 4 + 3]; + } else { + nextLineStartX = lineSet[0]; + nextLineStartY = lineSet[1]; + nextLineEndX = lineSet[2]; + nextLineEndY = lineSet[3]; + } + + var intersection = this.finiteLinesIntersect(currentLineStartX, currentLineStartY, currentLineEndX, currentLineEndY, nextLineStartX, nextLineStartY, nextLineEndX, nextLineEndY, true); + + vertices[i * 2] = intersection[0]; + vertices[i * 2 + 1] = intersection[1]; + } + + return vertices; +}; + +math.expandPolygon = function (points, pad) { + + var expandedLineSet = new Array(points.length * 2); + + var currentPointX = void 0, + currentPointY = void 0, + nextPointX = void 0, + nextPointY = void 0; + + for (var i = 0; i < points.length / 2; i++) { + currentPointX = points[i * 2]; + currentPointY = points[i * 2 + 1]; + + if (i < points.length / 2 - 1) { + nextPointX = points[(i + 1) * 2]; + nextPointY = points[(i + 1) * 2 + 1]; + } else { + nextPointX = points[0]; + nextPointY = points[1]; + } + + // Current line: [currentPointX, currentPointY] to [nextPointX, nextPointY] + + // Assume CCW polygon winding + + var offsetX = nextPointY - currentPointY; + var offsetY = -(nextPointX - currentPointX); + + // Normalize + var offsetLength = Math.sqrt(offsetX * offsetX + offsetY * offsetY); + var normalizedOffsetX = offsetX / offsetLength; + var normalizedOffsetY = offsetY / offsetLength; + + expandedLineSet[i * 4] = currentPointX + normalizedOffsetX * pad; + expandedLineSet[i * 4 + 1] = currentPointY + normalizedOffsetY * pad; + expandedLineSet[i * 4 + 2] = nextPointX + normalizedOffsetX * pad; + expandedLineSet[i * 4 + 3] = nextPointY + normalizedOffsetY * pad; + } + + return expandedLineSet; +}; + +math.intersectLineEllipse = function (x, y, centerX, centerY, ellipseWradius, ellipseHradius) { + + var dispX = centerX - x; + var dispY = centerY - y; + + dispX /= ellipseWradius; + dispY /= ellipseHradius; + + var len = Math.sqrt(dispX * dispX + dispY * dispY); + + var newLength = len - 1; + + if (newLength < 0) { + return []; + } + + var lenProportion = newLength / len; + + return [(centerX - x) * lenProportion + x, (centerY - y) * lenProportion + y]; +}; + +math.checkInEllipse = function (x, y, width, height, centerX, centerY, padding) { + x -= centerX; + y -= centerY; + + x /= width / 2 + padding; + y /= height / 2 + padding; + + return x * x + y * y <= 1; +}; + +// Returns intersections of increasing distance from line's start point +math.intersectLineCircle = function (x1, y1, x2, y2, centerX, centerY, radius) { + + // Calculate d, direction vector of line + var d = [x2 - x1, y2 - y1]; // Direction vector of line + var f = [x1 - centerX, y1 - centerY]; + + var a = d[0] * d[0] + d[1] * d[1]; + var b = 2 * (f[0] * d[0] + f[1] * d[1]); + var c = f[0] * f[0] + f[1] * f[1] - radius * radius; + + var discriminant = b * b - 4 * a * c; + + if (discriminant < 0) { + return []; + } + + var t1 = (-b + Math.sqrt(discriminant)) / (2 * a); + var t2 = (-b - Math.sqrt(discriminant)) / (2 * a); + + var tMin = Math.min(t1, t2); + var tMax = Math.max(t1, t2); + var inRangeParams = []; + + if (tMin >= 0 && tMin <= 1) { + inRangeParams.push(tMin); + } + + if (tMax >= 0 && tMax <= 1) { + inRangeParams.push(tMax); + } + + if (inRangeParams.length === 0) { + return []; + } + + var nearIntersectionX = inRangeParams[0] * d[0] + x1; + var nearIntersectionY = inRangeParams[0] * d[1] + y1; + + if (inRangeParams.length > 1) { + + if (inRangeParams[0] == inRangeParams[1]) { + return [nearIntersectionX, nearIntersectionY]; + } else { + + var farIntersectionX = inRangeParams[1] * d[0] + x1; + var farIntersectionY = inRangeParams[1] * d[1] + y1; + + return [nearIntersectionX, nearIntersectionY, farIntersectionX, farIntersectionY]; + } + } else { + return [nearIntersectionX, nearIntersectionY]; + } +}; + +math.findCircleNearPoint = function (centerX, centerY, radius, farX, farY) { + + var displacementX = farX - centerX; + var displacementY = farY - centerY; + var distance = Math.sqrt(displacementX * displacementX + displacementY * displacementY); + + var unitDisplacementX = displacementX / distance; + var unitDisplacementY = displacementY / distance; + + return [centerX + unitDisplacementX * radius, centerY + unitDisplacementY * radius]; +}; + +math.findMaxSqDistanceToOrigin = function (points) { + var maxSqDistance = 0.000001; + var sqDistance = void 0; + + for (var i = 0; i < points.length / 2; i++) { + + sqDistance = points[i * 2] * points[i * 2] + points[i * 2 + 1] * points[i * 2 + 1]; + + if (sqDistance > maxSqDistance) { + maxSqDistance = sqDistance; + } + } + + return maxSqDistance; +}; + +math.midOfThree = function (a, b, c) { + if (b <= a && a <= c || c <= a && a <= b) { + return a; + } else if (a <= b && b <= c || c <= b && b <= a) { + return b; + } else { + return c; + } +}; + +// (x1,y1)=>(x2,y2) intersect with (x3,y3)=>(x4,y4) +math.finiteLinesIntersect = function (x1, y1, x2, y2, x3, y3, x4, y4, infiniteLines) { + + var dx13 = x1 - x3; + var dx21 = x2 - x1; + var dx43 = x4 - x3; + + var dy13 = y1 - y3; + var dy21 = y2 - y1; + var dy43 = y4 - y3; + + var ua_t = dx43 * dy13 - dy43 * dx13; + var ub_t = dx21 * dy13 - dy21 * dx13; + var u_b = dy43 * dx21 - dx43 * dy21; + + if (u_b !== 0) { + var ua = ua_t / u_b; + var ub = ub_t / u_b; + + var flptThreshold = 0.001; + var min = 0 - flptThreshold; + var max = 1 + flptThreshold; + + if (min <= ua && ua <= max && min <= ub && ub <= max) { + return [x1 + ua * dx21, y1 + ua * dy21]; + } else { + if (!infiniteLines) { + return []; + } else { + return [x1 + ua * dx21, y1 + ua * dy21]; + } + } + } else { + if (ua_t === 0 || ub_t === 0) { + + // Parallel, coincident lines. Check if overlap + + // Check endpoint of second line + if (this.midOfThree(x1, x2, x4) === x4) { + return [x4, y4]; + } + + // Check start point of second line + if (this.midOfThree(x1, x2, x3) === x3) { + return [x3, y3]; + } + + // Endpoint of first line + if (this.midOfThree(x3, x4, x2) === x2) { + return [x2, y2]; + } + + return []; + } else { + + // Parallel, non-coincident + return []; + } + } +}; + +// math.polygonIntersectLine( x, y, basePoints, centerX, centerY, width, height, padding ) +// intersect a node polygon (pts transformed) +// +// math.polygonIntersectLine( x, y, basePoints, centerX, centerY ) +// intersect the points (no transform) +math.polygonIntersectLine = function (x, y, basePoints, centerX, centerY, width, height, padding) { + + var intersections = []; + var intersection = void 0; + + var transformedPoints = new Array(basePoints.length); + + var doTransform = true; + if (arguments.length === 5) { + doTransform = false; + } + + var points = void 0; + + if (doTransform) { + for (var i = 0; i < transformedPoints.length / 2; i++) { + transformedPoints[i * 2] = basePoints[i * 2] * width + centerX; + transformedPoints[i * 2 + 1] = basePoints[i * 2 + 1] * height + centerY; + } + + if (padding > 0) { + var expandedLineSet = math.expandPolygon(transformedPoints, -padding); + + points = math.joinLines(expandedLineSet); + } else { + points = transformedPoints; + } + } else { + points = basePoints; + } + + var currentX = void 0, + currentY = void 0, + nextX = void 0, + nextY = void 0; + + for (var _i = 0; _i < points.length / 2; _i++) { + + currentX = points[_i * 2]; + currentY = points[_i * 2 + 1]; + + if (_i < points.length / 2 - 1) { + nextX = points[(_i + 1) * 2]; + nextY = points[(_i + 1) * 2 + 1]; + } else { + nextX = points[0]; + nextY = points[1]; + } + + intersection = this.finiteLinesIntersect(x, y, centerX, centerY, currentX, currentY, nextX, nextY); + + if (intersection.length !== 0) { + intersections.push(intersection[0], intersection[1]); + } + } + + return intersections; +}; + +math.shortenIntersection = function (intersection, offset, amount) { + + var disp = [intersection[0] - offset[0], intersection[1] - offset[1]]; + + var length = Math.sqrt(disp[0] * disp[0] + disp[1] * disp[1]); + + var lenRatio = (length - amount) / length; + + if (lenRatio < 0) { + lenRatio = 0.00001; + } + + return [offset[0] + lenRatio * disp[0], offset[1] + lenRatio * disp[1]]; +}; + +math.generateUnitNgonPointsFitToSquare = function (sides, rotationRadians) { + var points = math.generateUnitNgonPoints(sides, rotationRadians); + points = math.fitPolygonToSquare(points); + + return points; +}; + +math.fitPolygonToSquare = function (points) { + var x = void 0, + y = void 0; + var sides = points.length / 2; + var minX = Infinity, + minY = Infinity, + maxX = -Infinity, + maxY = -Infinity; + + for (var i = 0; i < sides; i++) { + x = points[2 * i]; + y = points[2 * i + 1]; + + minX = Math.min(minX, x); + maxX = Math.max(maxX, x); + minY = Math.min(minY, y); + maxY = Math.max(maxY, y); + } + + // stretch factors + var sx = 2 / (maxX - minX); + var sy = 2 / (maxY - minY); + + for (var _i2 = 0; _i2 < sides; _i2++) { + x = points[2 * _i2] = points[2 * _i2] * sx; + y = points[2 * _i2 + 1] = points[2 * _i2 + 1] * sy; + + minX = Math.min(minX, x); + maxX = Math.max(maxX, x); + minY = Math.min(minY, y); + maxY = Math.max(maxY, y); + } + + if (minY < -1) { + for (var _i3 = 0; _i3 < sides; _i3++) { + y = points[2 * _i3 + 1] = points[2 * _i3 + 1] + (-1 - minY); + } + } + + return points; +}; + +math.generateUnitNgonPoints = function (sides, rotationRadians) { + + var increment = 1.0 / sides * 2 * Math.PI; + var startAngle = sides % 2 === 0 ? Math.PI / 2.0 + increment / 2.0 : Math.PI / 2.0; + + startAngle += rotationRadians; + + var points = new Array(sides * 2); + + var currentAngle = void 0; + for (var i = 0; i < sides; i++) { + currentAngle = i * increment + startAngle; + + points[2 * i] = Math.cos(currentAngle); // x + points[2 * i + 1] = Math.sin(-currentAngle); // y + } + + return points; +}; + +math.getRoundRectangleRadius = function (width, height) { + + // Set the default radius, unless half of width or height is smaller than default + return Math.min(width / 4, height / 4, 8); +}; + +math.getCutRectangleCornerLength = function () { + return 8; +}; + +math.bezierPtsToQuadCoeff = function (p0, p1, p2) { + return [p0 - 2 * p1 + p2, 2 * (p1 - p0), p0]; +}; + +math.getBarrelCurveConstants = function (width, height) { + // get curve width, height, and control point position offsets as a percentage of node height / width + return { + heightOffset: Math.min(15, 0.05 * height), + widthOffset: Math.min(100, 0.25 * width), + ctrlPtOffsetPct: 0.05 + }; +}; + +module.exports = math; + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = typeof window === 'undefined' ? null : window; // eslint-disable-line no-undef + +/***/ }), +/* 4 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +// use this module to cherry pick functions into your prototype +// (useful for functions shared between the core and collections, for example) + +// e.g. +// let foo = define.foo({ /* params... */ }) + +var util = __webpack_require__(1); + +var define = {}; + +[__webpack_require__(44), __webpack_require__(46), __webpack_require__(47)].forEach(function (m) { + util.assign(define, m); +}); + +module.exports = define; + +/***/ }), +/* 5 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +/*! +Embeddable Minimum Strictly-Compliant Promises/A+ 1.1.1 Thenable +Copyright (c) 2013-2014 Ralf S. Engelschall (http://engelschall.com) +Licensed under The MIT License (http://opensource.org/licenses/MIT) +*/ + +/* promise states [Promises/A+ 2.1] */ +var STATE_PENDING = 0; /* [Promises/A+ 2.1.1] */ +var STATE_FULFILLED = 1; /* [Promises/A+ 2.1.2] */ +var STATE_REJECTED = 2; /* [Promises/A+ 2.1.3] */ + +/* promise object constructor */ +var api = function api(executor) { + /* optionally support non-constructor/plain-function call */ + if (!(this instanceof api)) return new api(executor); + + /* initialize object */ + this.id = 'Thenable/1.0.7'; + this.state = STATE_PENDING; /* initial state */ + this.fulfillValue = undefined; /* initial value */ /* [Promises/A+ 1.3, 2.1.2.2] */ + this.rejectReason = undefined; /* initial reason */ /* [Promises/A+ 1.5, 2.1.3.2] */ + this.onFulfilled = []; /* initial handlers */ + this.onRejected = []; /* initial handlers */ + + /* provide optional information-hiding proxy */ + this.proxy = { + then: this.then.bind(this) + }; + + /* support optional executor function */ + if (typeof executor === 'function') executor.call(this, this.fulfill.bind(this), this.reject.bind(this)); +}; + +/* promise API methods */ +api.prototype = { + /* promise resolving methods */ + fulfill: function fulfill(value) { + return deliver(this, STATE_FULFILLED, 'fulfillValue', value); + }, + reject: function reject(value) { + return deliver(this, STATE_REJECTED, 'rejectReason', value); + }, + + /* "The then Method" [Promises/A+ 1.1, 1.2, 2.2] */ + then: function then(onFulfilled, onRejected) { + var curr = this; + var next = new api(); /* [Promises/A+ 2.2.7] */ + curr.onFulfilled.push(resolver(onFulfilled, next, 'fulfill')); /* [Promises/A+ 2.2.2/2.2.6] */ + curr.onRejected.push(resolver(onRejected, next, 'reject')); /* [Promises/A+ 2.2.3/2.2.6] */ + execute(curr); + return next.proxy; /* [Promises/A+ 2.2.7, 3.3] */ + } +}; + +/* deliver an action */ +var deliver = function deliver(curr, state, name, value) { + if (curr.state === STATE_PENDING) { + curr.state = state; /* [Promises/A+ 2.1.2.1, 2.1.3.1] */ + curr[name] = value; /* [Promises/A+ 2.1.2.2, 2.1.3.2] */ + execute(curr); + } + return curr; +}; + +/* execute all handlers */ +var execute = function execute(curr) { + if (curr.state === STATE_FULFILLED) execute_handlers(curr, 'onFulfilled', curr.fulfillValue);else if (curr.state === STATE_REJECTED) execute_handlers(curr, 'onRejected', curr.rejectReason); +}; + +/* execute particular set of handlers */ +var execute_handlers = function execute_handlers(curr, name, value) { + /* global setImmediate: true */ + /* global setTimeout: true */ + + /* short-circuit processing */ + if (curr[name].length === 0) return; + + /* iterate over all handlers, exactly once */ + var handlers = curr[name]; + curr[name] = []; /* [Promises/A+ 2.2.2.3, 2.2.3.3] */ + var func = function func() { + for (var i = 0; i < handlers.length; i++) { + handlers[i](value); + } /* [Promises/A+ 2.2.5] */ + }; + + /* execute procedure asynchronously */ /* [Promises/A+ 2.2.4, 3.1] */ + if (typeof setImmediate === 'function') setImmediate(func);else setTimeout(func, 0); +}; + +/* generate a resolver function */ +var resolver = function resolver(cb, next, method) { + return function (value) { + if (typeof cb !== 'function') /* [Promises/A+ 2.2.1, 2.2.7.3, 2.2.7.4] */ + next[method].call(next, value); /* [Promises/A+ 2.2.7.3, 2.2.7.4] */ + else { + var result; + try { + result = cb(value); + } /* [Promises/A+ 2.2.2.1, 2.2.3.1, 2.2.5, 3.2] */ + catch (e) { + next.reject(e); /* [Promises/A+ 2.2.7.2] */ + return; + } + resolve(next, result); /* [Promises/A+ 2.2.7.1] */ + } + }; +}; + +/* "Promise Resolution Procedure" */ /* [Promises/A+ 2.3] */ +var resolve = function resolve(promise, x) { + /* sanity check arguments */ /* [Promises/A+ 2.3.1] */ + if (promise === x || promise.proxy === x) { + promise.reject(new TypeError('cannot resolve promise with itself')); + return; + } + + /* surgically check for a "then" method + (mainly to just call the "getter" of "then" only once) */ + var then; + if ((typeof x === 'undefined' ? 'undefined' : _typeof(x)) === 'object' && x !== null || typeof x === 'function') { + try { + then = x.then; + } /* [Promises/A+ 2.3.3.1, 3.5] */ + catch (e) { + promise.reject(e); /* [Promises/A+ 2.3.3.2] */ + return; + } + } + + /* handle own Thenables [Promises/A+ 2.3.2] + and similar "thenables" [Promises/A+ 2.3.3] */ + if (typeof then === 'function') { + var resolved = false; + try { + /* call retrieved "then" method */ /* [Promises/A+ 2.3.3.3] */ + then.call(x, + /* resolvePromise */ /* [Promises/A+ 2.3.3.3.1] */ + function (y) { + if (resolved) return;resolved = true; /* [Promises/A+ 2.3.3.3.3] */ + if (y === x) /* [Promises/A+ 3.6] */ + promise.reject(new TypeError('circular thenable chain'));else resolve(promise, y); + }, + + /* rejectPromise */ /* [Promises/A+ 2.3.3.3.2] */ + function (r) { + if (resolved) return;resolved = true; /* [Promises/A+ 2.3.3.3.3] */ + promise.reject(r); + }); + } catch (e) { + if (!resolved) /* [Promises/A+ 2.3.3.3.3] */ + promise.reject(e); /* [Promises/A+ 2.3.3.3.4] */ + } + return; + } + + /* handle other values */ + promise.fulfill(x); /* [Promises/A+ 2.3.4, 2.3.3.4] */ +}; + +// so we always have Promise.all() +api.all = function (ps) { + return new api(function (resolveAll, rejectAll) { + var vals = new Array(ps.length); + var doneCount = 0; + + var fulfill = function fulfill(i, val) { + vals[i] = val; + doneCount++; + + if (doneCount === ps.length) { + resolveAll(vals); + } + }; + + for (var i = 0; i < ps.length; i++) { + (function (i) { + var p = ps[i]; + var isPromise = p != null && p.then != null; + + if (isPromise) { + p.then(function (val) { + fulfill(i, val); + }, function (err) { + rejectAll(err); + }); + } else { + var val = p; + fulfill(i, val); + } + })(i); + } + }); +}; + +api.resolve = function (val) { + return new api(function (resolve, reject) { + resolve(val); + }); +}; + +api.reject = function (val) { + return new api(function (resolve, reject) { + reject(val); + }); +}; + +module.exports = typeof Promise !== 'undefined' ? Promise : api; // eslint-disable-line no-undef + +/***/ }), +/* 6 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var is = __webpack_require__(0); +var util = __webpack_require__(1); +var newQuery = __webpack_require__(10); + +var Selector = function Selector(selector) { + var self = this; + + self._private = { + selectorText: selector, + invalid: true + }; + + if (selector == null || is.string(selector) && selector.match(/^\s*$/)) { + + self.length = 0; + } else if (selector === '*' || selector === 'edge' || selector === 'node') { + + // make single, group-only selectors cheap to make and cheap to filter + + self[0] = newQuery(); + self[0].group = selector === '*' ? selector : selector + 's'; + self[0].groupOnly = true; + self[0].length = 1; + self._private.invalid = false; + self.length = 1; + } else if (is.elementOrCollection(selector)) { + + var collection = selector.collection(); + + self[0] = newQuery(); + self[0].collection = collection; + self[0].length = 1; + self.length = 1; + } else if (is.fn(selector)) { + + self[0] = newQuery(); + self[0].filter = selector; + self[0].length = 1; + self.length = 1; + } else if (is.string(selector)) { + if (!self.parse(selector)) { + return; + } + } else { + util.error('A selector must be created from a string; found ', selector); + return; + } + + self._private.invalid = false; +}; + +var selfn = Selector.prototype; + +selfn.valid = function () { + return !this._private.invalid; +}; + +selfn.invalid = function () { + return this._private.invalid; +}; + +selfn.text = function () { + return this._private.selectorText; +}; + +selfn.size = function () { + return this.length; +}; + +selfn.eq = function (i) { + return this[i]; +}; + +selfn.sameText = function (otherSel) { + return this.text() === otherSel.text(); +}; + +selfn.toString = selfn.selector = function () { + + if (this._private.toStringCache != null) { + return this._private.toStringCache; + } + + var i = void 0; + var str = ''; + + var clean = function clean(obj) { + if (obj == null) { + return ''; + } else { + return obj; + } + }; + + var cleanVal = function cleanVal(val) { + if (is.string(val)) { + return '"' + val + '"'; + } else { + return clean(val); + } + }; + + var space = function space(val) { + return ' ' + val + ' '; + }; + + var queryToString = function queryToString(query) { + var str = ''; + var j = void 0, + sel = void 0; + + if (query.subject === query) { + str += '$'; + } + + var group = clean(query.group); + str += group.substring(0, group.length - 1); + + for (j = 0; j < query.data.length; j++) { + var data = query.data[j]; + + if (data.value) { + str += '[' + data.field + space(clean(data.operator)) + cleanVal(data.value) + ']'; + } else { + str += '[' + clean(data.operator) + data.field + ']'; + } + } + + for (j = 0; j < query.meta.length; j++) { + var meta = query.meta[j]; + str += '[[' + meta.field + space(clean(meta.operator)) + cleanVal(meta.value) + ']]'; + } + + for (j = 0; j < query.colonSelectors.length; j++) { + sel = query.colonSelectors[i]; + str += sel; + } + + for (j = 0; j < query.ids.length; j++) { + sel = '#' + query.ids[i]; + str += sel; + } + + for (j = 0; j < query.classes.length; j++) { + sel = '.' + query.classes[j]; + str += sel; + } + + if (query.source != null && query.target != null) { + str = queryToString(query.source) + ' -> ' + queryToString(query.target); + } + + if (query.connectedNodes != null) { + var n = query.connectedNodes; + + str = queryToString(n[0]) + ' <-> ' + queryToString(n[1]); + } + + if (query.parent != null) { + str = queryToString(query.parent) + ' > ' + str; + } + + if (query.ancestor != null) { + str = queryToString(query.ancestor) + ' ' + str; + } + + if (query.child != null) { + str += ' > ' + queryToString(query.child); + } + + if (query.descendant != null) { + str += ' ' + queryToString(query.descendant); + } + + return str; + }; + + for (i = 0; i < this.length; i++) { + var query = this[i]; + + str += queryToString(query); + + if (this.length > 1 && i < this.length - 1) { + str += ', '; + } + } + + this._private.toStringCache = str; + + return str; +}; + +[__webpack_require__(50), __webpack_require__(53)].forEach(function (p) { + return util.assign(selfn, p); +}); + +module.exports = Selector; + +/***/ }), +/* 7 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var util = __webpack_require__(1); +var is = __webpack_require__(0); +var Map = __webpack_require__(28); +var Set = __webpack_require__(8); + +var Element = __webpack_require__(14); + +// factory for generating edge ids when no id is specified for a new element +var idFactory = { + generate: function generate(cy, element, tryThisId) { + var id = tryThisId != null ? tryThisId : util.uuid(); + + while (cy.hasElementWithId(id)) { + id = util.uuid(); + } + + return id; + } +}; + +// represents a set of nodes, edges, or both together +var Collection = function Collection(cy, elements, options) { + if (cy === undefined || !is.core(cy)) { + util.error('A collection must have a reference to the core'); + return; + } + + var map = new Map(); + var createdElements = false; + + if (!elements) { + elements = []; + } else if (elements.length > 0 && is.plainObject(elements[0]) && !is.element(elements[0])) { + createdElements = true; + + // make elements from json and restore all at once later + var eles = []; + var elesIds = new Set(); + + for (var i = 0, l = elements.length; i < l; i++) { + var json = elements[i]; + + if (json.data == null) { + json.data = {}; + } + + var data = json.data; + + // make sure newly created elements have valid ids + if (data.id == null) { + data.id = idFactory.generate(cy, json); + } else if (cy.hasElementWithId(data.id) || elesIds.has(data.id)) { + continue; // can't create element if prior id already exists + } + + var ele = new Element(cy, json, false); + eles.push(ele); + elesIds.add(data.id); + } + + elements = eles; + } + + this.length = 0; + + for (var _i = 0, _l = elements.length; _i < _l; _i++) { + var element = elements[_i]; + if (element == null) { + continue; + } + + var id = element._private.data.id; + + if (options == null || options.unique && !map.has(id)) { + map.set(id, { + index: this.length, + ele: element + }); + + this[this.length] = element; + this.length++; + } + } + + this._private = { + cy: cy, + map: map + }; + + // restore the elements if we created them from json + if (createdElements) { + this.restore(); + } +}; + +// Functions +//////////////////////////////////////////////////////////////////////////////////////////////////// + +// keep the prototypes in sync (an element has the same functions as a collection) +// and use elefn and elesfn as shorthands to the prototypes +var elesfn = Element.prototype = Collection.prototype; + +elesfn.instanceString = function () { + return 'collection'; +}; + +elesfn.spawn = function (cy, eles, opts) { + if (!is.core(cy)) { + // cy is optional + opts = eles; + eles = cy; + cy = this.cy(); + } + + return new Collection(cy, eles, opts); +}; + +elesfn.spawnSelf = function () { + return this.spawn(this); +}; + +elesfn.cy = function () { + return this._private.cy; +}; + +elesfn.renderer = function () { + return this._private.cy.renderer(); +}; + +elesfn.element = function () { + return this[0]; +}; + +elesfn.collection = function () { + if (is.collection(this)) { + return this; + } else { + // an element + return new Collection(this._private.cy, [this]); + } +}; + +elesfn.unique = function () { + return new Collection(this._private.cy, this, { unique: true }); +}; + +elesfn.hasElementWithId = function (id) { + return this._private.map.has(id); +}; + +elesfn.getElementById = function (id) { + var cy = this._private.cy; + var entry = this._private.map.get(id); + + return entry ? entry.ele : new Collection(cy); // get ele or empty collection +}; + +elesfn.$id = elesfn.getElementById; + +elesfn.poolIndex = function () { + var cy = this._private.cy; + var eles = cy._private.elements; + var id = this._private.data.id; + + return eles._private.map.get(id).index; +}; + +elesfn.json = function (obj) { + var ele = this.element(); + var cy = this.cy(); + + if (ele == null && obj) { + return this; + } // can't set to no eles + + if (ele == null) { + return undefined; + } // can't get from no eles + + var p = ele._private; + + if (is.plainObject(obj)) { + // set + + cy.startBatch(); + + if (obj.data) { + ele.data(obj.data); + + var data = p.data; + + if (ele.isEdge()) { + // source and target are immutable via data() + var move = false; + var spec = {}; + var src = obj.data.source; + var tgt = obj.data.target; + + if (src != null && src !== data.source) { + spec.source = src; + move = true; + } + + if (tgt != null && tgt !== data.target) { + spec.target = tgt; + move = true; + } + + if (move) { + ele = ele.move(spec); + } + } else { + // parent is immutable via data() + var parent = obj.data.parent; + + if (parent != null && parent !== data.parent) { + ele = ele.move({ parent: parent }); + } + } + } + + if (obj.position) { + ele.position(obj.position); + } + + // ignore group -- immutable + + var checkSwitch = function checkSwitch(k, trueFnName, falseFnName) { + var obj_k = obj[k]; + + if (obj_k != null && obj_k !== p[k]) { + if (obj_k) { + ele[trueFnName](); + } else { + ele[falseFnName](); + } + } + }; + + checkSwitch('removed', 'remove', 'restore'); + + checkSwitch('selected', 'select', 'unselect'); + + checkSwitch('selectable', 'selectify', 'unselectify'); + + checkSwitch('locked', 'lock', 'unlock'); + + checkSwitch('grabbable', 'grabify', 'ungrabify'); + + if (obj.classes != null) { + ele.classes(obj.classes); + } + + cy.endBatch(); + + return this; + } else if (obj === undefined) { + // get + + var json = { + data: util.copy(p.data), + position: util.copy(p.position), + group: p.group, + removed: p.removed, + selected: p.selected, + selectable: p.selectable, + locked: p.locked, + grabbable: p.grabbable, + classes: null + }; + + json.classes = ''; + + var i = 0; + p.classes.forEach(function (cls) { + return json.classes += i++ === 0 ? cls : ' ' + cls; + }); + + return json; + } +}; + +elesfn.jsons = function () { + var jsons = []; + + for (var i = 0; i < this.length; i++) { + var ele = this[i]; + var json = ele.json(); + + jsons.push(json); + } + + return jsons; +}; + +elesfn.clone = function () { + var cy = this.cy(); + var elesArr = []; + + for (var i = 0; i < this.length; i++) { + var ele = this[i]; + var json = ele.json(); + var clone = new Element(cy, json, false); // NB no restore + + elesArr.push(clone); + } + + return new Collection(cy, elesArr); +}; +elesfn.copy = elesfn.clone; + +elesfn.restore = function (notifyRenderer) { + var self = this; + var cy = self.cy(); + var cy_p = cy._private; + + if (notifyRenderer === undefined) { + notifyRenderer = true; + } + + // create arrays of nodes and edges, since we need to + // restore the nodes first + var nodes = []; + var edges = []; + var elements = void 0; + for (var _i2 = 0, l = self.length; _i2 < l; _i2++) { + var ele = self[_i2]; + + if (!ele.removed()) { + // don't need to handle this ele + continue; + } + + // keep nodes first in the array and edges after + if (ele.isNode()) { + // put to front of array if node + nodes.push(ele); + } else { + // put to end of array if edge + edges.push(ele); + } + } + + elements = nodes.concat(edges); + + var i = void 0; + var removeFromElements = function removeFromElements() { + elements.splice(i, 1); + i--; + }; + + // now, restore each element + for (i = 0; i < elements.length; i++) { + var _ele = elements[i]; + + var _private = _ele._private; + var data = _private.data; + + // the traversal cache should start fresh when ele is added + _ele.clearTraversalCache(); + + // set id and validate + if (data.id === undefined) { + data.id = idFactory.generate(cy, _ele); + } else if (is.number(data.id)) { + data.id = '' + data.id; // now it's a string + } else if (is.emptyString(data.id) || !is.string(data.id)) { + util.error('Can not create element with invalid string ID `' + data.id + '`'); + + // can't create element if it has empty string as id or non-string id + removeFromElements(); + continue; + } else if (cy.hasElementWithId(data.id)) { + util.error('Can not create second element with ID `' + data.id + '`'); + + // can't create element if one already has that id + removeFromElements(); + continue; + } + + var id = data.id; // id is finalised, now let's keep a ref + + if (_ele.isNode()) { + // extra checks for nodes + var pos = _private.position; + + // make sure the nodes have a defined position + + if (pos.x == null) { + pos.x = 0; + } + + if (pos.y == null) { + pos.y = 0; + } + } + + if (_ele.isEdge()) { + // extra checks for edges + + var edge = _ele; + var fields = ['source', 'target']; + var fieldsLength = fields.length; + var badSourceOrTarget = false; + for (var j = 0; j < fieldsLength; j++) { + + var field = fields[j]; + var val = data[field]; + + if (is.number(val)) { + val = data[field] = '' + data[field]; // now string + } + + if (val == null || val === '') { + // can't create if source or target is not defined properly + util.error('Can not create edge `' + id + '` with unspecified ' + field); + badSourceOrTarget = true; + } else if (!cy.hasElementWithId(val)) { + // can't create edge if one of its nodes doesn't exist + util.error('Can not create edge `' + id + '` with nonexistant ' + field + ' `' + val + '`'); + badSourceOrTarget = true; + } + } + + if (badSourceOrTarget) { + removeFromElements();continue; + } // can't create this + + var src = cy.getElementById(data.source); + var tgt = cy.getElementById(data.target); + + src._private.edges.push(edge); + tgt._private.edges.push(edge); + + edge._private.source = src; + edge._private.target = tgt; + } // if is edge + + // create mock ids / indexes maps for element so it can be used like collections + _private.map = new Map(); + _private.map.set(id, { ele: _ele, index: 0 }); + + _private.removed = false; + cy.addToPool(_ele); + } // for each element + + // do compound node sanity checks + for (var _i3 = 0; _i3 < nodes.length; _i3++) { + // each node + var node = nodes[_i3]; + var _data = node._private.data; + + if (is.number(_data.parent)) { + // then automake string + _data.parent = '' + _data.parent; + } + + var parentId = _data.parent; + + var specifiedParent = parentId != null; + + if (specifiedParent) { + var parent = cy.getElementById(parentId); + + if (parent.empty()) { + // non-existant parent; just remove it + _data.parent = undefined; + } else { + var selfAsParent = false; + var ancestor = parent; + while (!ancestor.empty()) { + if (node.same(ancestor)) { + // mark self as parent and remove from data + selfAsParent = true; + _data.parent = undefined; // remove parent reference + + // exit or we loop forever + break; + } + + ancestor = ancestor.parent(); + } + + if (!selfAsParent) { + // connect with children + parent[0]._private.children.push(node); + node._private.parent = parent[0]; + + // let the core know we have a compound graph + cy_p.hasCompoundNodes = true; + } + } // else + } // if specified parent + } // for each node + + if (elements.length > 0) { + var restored = new Collection(cy, elements); + + for (var _i4 = 0; _i4 < restored.length; _i4++) { + var _ele2 = restored[_i4]; + + if (_ele2.isNode()) { + continue; + } + + // adding an edge invalidates the traversal caches for the parallel edges + _ele2.parallelEdges().clearTraversalCache(); + + // adding an edge invalidates the traversal cache for the connected nodes + _ele2.source().clearTraversalCache(); + _ele2.target().clearTraversalCache(); + } + + var toUpdateStyle = void 0; + + if (cy_p.hasCompoundNodes) { + toUpdateStyle = cy.collection().merge(restored).merge(restored.connectedNodes()).merge(restored.parent()); + } else { + toUpdateStyle = restored; + } + + toUpdateStyle.dirtyCompoundBoundsCache().updateStyle(notifyRenderer); + + if (notifyRenderer) { + restored.emitAndNotify('add'); + } else { + restored.emit('add'); + } + } + + return self; // chainability +}; + +elesfn.removed = function () { + var ele = this[0]; + return ele && ele._private.removed; +}; + +elesfn.inside = function () { + var ele = this[0]; + return ele && !ele._private.removed; +}; + +elesfn.remove = function (notifyRenderer) { + var self = this; + var removed = []; + var elesToRemove = []; + var elesToRemoveIds = {}; + var cy = self._private.cy; + + if (notifyRenderer === undefined) { + notifyRenderer = true; + } + + // add connected edges + function addConnectedEdges(node) { + var edges = node._private.edges; + for (var i = 0; i < edges.length; i++) { + add(edges[i]); + } + } + + // add descendant nodes + function addChildren(node) { + var children = node._private.children; + + for (var i = 0; i < children.length; i++) { + add(children[i]); + } + } + + function add(ele) { + var alreadyAdded = elesToRemoveIds[ele.id()]; + if (ele.removed() || alreadyAdded) { + return; + } else { + elesToRemoveIds[ele.id()] = true; + } + + if (ele.isNode()) { + elesToRemove.push(ele); // nodes are removed last + + addConnectedEdges(ele); + addChildren(ele); + } else { + elesToRemove.unshift(ele); // edges are removed first + } + } + + // make the list of elements to remove + // (may be removing more than specified due to connected edges etc) + + for (var i = 0, l = self.length; i < l; i++) { + var ele = self[i]; + + add(ele); + } + + function removeEdgeRef(node, edge) { + var connectedEdges = node._private.edges; + + util.removeFromArray(connectedEdges, edge); + + // removing an edges invalidates the traversal cache for its nodes + node.clearTraversalCache(); + } + + function removeParallelRefs(edge) { + // removing an edge invalidates the traversal caches for the parallel edges + edge.parallelEdges().clearTraversalCache(); + } + + var alteredParents = []; + alteredParents.ids = {}; + + function removeChildRef(parent, ele) { + ele = ele[0]; + parent = parent[0]; + + var children = parent._private.children; + var pid = parent.id(); + + util.removeFromArray(children, ele); + + if (!alteredParents.ids[pid]) { + alteredParents.ids[pid] = true; + alteredParents.push(parent); + } + } + + self.dirtyCompoundBoundsCache(); + + cy.removeFromPool(elesToRemove); // remove from core pool + + for (var _i5 = 0; _i5 < elesToRemove.length; _i5++) { + var _ele3 = elesToRemove[_i5]; + + // mark as removed + _ele3._private.removed = true; + + // add to list of removed elements + removed.push(_ele3); + + if (_ele3.isEdge()) { + // remove references to this edge in its connected nodes + var src = _ele3.source()[0]; + var tgt = _ele3.target()[0]; + + removeEdgeRef(src, _ele3); + removeEdgeRef(tgt, _ele3); + removeParallelRefs(_ele3); + } else { + // remove reference to parent + var parent = _ele3.parent(); + + if (parent.length !== 0) { + removeChildRef(parent, _ele3); + } + } + } + + // check to see if we have a compound graph or not + var elesStillInside = cy._private.elements; + cy._private.hasCompoundNodes = false; + for (var _i6 = 0; _i6 < elesStillInside.length; _i6++) { + var _ele4 = elesStillInside[_i6]; + + if (_ele4.isParent()) { + cy._private.hasCompoundNodes = true; + break; + } + } + + var removedElements = new Collection(this.cy(), removed); + if (removedElements.size() > 0) { + // must manually notify since trigger won't do this automatically once removed + + if (notifyRenderer) { + this.cy().notify({ + type: 'remove', + eles: removedElements + }); + } + + removedElements.emit('remove'); + } + + // the parents who were modified by the removal need their style updated + for (var _i7 = 0; _i7 < alteredParents.length; _i7++) { + var _ele5 = alteredParents[_i7]; + + if (!_ele5.removed()) { + _ele5.updateStyle(); + } + } + + return new Collection(cy, removed); +}; + +elesfn.move = function (struct) { + var cy = this._private.cy; + + if (struct.source !== undefined || struct.target !== undefined) { + var srcId = struct.source; + var tgtId = struct.target; + var srcExists = cy.hasElementWithId(srcId); + var tgtExists = cy.hasElementWithId(tgtId); + + if (srcExists || tgtExists) { + var jsons = this.jsons(); + + this.remove(); + + for (var i = 0; i < jsons.length; i++) { + var json = jsons[i]; + var ele = this[i]; + + if (json.group === 'edges') { + if (srcExists) { + json.data.source = srcId; + } + + if (tgtExists) { + json.data.target = tgtId; + } + + json.scratch = ele._private.scratch; + } + } + + return cy.add(jsons); + } + } else if (struct.parent !== undefined) { + // move node to new parent + var parentId = struct.parent; + var parentExists = parentId === null || cy.hasElementWithId(parentId); + + if (parentExists) { + var _jsons = this.jsons(); + var descs = this.descendants(); + var descsEtcJsons = descs.union(descs.union(this).connectedEdges()).jsons(); + + this.remove(); // NB: also removes descendants and their connected edges + + for (var _i8 = 0; _i8 < _jsons.length; _i8++) { + var _json = _jsons[_i8]; + var _ele6 = this[_i8]; + + if (_json.group === 'nodes') { + _json.data.parent = parentId === null ? undefined : parentId; + + _json.scratch = _ele6._private.scratch; + } + } + + return cy.add(_jsons.concat(descsEtcJsons)); + } + } + + return this; // if nothing done +}; + +[__webpack_require__(29), __webpack_require__(43), __webpack_require__(48), __webpack_require__(49), __webpack_require__(54), __webpack_require__(55), __webpack_require__(56), __webpack_require__(57), __webpack_require__(62), __webpack_require__(63), __webpack_require__(64), __webpack_require__(7), __webpack_require__(65), __webpack_require__(66), __webpack_require__(67), __webpack_require__(68), __webpack_require__(69)].forEach(function (props) { + util.extend(elesfn, props); +}); + +module.exports = Collection; + +/***/ }), +/* 8 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +/* global Set */ + +var undef = true ? 'undefined' : _typeof(undefined); + +var ObjectSet = function () { + function ObjectSet(arrayOrObjectSet) { + _classCallCheck(this, ObjectSet); + + this._obj = Object.create(null); + + if (arrayOrObjectSet != null) { + var arr = void 0; + + if (arrayOrObjectSet.instanceString != null && arrayOrObjectSet.instanceString() === this.instanceString()) { + arr = arrayOrObjectSet.toArray(); + } else { + arr = arrayOrObjectSet; + } + + for (var i = 0; i < arr.length; i++) { + this.add(arr[i]); + } + } + } + + _createClass(ObjectSet, [{ + key: 'instanceString', + value: function instanceString() { + return 'set'; + } + }, { + key: 'add', + value: function add(val) { + this._obj[val] = 1; + } + }, { + key: 'delete', + value: function _delete(val) { + this._obj[val] = 0; + } + }, { + key: 'clear', + value: function clear() { + this._obj = Object.create(null); + } + }, { + key: 'has', + value: function has(val) { + return this._obj[val] === 1; + } + }, { + key: 'toArray', + value: function toArray() { + var _this = this; + + return Object.keys(this._obj).filter(function (key) { + return _this.has(key); + }); + } + }, { + key: 'forEach', + value: function forEach(callback, thisArg) { + return this.toArray().forEach(callback, thisArg); + } + }, { + key: 'size', + get: function get() { + return this.toArray().length; + } + }]); + + return ObjectSet; +}(); + +// TODO use the stdlib Set in future... +// module.exports = typeof Set !== undef ? Set : ObjectSet; + + +module.exports = ObjectSet; + +/***/ }), +/* 9 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = __webpack_require__(32); + +/***/ }), +/* 10 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +// storage for parsed queries +var newQuery = function newQuery() { + return { + classes: [], + colonSelectors: [], + data: [], + group: null, + ids: [], + meta: [], + + // fake selectors + collection: null, // a collection to match against + filter: null, // filter function + + // these are defined in the upward direction rather than down (e.g. child) + // because we need to go up in Selector.filter() + parent: null, // parent query obj + ancestor: null, // ancestor query obj + subject: null, // defines subject in compound query (subject query obj; points to self if subject) + + // use these only when subject has been defined + child: null, + descendant: null + }; +}; + +module.exports = newQuery; + +/***/ }), +/* 11 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var util = __webpack_require__(1); +var is = __webpack_require__(0); +var Event = __webpack_require__(16); + +var eventRegex = /^([^.]+)(\.(?:[^.]+))?$/; // regex for matching event strings (e.g. "click.namespace") +var universalNamespace = '.*'; // matches as if no namespace specified and prevents users from unbinding accidentally + +var defaults = { + qualifierCompare: function qualifierCompare(q1, q2) { + return q1 === q2; + }, + eventMatches: function eventMatches() /*context, listener, eventObj*/{ + return true; + }, + eventFields: function eventFields() /*context*/{ + return {}; + }, + callbackContext: function callbackContext(context /*, listener, eventObj*/) { + return context; + }, + beforeEmit: function beforeEmit() /* context, listener, eventObj */{}, + afterEmit: function afterEmit() /* context, listener, eventObj */{}, + bubble: function bubble() /*context*/{ + return false; + }, + parent: function parent() /*context*/{ + return null; + }, + context: undefined +}; + +function Emitter(opts) { + util.assign(this, defaults, opts); + + this.listeners = []; + this.emitting = 0; +} + +var p = Emitter.prototype; + +var forEachEvent = function forEachEvent(self, handler, events, qualifier, callback, conf, confOverrides) { + if (is.fn(qualifier)) { + callback = qualifier; + qualifier = null; + } + + if (confOverrides) { + if (conf == null) { + conf = confOverrides; + } else { + conf = util.assign({}, conf, confOverrides); + } + } + + var eventList = events.split(/\s+/); + + for (var i = 0; i < eventList.length; i++) { + var evt = eventList[i]; + + if (is.emptyString(evt)) { + continue; + } + + var match = evt.match(eventRegex); // type[.namespace] + + if (match) { + var type = match[1]; + var namespace = match[2] ? match[2] : null; + var ret = handler(self, evt, type, namespace, qualifier, callback, conf); + + if (ret === false) { + break; + } // allow exiting early + } + } +}; + +var makeEventObj = function makeEventObj(self, obj) { + return new Event(obj.type, util.assign(obj, self.eventFields(self.context))); +}; + +var forEachEventObj = function forEachEventObj(self, handler, events) { + if (is.event(events)) { + handler(self, events); + + return; + } else if (is.plainObject(events)) { + handler(self, makeEventObj(self, events)); + + return; + } + + var eventList = events.split(/\s+/); + + for (var i = 0; i < eventList.length; i++) { + var evt = eventList[i]; + + if (is.emptyString(evt)) { + continue; + } + + var match = evt.match(eventRegex); // type[.namespace] + + if (match) { + var type = match[1]; + var namespace = match[2] ? match[2] : null; + var eventObj = makeEventObj(self, { + type: type, + namespace: namespace, + target: self.context + }); + + handler(self, eventObj); + } + } +}; + +p.on = p.addListener = function (events, qualifier, callback, conf, confOverrides) { + forEachEvent(this, function (self, event, type, namespace, qualifier, callback, conf) { + if (is.fn(callback)) { + self.listeners.push({ + event: event, // full event string + callback: callback, // callback to run + type: type, // the event type (e.g. 'click') + namespace: namespace, // the event namespace (e.g. ".foo") + qualifier: qualifier, // a restriction on whether to match this emitter + conf: conf // additional configuration + }); + } + }, events, qualifier, callback, conf, confOverrides); + + return this; +}; + +p.one = function (events, qualifier, callback, conf) { + return this.on(events, qualifier, callback, conf, { one: true }); +}; + +p.removeListener = p.off = function (events, qualifier, callback, conf) { + var _this = this; + + if (this.emitting !== 0) { + this.listeners = util.copyArray(this.listeners); + } + + var listeners = this.listeners; + + var _loop = function _loop(i) { + var listener = listeners[i]; + + forEachEvent(_this, function (self, event, type, namespace, qualifier, callback /*, conf*/) { + if (listener.type === type && (!namespace || listener.namespace === namespace) && (!qualifier || self.qualifierCompare(listener.qualifier, qualifier)) && (!callback || listener.callback === callback)) { + listeners.splice(i, 1); + + return false; + } + }, events, qualifier, callback, conf); + }; + + for (var i = listeners.length - 1; i >= 0; i--) { + _loop(i); + } + + return this; +}; + +p.emit = p.trigger = function (events, extraParams, manualCallback) { + var listeners = this.listeners; + var numListenersBeforeEmit = listeners.length; + + this.emitting++; + + if (!is.array(extraParams)) { + extraParams = [extraParams]; + } + + forEachEventObj(this, function (self, eventObj) { + if (manualCallback != null) { + listeners = [{ + event: eventObj.event, + type: eventObj.type, + namespace: eventObj.namespace, + callback: manualCallback + }]; + + numListenersBeforeEmit = listeners.length; + } + + var _loop2 = function _loop2(i) { + var listener = listeners[i]; + + if (listener.type === eventObj.type && (!listener.namespace || listener.namespace === eventObj.namespace || listener.namespace === universalNamespace) && self.eventMatches(self.context, listener, eventObj)) { + var args = [eventObj]; + + if (extraParams != null) { + util.push(args, extraParams); + } + + self.beforeEmit(self.context, listener, eventObj); + + if (listener.conf && listener.conf.one) { + self.listeners = self.listeners.filter(function (l) { + return l !== listener; + }); + } + + var context = self.callbackContext(self.context, listener, eventObj); + var ret = listener.callback.apply(context, args); + + self.afterEmit(self.context, listener, eventObj); + + if (ret === false) { + eventObj.stopPropagation(); + eventObj.preventDefault(); + } + } // if listener matches + }; + + for (var i = 0; i < numListenersBeforeEmit; i++) { + _loop2(i); + } // for listener + + if (self.bubble(self.context) && !eventObj.isPropagationStopped()) { + self.parent(self.context).emit(eventObj, extraParams); + } + }, events); + + this.emitting--; + + return this; +}; + +module.exports = Emitter; + +/***/ }), +/* 12 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var window = __webpack_require__(3); +var util = __webpack_require__(1); +var Collection = __webpack_require__(7); +var is = __webpack_require__(0); +var Promise = __webpack_require__(5); +var define = __webpack_require__(4); + +var Core = function Core(opts) { + var cy = this; + + opts = util.extend({}, opts); + + var container = opts.container; + + // allow for passing a wrapped jquery object + // e.g. cytoscape({ container: $('#cy') }) + if (container && !is.htmlElement(container) && is.htmlElement(container[0])) { + container = container[0]; + } + + var reg = container ? container._cyreg : null; // e.g. already registered some info (e.g. readies) via jquery + reg = reg || {}; + + if (reg && reg.cy) { + reg.cy.destroy(); + + reg = {}; // old instance => replace reg completely + } + + var readies = reg.readies = reg.readies || []; + + if (container) { + container._cyreg = reg; + } // make sure container assoc'd reg points to this cy + reg.cy = cy; + + var head = window !== undefined && container !== undefined && !opts.headless; + var options = opts; + options.layout = util.extend({ name: head ? 'grid' : 'null' }, options.layout); + options.renderer = util.extend({ name: head ? 'canvas' : 'null' }, options.renderer); + + var defVal = function defVal(def, val, altVal) { + if (val !== undefined) { + return val; + } else if (altVal !== undefined) { + return altVal; + } else { + return def; + } + }; + + var _p = this._private = { + container: container, // html dom ele container + ready: false, // whether ready has been triggered + options: options, // cached options + elements: new Collection(this), // elements in the graph + listeners: [], // list of listeners + aniEles: new Collection(this), // elements being animated + scratch: {}, // scratch object for core + layout: null, + renderer: null, + destroyed: false, // whether destroy was called + notificationsEnabled: true, // whether notifications are sent to the renderer + minZoom: 1e-50, + maxZoom: 1e50, + zoomingEnabled: defVal(true, options.zoomingEnabled), + userZoomingEnabled: defVal(true, options.userZoomingEnabled), + panningEnabled: defVal(true, options.panningEnabled), + userPanningEnabled: defVal(true, options.userPanningEnabled), + boxSelectionEnabled: defVal(true, options.boxSelectionEnabled), + autolock: defVal(false, options.autolock, options.autolockNodes), + autoungrabify: defVal(false, options.autoungrabify, options.autoungrabifyNodes), + autounselectify: defVal(false, options.autounselectify), + styleEnabled: options.styleEnabled === undefined ? head : options.styleEnabled, + zoom: is.number(options.zoom) ? options.zoom : 1, + pan: { + x: is.plainObject(options.pan) && is.number(options.pan.x) ? options.pan.x : 0, + y: is.plainObject(options.pan) && is.number(options.pan.y) ? options.pan.y : 0 + }, + animation: { // object for currently-running animations + current: [], + queue: [] + }, + hasCompoundNodes: false + }; + + this.createEmitter(); + + // set selection type + var selType = options.selectionType; + if (selType === undefined || selType !== 'additive' && selType !== 'single') { + // then set default + + _p.selectionType = 'single'; + } else { + _p.selectionType = selType; + } + + // init zoom bounds + if (is.number(options.minZoom) && is.number(options.maxZoom) && options.minZoom < options.maxZoom) { + _p.minZoom = options.minZoom; + _p.maxZoom = options.maxZoom; + } else if (is.number(options.minZoom) && options.maxZoom === undefined) { + _p.minZoom = options.minZoom; + } else if (is.number(options.maxZoom) && options.minZoom === undefined) { + _p.maxZoom = options.maxZoom; + } + + var loadExtData = function loadExtData(extData, next) { + var anyIsPromise = extData.some(is.promise); + + if (anyIsPromise) { + return Promise.all(extData).then(next); // load all data asynchronously, then exec rest of init + } else { + next(extData); // exec synchronously for convenience + } + }; + + // start with the default stylesheet so we have something before loading an external stylesheet + if (_p.styleEnabled) { + cy.setStyle([]); + } + + // create the renderer + cy.initRenderer(util.extend({ + hideEdgesOnViewport: options.hideEdgesOnViewport, + textureOnViewport: options.textureOnViewport, + wheelSensitivity: is.number(options.wheelSensitivity) && options.wheelSensitivity > 0 ? options.wheelSensitivity : 1, + motionBlur: options.motionBlur === undefined ? false : options.motionBlur, // off by default + motionBlurOpacity: options.motionBlurOpacity === undefined ? 0.05 : options.motionBlurOpacity, + pixelRatio: is.number(options.pixelRatio) && options.pixelRatio > 0 ? options.pixelRatio : undefined, + desktopTapThreshold: options.desktopTapThreshold === undefined ? 4 : options.desktopTapThreshold, + touchTapThreshold: options.touchTapThreshold === undefined ? 8 : options.touchTapThreshold + }, options.renderer)); + + var setElesAndLayout = function setElesAndLayout(elements, onload, ondone) { + cy.notifications(false); + + // remove old elements + var oldEles = cy.mutableElements(); + if (oldEles.length > 0) { + oldEles.remove(); + } + + if (elements != null) { + if (is.plainObject(elements) || is.array(elements)) { + cy.add(elements); + } + } + + cy.one('layoutready', function (e) { + cy.notifications(true); + cy.emit(e); // we missed this event by turning notifications off, so pass it on + + cy.notify({ + type: 'load', + eles: cy.mutableElements() + }); + + cy.one('load', onload); + cy.emit('load'); + }).one('layoutstop', function () { + cy.one('done', ondone); + cy.emit('done'); + }); + + var layoutOpts = util.extend({}, cy._private.options.layout); + layoutOpts.eles = cy.elements(); + + cy.layout(layoutOpts).run(); + }; + + loadExtData([options.style, options.elements], function (thens) { + var initStyle = thens[0]; + var initEles = thens[1]; + + // init style + if (_p.styleEnabled) { + cy.style().append(initStyle); + } + + // initial load + setElesAndLayout(initEles, function () { + // onready + cy.startAnimationLoop(); + _p.ready = true; + + // if a ready callback is specified as an option, the bind it + if (is.fn(options.ready)) { + cy.on('ready', options.ready); + } + + // bind all the ready handlers registered before creating this instance + for (var i = 0; i < readies.length; i++) { + var fn = readies[i]; + cy.on('ready', fn); + } + if (reg) { + reg.readies = []; + } // clear b/c we've bound them all and don't want to keep it around in case a new core uses the same div etc + + cy.emit('ready'); + }, options.done); + }); +}; + +var corefn = Core.prototype; // short alias + +util.extend(corefn, { + instanceString: function instanceString() { + return 'core'; + }, + + isReady: function isReady() { + return this._private.ready; + }, + + isDestroyed: function isDestroyed() { + return this._private.destroyed; + }, + + ready: function ready(fn) { + if (this.isReady()) { + this.emitter().emit('ready', [], fn); // just calls fn as though triggered via ready event + } else { + this.on('ready', fn); + } + + return this; + }, + + destroy: function destroy() { + var cy = this; + if (cy.isDestroyed()) return; + + cy.stopAnimationLoop(); + + cy.destroyRenderer(); + + this.emit('destroy'); + + cy._private.destroyed = true; + + return cy; + }, + + hasElementWithId: function hasElementWithId(id) { + return this._private.elements.hasElementWithId(id); + }, + + getElementById: function getElementById(id) { + return this._private.elements.getElementById(id); + }, + + selectionType: function selectionType() { + return this._private.selectionType; + }, + + hasCompoundNodes: function hasCompoundNodes() { + return this._private.hasCompoundNodes; + }, + + headless: function headless() { + return this._private.options.renderer.name === 'null'; + }, + + styleEnabled: function styleEnabled() { + return this._private.styleEnabled; + }, + + addToPool: function addToPool(eles) { + this._private.elements.merge(eles); + + return this; // chaining + }, + + removeFromPool: function removeFromPool(eles) { + this._private.elements.unmerge(eles); + + return this; + }, + + container: function container() { + return this._private.container; + }, + + options: function options() { + return util.copy(this._private.options); + }, + + json: function json(obj) { + var cy = this; + var _p = cy._private; + var eles = cy.mutableElements(); + + if (is.plainObject(obj)) { + // set + + cy.startBatch(); + + if (obj.elements) { + var idInJson = {}; + + var updateEles = function updateEles(jsons, gr) { + var toAdd = []; + + for (var i = 0; i < jsons.length; i++) { + var json = jsons[i]; + var id = json.data.id; + var ele = cy.getElementById(id); + + idInJson[id] = true; + + if (ele.length !== 0) { + // existing element should be updated + ele.json(json); + } else { + // otherwise should be added + if (gr) { + toAdd.push(util.extend({ group: gr }, json)); + } else { + toAdd.push(json); + } + } + } + + cy.add(toAdd); + }; + + if (is.array(obj.elements)) { + // elements: [] + updateEles(obj.elements); + } else { + // elements: { nodes: [], edges: [] } + var grs = ['nodes', 'edges']; + for (var i = 0; i < grs.length; i++) { + var gr = grs[i]; + var elements = obj.elements[gr]; + + if (is.array(elements)) { + updateEles(elements, gr); + } + } + } + + // elements not specified in json should be removed + eles.stdFilter(function (ele) { + return !idInJson[ele.id()]; + }).remove(); + } + + if (obj.style) { + cy.style(obj.style); + } + + if (obj.zoom != null && obj.zoom !== _p.zoom) { + cy.zoom(obj.zoom); + } + + if (obj.pan) { + if (obj.pan.x !== _p.pan.x || obj.pan.y !== _p.pan.y) { + cy.pan(obj.pan); + } + } + + var fields = ['minZoom', 'maxZoom', 'zoomingEnabled', 'userZoomingEnabled', 'panningEnabled', 'userPanningEnabled', 'boxSelectionEnabled', 'autolock', 'autoungrabify', 'autounselectify']; + + for (var _i = 0; _i < fields.length; _i++) { + var f = fields[_i]; + + if (obj[f] != null) { + cy[f](obj[f]); + } + } + + cy.endBatch(); + + return this; // chaining + } else if (obj === undefined) { + // get + var json = {}; + + json.elements = {}; + eles.forEach(function (ele) { + var group = ele.group(); + + if (!json.elements[group]) { + json.elements[group] = []; + } + + json.elements[group].push(ele.json()); + }); + + if (this._private.styleEnabled) { + json.style = cy.style().json(); + } + + json.zoomingEnabled = cy._private.zoomingEnabled; + json.userZoomingEnabled = cy._private.userZoomingEnabled; + json.zoom = cy._private.zoom; + json.minZoom = cy._private.minZoom; + json.maxZoom = cy._private.maxZoom; + json.panningEnabled = cy._private.panningEnabled; + json.userPanningEnabled = cy._private.userPanningEnabled; + json.pan = util.copy(cy._private.pan); + json.boxSelectionEnabled = cy._private.boxSelectionEnabled; + json.renderer = util.copy(cy._private.options.renderer); + json.hideEdgesOnViewport = cy._private.options.hideEdgesOnViewport; + json.textureOnViewport = cy._private.options.textureOnViewport; + json.wheelSensitivity = cy._private.options.wheelSensitivity; + json.motionBlur = cy._private.options.motionBlur; + + return json; + } + }, + + scratch: define.data({ + field: 'scratch', + bindingEvent: 'scratch', + allowBinding: true, + allowSetting: true, + settingEvent: 'scratch', + settingTriggersEvent: true, + triggerFnName: 'trigger', + allowGetting: true + }), + + removeScratch: define.removeData({ + field: 'scratch', + event: 'scratch', + triggerFnName: 'trigger', + triggerEvent: true + }) + +}); + +corefn.$id = corefn.getElementById; + +[__webpack_require__(70), __webpack_require__(71), __webpack_require__(79), __webpack_require__(80), __webpack_require__(81), __webpack_require__(82), __webpack_require__(83), __webpack_require__(84), __webpack_require__(85), __webpack_require__(94)].forEach(function (props) { + util.extend(corefn, props); +}); + +module.exports = Core; + +/***/ }), +/* 13 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = function memoize(fn, keyFn) { + if (!keyFn) { + keyFn = function keyFn() { + if (arguments.length === 1) { + return arguments[0]; + } else if (arguments.length === 0) { + return 'undefined'; + } + + var args = []; + + for (var i = 0; i < arguments.length; i++) { + args.push(arguments[i]); + } + + return args.join('$'); + }; + } + + var memoizedFn = function memoizedFn() { + var self = this; + var args = arguments; + var ret = void 0; + var k = keyFn.apply(self, args); + var cache = memoizedFn.cache; + + if (!(ret = cache[k])) { + ret = cache[k] = fn.apply(self, args); + } + + return ret; + }; + + memoizedFn.cache = {}; + + return memoizedFn; +}; + +/***/ }), +/* 14 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var util = __webpack_require__(1); +var is = __webpack_require__(0); +var Set = __webpack_require__(8); + +// represents a node or an edge +var Element = function Element(cy, params, restore) { + restore = restore === undefined || restore ? true : false; + + if (cy === undefined || params === undefined || !is.core(cy)) { + util.error('An element must have a core reference and parameters set'); + return; + } + + var group = params.group; + + // try to automatically infer the group if unspecified + if (group == null) { + if (params.data && params.data.source != null && params.data.target != null) { + group = 'edges'; + } else { + group = 'nodes'; + } + } + + // validate group + if (group !== 'nodes' && group !== 'edges') { + util.error('An element must be of type `nodes` or `edges`; you specified `' + group + '`'); + return; + } + + // make the element array-like, just like a collection + this.length = 1; + this[0] = this; + + // NOTE: when something is added here, add also to ele.json() + var _p = this._private = { + cy: cy, + single: true, // indicates this is an element + data: params.data || {}, // data object + position: params.position || {}, // (x, y) position pair + autoWidth: undefined, // width and height of nodes calculated by the renderer when set to special 'auto' value + autoHeight: undefined, + autoPadding: undefined, + compoundBoundsClean: false, // whether the compound dimensions need to be recalculated the next time dimensions are read + listeners: [], // array of bound listeners + group: group, // string; 'nodes' or 'edges' + style: {}, // properties as set by the style + rstyle: {}, // properties for style sent from the renderer to the core + styleCxts: [], // applied style contexts from the styler + removed: true, // whether it's inside the vis; true if removed (set true here since we call restore) + selected: params.selected ? true : false, // whether it's selected + selectable: params.selectable === undefined ? true : params.selectable ? true : false, // whether it's selectable + locked: params.locked ? true : false, // whether the element is locked (cannot be moved) + grabbed: false, // whether the element is grabbed by the mouse; renderer sets this privately + grabbable: params.grabbable === undefined ? true : params.grabbable ? true : false, // whether the element can be grabbed + active: false, // whether the element is active from user interaction + classes: new Set(), // map ( className => true ) + animation: { // object for currently-running animations + current: [], + queue: [] + }, + rscratch: {}, // object in which the renderer can store information + scratch: params.scratch || {}, // scratch objects + edges: [], // array of connected edges + children: [], // array of children + parent: null, // parent ref + traversalCache: {}, // cache of output of traversal functions + backgrounding: false // whether background images are loading + }; + + // renderedPosition overrides if specified + if (params.renderedPosition) { + var rpos = params.renderedPosition; + var pan = cy.pan(); + var zoom = cy.zoom(); + + _p.position = { + x: (rpos.x - pan.x) / zoom, + y: (rpos.y - pan.y) / zoom + }; + } + + if (is.string(params.classes)) { + var classes = params.classes.split(/\s+/); + for (var i = 0, l = classes.length; i < l; i++) { + var cls = classes[i]; + if (!cls || cls === '') { + continue; + } + + _p.classes.add(cls); + } + } + + if (params.style || params.css) { + cy.style().applyBypass(this, params.style || params.css); + } + + this.createEmitter(); + + if (restore === undefined || restore) { + this.restore(); + } +}; + +module.exports = Element; + +/***/ }), +/* 15 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var util = __webpack_require__(1); + +var stateSelectors = [{ + selector: ':selected', + matches: function matches(ele) { + return ele.selected(); + } +}, { + selector: ':unselected', + matches: function matches(ele) { + return !ele.selected(); + } +}, { + selector: ':selectable', + matches: function matches(ele) { + return ele.selectable(); + } +}, { + selector: ':unselectable', + matches: function matches(ele) { + return !ele.selectable(); + } +}, { + selector: ':locked', + matches: function matches(ele) { + return ele.locked(); + } +}, { + selector: ':unlocked', + matches: function matches(ele) { + return !ele.locked(); + } +}, { + selector: ':visible', + matches: function matches(ele) { + return ele.visible(); + } +}, { + selector: ':hidden', + matches: function matches(ele) { + return !ele.visible(); + } +}, { + selector: ':transparent', + matches: function matches(ele) { + return ele.transparent(); + } +}, { + selector: ':grabbed', + matches: function matches(ele) { + return ele.grabbed(); + } +}, { + selector: ':free', + matches: function matches(ele) { + return !ele.grabbed(); + } +}, { + selector: ':removed', + matches: function matches(ele) { + return ele.removed(); + } +}, { + selector: ':inside', + matches: function matches(ele) { + return !ele.removed(); + } +}, { + selector: ':grabbable', + matches: function matches(ele) { + return ele.grabbable(); + } +}, { + selector: ':ungrabbable', + matches: function matches(ele) { + return !ele.grabbable(); + } +}, { + selector: ':animated', + matches: function matches(ele) { + return ele.animated(); + } +}, { + selector: ':unanimated', + matches: function matches(ele) { + return !ele.animated(); + } +}, { + selector: ':parent', + matches: function matches(ele) { + return ele.isParent(); + } +}, { + selector: ':childless', + matches: function matches(ele) { + return ele.isChildless(); + } +}, { + selector: ':child', + matches: function matches(ele) { + return ele.isChild(); + } +}, { + selector: ':orphan', + matches: function matches(ele) { + return ele.isOrphan(); + } +}, { + selector: ':nonorphan', + matches: function matches(ele) { + return ele.isChild(); + } +}, { + selector: ':loop', + matches: function matches(ele) { + return ele.isLoop(); + } +}, { + selector: ':simple', + matches: function matches(ele) { + return ele.isSimple(); + } +}, { + selector: ':active', + matches: function matches(ele) { + return ele.active(); + } +}, { + selector: ':inactive', + matches: function matches(ele) { + return !ele.active(); + } +}, { + selector: ':backgrounding', + matches: function matches(ele) { + return ele.backgrounding(); + } +}, { + selector: ':nonbackgrounding', + matches: function matches(ele) { + return !ele.backgrounding(); + } +}].sort(function (a, b) { + // n.b. selectors that are starting substrings of others must have the longer ones first + return util.sort.descending(a.selector, b.selector); +}); + +var stateSelectorMatches = function stateSelectorMatches(sel, ele) { + var lookup = stateSelectorMatches.lookup = stateSelectorMatches.lookup || function () { + var selToFn = {}; + var s = void 0; + + for (var i = 0; i < stateSelectors.length; i++) { + s = stateSelectors[i]; + + selToFn[s.selector] = s.matches; + } + + return selToFn; + }(); + + return lookup[sel](ele); +}; + +var stateSelectorRegex = '(' + stateSelectors.map(function (s) { + return s.selector; +}).join('|') + ')'; + +module.exports = { stateSelectors: stateSelectors, stateSelectorMatches: stateSelectorMatches, stateSelectorRegex: stateSelectorRegex }; + +/***/ }), +/* 16 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/*! +Event object based on jQuery events, MIT license + +https://jquery.org/license/ +https://tldrlegal.com/license/mit-license +https://github.com/jquery/jquery/blob/master/src/event.js +*/ + +var Event = function Event(src, props) { + this.recycle(src, props); +}; + +function returnFalse() { + return false; +} + +function returnTrue() { + return true; +} + +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +Event.prototype = { + instanceString: function instanceString() { + return 'event'; + }, + + recycle: function recycle(src, props) { + this.isImmediatePropagationStopped = this.isPropagationStopped = this.isDefaultPrevented = returnFalse; + + if (src != null && src.preventDefault) { + // Browser Event object + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented ? returnTrue : returnFalse; + } else if (src != null && src.type) { + // Plain object containing all event details + props = src; + } else { + // Event string + this.type = src; + } + + // Put explicitly provided properties onto the event object + if (props != null) { + // more efficient to manually copy fields we use + this.originalEvent = props.originalEvent; + this.type = props.type != null ? props.type : this.type; + this.cy = props.cy; + this.target = props.target; + this.position = props.position; + this.renderedPosition = props.renderedPosition; + this.namespace = props.namespace; + this.layout = props.layout; + } + + if (this.cy != null && this.position != null && this.renderedPosition == null) { + // create a rendered position based on the passed position + var pos = this.position; + var zoom = this.cy.zoom(); + var pan = this.cy.pan(); + + this.renderedPosition = { + x: pos.x * zoom + pan.x, + y: pos.y * zoom + pan.y + }; + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + }, + + preventDefault: function preventDefault() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if (!e) { + return; + } + + // if preventDefault exists run it on the original event + if (e.preventDefault) { + e.preventDefault(); + } + }, + + stopPropagation: function stopPropagation() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if (!e) { + return; + } + + // if stopPropagation exists run it on the original event + if (e.stopPropagation) { + e.stopPropagation(); + } + }, + + stopImmediatePropagation: function stopImmediatePropagation() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +module.exports = Event; + +/***/ }), +/* 17 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/** + * Elements are drawn in a specific order based on compound depth (low to high), the element type (nodes above edges), + * and z-index (low to high). These styles affect how this applies: + * + * z-compound-depth: May be `bottom | orphan | auto | top`. The first drawn is `bottom`, then `orphan` which is the + * same depth as the root of the compound graph, followed by the default value `auto` which draws in order from + * root to leaves of the compound graph. The last drawn is `top`. + * z-index-compare: May be `auto | manual`. The default value is `auto` which always draws edges under nodes. + * `manual` ignores this convention and draws based on the `z-index` value setting. + * z-index: An integer value that affects the relative draw order of elements. In general, an element with a higher + * `z-index` will be drawn on top of an element with a lower `z-index`. + */ +var util = __webpack_require__(1); + +var zIndexSort = function zIndexSort(a, b) { + var cy = a.cy(); + var hasCompoundNodes = cy.hasCompoundNodes(); + + function getDepth(ele) { + var style = ele.pstyle('z-compound-depth'); + if (style.value === 'auto') { + return hasCompoundNodes ? ele.zDepth() : 0; + } else if (style.value === 'bottom') { + return -1; + } else if (style.value === 'top') { + return util.MAX_INT; + } + // 'orphan' + return 0; + } + var depthDiff = getDepth(a) - getDepth(b); + if (depthDiff !== 0) { + return depthDiff; + } + + function getEleDepth(ele) { + var style = ele.pstyle('z-index-compare'); + if (style.value === 'auto') { + return ele.isNode() ? 1 : 0; + } + // 'manual' + return 0; + } + var eleDiff = getEleDepth(a) - getEleDepth(b); + if (eleDiff !== 0) { + return eleDiff; + } + + var zDiff = a.pstyle('z-index').value - b.pstyle('z-index').value; + if (zDiff !== 0) { + return zDiff; + } + // compare indices in the core (order added to graph w/ last on top) + return a.poolIndex() - b.poolIndex(); +}; + +module.exports = zIndexSort; + +/***/ }), +/* 18 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var is = __webpack_require__(0); +var util = __webpack_require__(1); +var Selector = __webpack_require__(6); + +var Style = function Style(cy) { + + if (!(this instanceof Style)) { + return new Style(cy); + } + + if (!is.core(cy)) { + util.error('A style must have a core reference'); + return; + } + + this._private = { + cy: cy, + coreStyle: {} + }; + + this.length = 0; + + this.resetToDefault(); +}; + +var styfn = Style.prototype; + +styfn.instanceString = function () { + return 'style'; +}; + +// remove all contexts +styfn.clear = function () { + for (var i = 0; i < this.length; i++) { + this[i] = undefined; + } + this.length = 0; + + var _p = this._private; + + _p.newStyle = true; + + return this; // chaining +}; + +styfn.resetToDefault = function () { + this.clear(); + this.addDefaultStylesheet(); + + return this; +}; + +// builds a style object for the 'core' selector +styfn.core = function () { + return this._private.coreStyle; +}; + +// create a new context from the specified selector string and switch to that context +styfn.selector = function (selectorStr) { + // 'core' is a special case and does not need a selector + var selector = selectorStr === 'core' ? null : new Selector(selectorStr); + + var i = this.length++; // new context means new index + this[i] = { + selector: selector, + properties: [], + mappedProperties: [], + index: i + }; + + return this; // chaining +}; + +// add one or many css rules to the current context +styfn.css = function () { + var self = this; + var args = arguments; + + switch (args.length) { + case 1: + var map = args[0]; + + for (var i = 0; i < self.properties.length; i++) { + var prop = self.properties[i]; + var mapVal = map[prop.name]; + + if (mapVal === undefined) { + mapVal = map[util.dash2camel(prop.name)]; + } + + if (mapVal !== undefined) { + this.cssRule(prop.name, mapVal); + } + } + + break; + + case 2: + this.cssRule(args[0], args[1]); + break; + + default: + break; // do nothing if args are invalid + } + + return this; // chaining +}; +styfn.style = styfn.css; + +// add a single css rule to the current context +styfn.cssRule = function (name, value) { + // name-value pair + var property = this.parse(name, value); + + // add property to current context if valid + if (property) { + var i = this.length - 1; + this[i].properties.push(property); + this[i].properties[property.name] = property; // allow access by name as well + + if (property.name.match(/pie-(\d+)-background-size/) && property.value) { + this._private.hasPie = true; + } + + if (property.mapped) { + this[i].mappedProperties.push(property); + } + + // add to core style if necessary + var currentSelectorIsCore = !this[i].selector; + if (currentSelectorIsCore) { + this._private.coreStyle[property.name] = property; + } + } + + return this; // chaining +}; + +styfn.append = function (style) { + if (is.stylesheet(style)) { + style.appendToStyle(this); + } else if (is.array(style)) { + this.appendFromJson(style); + } else if (is.string(style)) { + this.appendFromString(style); + } // you probably wouldn't want to append a Style, since you'd duplicate the default parts + + return this; +}; + +// static function +Style.fromJson = function (cy, json) { + var style = new Style(cy); + + style.fromJson(json); + + return style; +}; + +Style.fromString = function (cy, string) { + return new Style(cy).fromString(string); +}; + +[__webpack_require__(86), __webpack_require__(87), __webpack_require__(88), __webpack_require__(89), __webpack_require__(90), __webpack_require__(91), __webpack_require__(92), __webpack_require__(93)].forEach(function (props) { + util.extend(styfn, props); +}); + +Style.types = styfn.types; +Style.properties = styfn.properties; + +module.exports = Style; + +/***/ }), +/* 19 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var util = __webpack_require__(1); + +var fullFpsTime = 1000 / 60; // assume 60 frames per second + +module.exports = { + setupDequeueing: function setupDequeueing(opts) { + return function setupDequeueingImpl() { + var self = this; + var r = this.renderer; + + if (self.dequeueingSetup) { + return; + } else { + self.dequeueingSetup = true; + } + + var queueRedraw = util.debounce(function () { + r.redrawHint('eles', true); + r.redrawHint('drag', true); + + r.redraw(); + }, opts.deqRedrawThreshold); + + var dequeue = function dequeue(willDraw, frameStartTime) { + var startTime = util.performanceNow(); + var avgRenderTime = r.averageRedrawTime; + var renderTime = r.lastRedrawTime; + var deqd = []; + var extent = r.cy.extent(); + var pixelRatio = r.getPixelRatio(); + + while (true) { + var now = util.performanceNow(); + var duration = now - startTime; + var frameDuration = now - frameStartTime; + + if (renderTime < fullFpsTime) { + // if we're rendering faster than the ideal fps, then do dequeueing + // during all of the remaining frame time + + var timeAvailable = fullFpsTime - (willDraw ? avgRenderTime : 0); + + if (frameDuration >= opts.deqFastCost * timeAvailable) { + break; + } + } else { + if (willDraw) { + if (duration >= opts.deqCost * renderTime || duration >= opts.deqAvgCost * avgRenderTime) { + break; + } + } else if (frameDuration >= opts.deqNoDrawCost * fullFpsTime) { + break; + } + } + + var thisDeqd = opts.deq(self, pixelRatio, extent); + + if (thisDeqd.length > 0) { + for (var i = 0; i < thisDeqd.length; i++) { + deqd.push(thisDeqd[i]); + } + } else { + break; + } + } + + // callbacks on dequeue + if (deqd.length > 0) { + opts.onDeqd(self, deqd); + + if (!willDraw && opts.shouldRedraw(self, deqd, pixelRatio, extent)) { + queueRedraw(); + } + } + }; + + var priority = opts.priority || util.noop; + + r.beforeRender(dequeue, priority(self)); + }; + } +}; + +/***/ }), +/* 20 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var is = __webpack_require__(0); +var Core = __webpack_require__(12); +var extension = __webpack_require__(95); +var Stylesheet = __webpack_require__(137); + +var cytoscape = function cytoscape(options) { + // jshint ignore:line + // if no options specified, use default + if (options === undefined) { + options = {}; + } + + // create instance + if (is.plainObject(options)) { + return new Core(options); + } + + // allow for registration of extensions + else if (is.string(options)) { + return extension.apply(extension, arguments); + } +}; + +// e.g. cytoscape.use( require('cytoscape-foo'), bar ) +cytoscape.use = function (ext) { + var args = Array.prototype.slice.call(arguments, 1); // args to pass to ext + + args.unshift(cytoscape); // cytoscape is first arg to ext + + ext.apply(null, args); + + return this; +}; + +// replaced by build system +cytoscape.version = __webpack_require__(138); + +// expose public apis (mostly for extensions) +cytoscape.stylesheet = cytoscape.Stylesheet = Stylesheet; + +module.exports = cytoscape; + +/***/ }), +/* 21 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var is = __webpack_require__(0); + +module.exports = { + // get [r, g, b] from #abc or #aabbcc + hex2tuple: function hex2tuple(hex) { + if (!(hex.length === 4 || hex.length === 7) || hex[0] !== '#') { + return; + } + + var shortHex = hex.length === 4; + var r = void 0, + g = void 0, + b = void 0; + var base = 16; + + if (shortHex) { + r = parseInt(hex[1] + hex[1], base); + g = parseInt(hex[2] + hex[2], base); + b = parseInt(hex[3] + hex[3], base); + } else { + r = parseInt(hex[1] + hex[2], base); + g = parseInt(hex[3] + hex[4], base); + b = parseInt(hex[5] + hex[6], base); + } + + return [r, g, b]; + }, + + // get [r, g, b, a] from hsl(0, 0, 0) or hsla(0, 0, 0, 0) + hsl2tuple: function hsl2tuple(hsl) { + var ret = void 0; + var h = void 0, + s = void 0, + l = void 0, + a = void 0, + r = void 0, + g = void 0, + b = void 0; + function hue2rgb(p, q, t) { + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1 / 6) return p + (q - p) * 6 * t; + if (t < 1 / 2) return q; + if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; + return p; + } + + var m = new RegExp('^' + this.regex.hsla + '$').exec(hsl); + if (m) { + + // get hue + h = parseInt(m[1]); + if (h < 0) { + h = (360 - -1 * h % 360) % 360; + } else if (h > 360) { + h = h % 360; + } + h /= 360; // normalise on [0, 1] + + s = parseFloat(m[2]); + if (s < 0 || s > 100) { + return; + } // saturation is [0, 100] + s = s / 100; // normalise on [0, 1] + + l = parseFloat(m[3]); + if (l < 0 || l > 100) { + return; + } // lightness is [0, 100] + l = l / 100; // normalise on [0, 1] + + a = m[4]; + if (a !== undefined) { + a = parseFloat(a); + + if (a < 0 || a > 1) { + return; + } // alpha is [0, 1] + } + + // now, convert to rgb + // code from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript + if (s === 0) { + r = g = b = Math.round(l * 255); // achromatic + } else { + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = Math.round(255 * hue2rgb(p, q, h + 1 / 3)); + g = Math.round(255 * hue2rgb(p, q, h)); + b = Math.round(255 * hue2rgb(p, q, h - 1 / 3)); + } + + ret = [r, g, b, a]; + } + + return ret; + }, + + // get [r, g, b, a] from rgb(0, 0, 0) or rgba(0, 0, 0, 0) + rgb2tuple: function rgb2tuple(rgb) { + var ret = void 0; + + var m = new RegExp('^' + this.regex.rgba + '$').exec(rgb); + if (m) { + ret = []; + + var isPct = []; + for (var i = 1; i <= 3; i++) { + var channel = m[i]; + + if (channel[channel.length - 1] === '%') { + isPct[i] = true; + } + channel = parseFloat(channel); + + if (isPct[i]) { + channel = channel / 100 * 255; // normalise to [0, 255] + } + + if (channel < 0 || channel > 255) { + return; + } // invalid channel value + + ret.push(Math.floor(channel)); + } + + var atLeastOneIsPct = isPct[1] || isPct[2] || isPct[3]; + var allArePct = isPct[1] && isPct[2] && isPct[3]; + if (atLeastOneIsPct && !allArePct) { + return; + } // must all be percent values if one is + + var alpha = m[4]; + if (alpha !== undefined) { + alpha = parseFloat(alpha); + + if (alpha < 0 || alpha > 1) { + return; + } // invalid alpha value + + ret.push(alpha); + } + } + + return ret; + }, + + colorname2tuple: function colorname2tuple(color) { + return this.colors[color.toLowerCase()]; + }, + + color2tuple: function color2tuple(color) { + return (is.array(color) ? color : null) || this.colorname2tuple(color) || this.hex2tuple(color) || this.rgb2tuple(color) || this.hsl2tuple(color); + }, + + colors: { + // special colour names + transparent: [0, 0, 0, 0], // NB alpha === 0 + + // regular colours + aliceblue: [240, 248, 255], + antiquewhite: [250, 235, 215], + aqua: [0, 255, 255], + aquamarine: [127, 255, 212], + azure: [240, 255, 255], + beige: [245, 245, 220], + bisque: [255, 228, 196], + black: [0, 0, 0], + blanchedalmond: [255, 235, 205], + blue: [0, 0, 255], + blueviolet: [138, 43, 226], + brown: [165, 42, 42], + burlywood: [222, 184, 135], + cadetblue: [95, 158, 160], + chartreuse: [127, 255, 0], + chocolate: [210, 105, 30], + coral: [255, 127, 80], + cornflowerblue: [100, 149, 237], + cornsilk: [255, 248, 220], + crimson: [220, 20, 60], + cyan: [0, 255, 255], + darkblue: [0, 0, 139], + darkcyan: [0, 139, 139], + darkgoldenrod: [184, 134, 11], + darkgray: [169, 169, 169], + darkgreen: [0, 100, 0], + darkgrey: [169, 169, 169], + darkkhaki: [189, 183, 107], + darkmagenta: [139, 0, 139], + darkolivegreen: [85, 107, 47], + darkorange: [255, 140, 0], + darkorchid: [153, 50, 204], + darkred: [139, 0, 0], + darksalmon: [233, 150, 122], + darkseagreen: [143, 188, 143], + darkslateblue: [72, 61, 139], + darkslategray: [47, 79, 79], + darkslategrey: [47, 79, 79], + darkturquoise: [0, 206, 209], + darkviolet: [148, 0, 211], + deeppink: [255, 20, 147], + deepskyblue: [0, 191, 255], + dimgray: [105, 105, 105], + dimgrey: [105, 105, 105], + dodgerblue: [30, 144, 255], + firebrick: [178, 34, 34], + floralwhite: [255, 250, 240], + forestgreen: [34, 139, 34], + fuchsia: [255, 0, 255], + gainsboro: [220, 220, 220], + ghostwhite: [248, 248, 255], + gold: [255, 215, 0], + goldenrod: [218, 165, 32], + gray: [128, 128, 128], + grey: [128, 128, 128], + green: [0, 128, 0], + greenyellow: [173, 255, 47], + honeydew: [240, 255, 240], + hotpink: [255, 105, 180], + indianred: [205, 92, 92], + indigo: [75, 0, 130], + ivory: [255, 255, 240], + khaki: [240, 230, 140], + lavender: [230, 230, 250], + lavenderblush: [255, 240, 245], + lawngreen: [124, 252, 0], + lemonchiffon: [255, 250, 205], + lightblue: [173, 216, 230], + lightcoral: [240, 128, 128], + lightcyan: [224, 255, 255], + lightgoldenrodyellow: [250, 250, 210], + lightgray: [211, 211, 211], + lightgreen: [144, 238, 144], + lightgrey: [211, 211, 211], + lightpink: [255, 182, 193], + lightsalmon: [255, 160, 122], + lightseagreen: [32, 178, 170], + lightskyblue: [135, 206, 250], + lightslategray: [119, 136, 153], + lightslategrey: [119, 136, 153], + lightsteelblue: [176, 196, 222], + lightyellow: [255, 255, 224], + lime: [0, 255, 0], + limegreen: [50, 205, 50], + linen: [250, 240, 230], + magenta: [255, 0, 255], + maroon: [128, 0, 0], + mediumaquamarine: [102, 205, 170], + mediumblue: [0, 0, 205], + mediumorchid: [186, 85, 211], + mediumpurple: [147, 112, 219], + mediumseagreen: [60, 179, 113], + mediumslateblue: [123, 104, 238], + mediumspringgreen: [0, 250, 154], + mediumturquoise: [72, 209, 204], + mediumvioletred: [199, 21, 133], + midnightblue: [25, 25, 112], + mintcream: [245, 255, 250], + mistyrose: [255, 228, 225], + moccasin: [255, 228, 181], + navajowhite: [255, 222, 173], + navy: [0, 0, 128], + oldlace: [253, 245, 230], + olive: [128, 128, 0], + olivedrab: [107, 142, 35], + orange: [255, 165, 0], + orangered: [255, 69, 0], + orchid: [218, 112, 214], + palegoldenrod: [238, 232, 170], + palegreen: [152, 251, 152], + paleturquoise: [175, 238, 238], + palevioletred: [219, 112, 147], + papayawhip: [255, 239, 213], + peachpuff: [255, 218, 185], + peru: [205, 133, 63], + pink: [255, 192, 203], + plum: [221, 160, 221], + powderblue: [176, 224, 230], + purple: [128, 0, 128], + red: [255, 0, 0], + rosybrown: [188, 143, 143], + royalblue: [65, 105, 225], + saddlebrown: [139, 69, 19], + salmon: [250, 128, 114], + sandybrown: [244, 164, 96], + seagreen: [46, 139, 87], + seashell: [255, 245, 238], + sienna: [160, 82, 45], + silver: [192, 192, 192], + skyblue: [135, 206, 235], + slateblue: [106, 90, 205], + slategray: [112, 128, 144], + slategrey: [112, 128, 144], + snow: [255, 250, 250], + springgreen: [0, 255, 127], + steelblue: [70, 130, 180], + tan: [210, 180, 140], + teal: [0, 128, 128], + thistle: [216, 191, 216], + tomato: [255, 99, 71], + turquoise: [64, 224, 208], + violet: [238, 130, 238], + wheat: [245, 222, 179], + white: [255, 255, 255], + whitesmoke: [245, 245, 245], + yellow: [255, 255, 0], + yellowgreen: [154, 205, 50] + } +}; + +/***/ }), +/* 22 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var is = __webpack_require__(0); + +module.exports = { + // has anything been set in the map + mapEmpty: function mapEmpty(map) { + var empty = true; + + if (map != null) { + return Object.keys(map).length === 0; + } + + return empty; + }, + + // pushes to the array at the end of a map (map may not be built) + pushMap: function pushMap(options) { + var array = this.getMap(options); + + if (array == null) { + // if empty, put initial array + this.setMap(this.extend({}, options, { + value: [options.value] + })); + } else { + array.push(options.value); + } + }, + + // sets the value in a map (map may not be built) + setMap: function setMap(options) { + var obj = options.map; + var key = void 0; + var keys = options.keys; + var l = keys.length; + + for (var i = 0; i < l; i++) { + var _key = keys[i]; + + if (is.plainObject(_key)) { + this.error('Tried to set map with object key'); + } + + if (i < keys.length - 1) { + + // extend the map if necessary + if (obj[_key] == null) { + obj[_key] = {}; + } + + obj = obj[_key]; + } else { + // set the value + obj[_key] = options.value; + } + } + }, + + // gets the value in a map even if it's not built in places + getMap: function getMap(options) { + var obj = options.map; + var keys = options.keys; + var l = keys.length; + + for (var i = 0; i < l; i++) { + var key = keys[i]; + + if (is.plainObject(key)) { + this.error('Tried to get map with object key'); + } + + obj = obj[key]; + + if (obj == null) { + return obj; + } + } + + return obj; + }, + + // deletes the entry in the map + deleteMap: function deleteMap(options) { + var obj = options.map; + var keys = options.keys; + var l = keys.length; + var keepChildren = options.keepChildren; + + for (var i = 0; i < l; i++) { + var key = keys[i]; + + if (is.plainObject(key)) { + this.error('Tried to delete map with object key'); + } + + var lastKey = i === options.keys.length - 1; + if (lastKey) { + + if (keepChildren) { + // then only delete child fields not in keepChildren + var children = Object.keys(obj); + + for (var j = 0; j < children.length; j++) { + var child = children[j]; + + if (!keepChildren[child]) { + obj[child] = undefined; + } + } + } else { + obj[key] = undefined; + } + } else { + obj = obj[key]; + } + } + } +}; + +/***/ }), +/* 23 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var number = '(?:[-+]?(?:(?:\\d+|\\d*\\.\\d+)(?:[Ee][+-]?\\d+)?))'; + +var rgba = 'rgb[a]?\\((' + number + '[%]?)\\s*,\\s*(' + number + '[%]?)\\s*,\\s*(' + number + '[%]?)(?:\\s*,\\s*(' + number + '))?\\)'; +var rgbaNoBackRefs = 'rgb[a]?\\((?:' + number + '[%]?)\\s*,\\s*(?:' + number + '[%]?)\\s*,\\s*(?:' + number + '[%]?)(?:\\s*,\\s*(?:' + number + '))?\\)'; + +var hsla = 'hsl[a]?\\((' + number + ')\\s*,\\s*(' + number + '[%])\\s*,\\s*(' + number + '[%])(?:\\s*,\\s*(' + number + '))?\\)'; +var hslaNoBackRefs = 'hsl[a]?\\((?:' + number + ')\\s*,\\s*(?:' + number + '[%])\\s*,\\s*(?:' + number + '[%])(?:\\s*,\\s*(?:' + number + '))?\\)'; + +var hex3 = '\\#[0-9a-fA-F]{3}'; +var hex6 = '\\#[0-9a-fA-F]{6}'; + +module.exports = { + regex: { + number: number, + rgba: rgba, + rgbaNoBackRefs: rgbaNoBackRefs, + hsla: hsla, + hslaNoBackRefs: hslaNoBackRefs, + hex3: hex3, + hex6: hex6 + } +}; + +/***/ }), +/* 24 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var memoize = __webpack_require__(13); +var is = __webpack_require__(0); + +module.exports = { + + camel2dash: memoize(function (str) { + return str.replace(/([A-Z])/g, function (v) { + return '-' + v.toLowerCase(); + }); + }), + + dash2camel: memoize(function (str) { + return str.replace(/(-\w)/g, function (v) { + return v[1].toUpperCase(); + }); + }), + + prependCamel: memoize(function (prefix, str) { + return prefix + str[0].toUpperCase() + str.substring(1); + }, function (prefix, str) { + return prefix + '$' + str; + }), + + capitalize: function capitalize(str) { + if (is.emptyString(str)) { + return str; + } + + return str.charAt(0).toUpperCase() + str.substring(1); + } + +}; + +/***/ }), +/* 25 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var window = __webpack_require__(3); +var performance = window ? window.performance : null; + +var util = {}; + +var pnow = performance && performance.now ? function () { + return performance.now(); +} : function () { + return Date.now(); +}; + +var raf = function () { + if (window) { + if (window.requestAnimationFrame) { + return function (fn) { + window.requestAnimationFrame(fn); + }; + } else if (window.mozRequestAnimationFrame) { + return function (fn) { + window.mozRequestAnimationFrame(fn); + }; + } else if (window.webkitRequestAnimationFrame) { + return function (fn) { + window.webkitRequestAnimationFrame(fn); + }; + } else if (window.msRequestAnimationFrame) { + return function (fn) { + window.msRequestAnimationFrame(fn); + }; + } + } + + return function (fn) { + if (fn) { + setTimeout(function () { + fn(pnow()); + }, 1000 / 60); + } + }; +}(); + +util.requestAnimationFrame = function (fn) { + raf(fn); +}; + +util.performanceNow = pnow; + +util.debounce = __webpack_require__(26); + +util.now = function () { + return Date.now(); +}; + +module.exports = util; + +/***/ }), +/* 26 */ +/***/ (function(module, exports) { + +/** + * lodash (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ + +/** Used as the `TypeError` message for "Functions" methods. */ +var FUNC_ERROR_TEXT = 'Expected a function'; + +/** Used as references for various `Number` constants. */ +var NAN = 0 / 0; + +/** `Object#toString` result references. */ +var symbolTag = '[object Symbol]'; + +/** Used to match leading and trailing whitespace. */ +var reTrim = /^\s+|\s+$/g; + +/** Used to detect bad signed hexadecimal string values. */ +var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; + +/** Used to detect binary string values. */ +var reIsBinary = /^0b[01]+$/i; + +/** Used to detect octal string values. */ +var reIsOctal = /^0o[0-7]+$/i; + +/** Built-in method references without a dependency on `root`. */ +var freeParseInt = parseInt; + +/** Detect free variable `global` from Node.js. */ +var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + +/** Detect free variable `self`. */ +var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + +/** Used as a reference to the global object. */ +var root = freeGlobal || freeSelf || Function('return this')(); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var objectToString = objectProto.toString; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max, + nativeMin = Math.min; + +/** + * Gets the timestamp of the number of milliseconds that have elapsed since + * the Unix epoch (1 January 1970 00:00:00 UTC). + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Date + * @returns {number} Returns the timestamp. + * @example + * + * _.defer(function(stamp) { + * console.log(_.now() - stamp); + * }, _.now()); + * // => Logs the number of milliseconds it took for the deferred invocation. + */ +var now = function() { + return root.Date.now(); +}; + +/** + * Creates a debounced function that delays invoking `func` until after `wait` + * milliseconds have elapsed since the last time the debounced function was + * invoked. The debounced function comes with a `cancel` method to cancel + * delayed `func` invocations and a `flush` method to immediately invoke them. + * Provide `options` to indicate whether `func` should be invoked on the + * leading and/or trailing edge of the `wait` timeout. The `func` is invoked + * with the last arguments provided to the debounced function. Subsequent + * calls to the debounced function return the result of the last `func` + * invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the debounced function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.debounce` and `_.throttle`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to debounce. + * @param {number} [wait=0] The number of milliseconds to delay. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=false] + * Specify invoking on the leading edge of the timeout. + * @param {number} [options.maxWait] + * The maximum time `func` is allowed to be delayed before it's invoked. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new debounced function. + * @example + * + * // Avoid costly calculations while the window size is in flux. + * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); + * + * // Invoke `sendMail` when clicked, debouncing subsequent calls. + * jQuery(element).on('click', _.debounce(sendMail, 300, { + * 'leading': true, + * 'trailing': false + * })); + * + * // Ensure `batchLog` is invoked once after 1 second of debounced calls. + * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); + * var source = new EventSource('/stream'); + * jQuery(source).on('message', debounced); + * + * // Cancel the trailing debounced invocation. + * jQuery(window).on('popstate', debounced.cancel); + */ +function debounce(func, wait, options) { + var lastArgs, + lastThis, + maxWait, + result, + timerId, + lastCallTime, + lastInvokeTime = 0, + leading = false, + maxing = false, + trailing = true; + + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = toNumber(wait) || 0; + if (isObject(options)) { + leading = !!options.leading; + maxing = 'maxWait' in options; + maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + + function invokeFunc(time) { + var args = lastArgs, + thisArg = lastThis; + + lastArgs = lastThis = undefined; + lastInvokeTime = time; + result = func.apply(thisArg, args); + return result; + } + + function leadingEdge(time) { + // Reset any `maxWait` timer. + lastInvokeTime = time; + // Start the timer for the trailing edge. + timerId = setTimeout(timerExpired, wait); + // Invoke the leading edge. + return leading ? invokeFunc(time) : result; + } + + function remainingWait(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime, + result = wait - timeSinceLastCall; + + return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result; + } + + function shouldInvoke(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime; + + // Either this is the first call, activity has stopped and we're at the + // trailing edge, the system time has gone backwards and we're treating + // it as the trailing edge, or we've hit the `maxWait` limit. + return (lastCallTime === undefined || (timeSinceLastCall >= wait) || + (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); + } + + function timerExpired() { + var time = now(); + if (shouldInvoke(time)) { + return trailingEdge(time); + } + // Restart the timer. + timerId = setTimeout(timerExpired, remainingWait(time)); + } + + function trailingEdge(time) { + timerId = undefined; + + // Only invoke if we have `lastArgs` which means `func` has been + // debounced at least once. + if (trailing && lastArgs) { + return invokeFunc(time); + } + lastArgs = lastThis = undefined; + return result; + } + + function cancel() { + if (timerId !== undefined) { + clearTimeout(timerId); + } + lastInvokeTime = 0; + lastArgs = lastCallTime = lastThis = timerId = undefined; + } + + function flush() { + return timerId === undefined ? result : trailingEdge(now()); + } + + function debounced() { + var time = now(), + isInvoking = shouldInvoke(time); + + lastArgs = arguments; + lastThis = this; + lastCallTime = time; + + if (isInvoking) { + if (timerId === undefined) { + return leadingEdge(lastCallTime); + } + if (maxing) { + // Handle invocations in a tight loop. + timerId = setTimeout(timerExpired, wait); + return invokeFunc(lastCallTime); + } + } + if (timerId === undefined) { + timerId = setTimeout(timerExpired, wait); + } + return result; + } + debounced.cancel = cancel; + debounced.flush = flush; + return debounced; +} + +/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ +function isObject(value) { + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); +} + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +/** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ +function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && objectToString.call(value) == symbolTag); +} + +/** + * Converts `value` to a number. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to process. + * @returns {number} Returns the number. + * @example + * + * _.toNumber(3.2); + * // => 3.2 + * + * _.toNumber(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toNumber(Infinity); + * // => Infinity + * + * _.toNumber('3.2'); + * // => 3.2 + */ +function toNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + if (isObject(value)) { + var other = typeof value.valueOf == 'function' ? value.valueOf() : value; + value = isObject(other) ? (other + '') : other; + } + if (typeof value != 'string') { + return value === 0 ? value : +value; + } + value = value.replace(reTrim, ''); + var isBinary = reIsBinary.test(value); + return (isBinary || reIsOctal.test(value)) + ? freeParseInt(value.slice(2), isBinary ? 2 : 8) + : (reIsBadHex.test(value) ? NAN : +value); +} + +module.exports = debounce; + + +/***/ }), +/* 27 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +function ascending(a, b) { + if (a < b) { + return -1; + } else if (a > b) { + return 1; + } else { + return 0; + } +} + +function descending(a, b) { + return -1 * ascending(a, b); +} + +module.exports = { + sort: { + ascending: ascending, + descending: descending + } +}; + +/***/ }), +/* 28 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +function ObjectMap() { + this._obj = {}; +} + +var p = ObjectMap.prototype; + +p.set = function (key, val) { + this._obj[key] = val; +}; + +p.delete = function (key) { + this._obj[key] = null; +}; + +p.has = function (key) { + return this._obj[key] != null; +}; + +p.get = function (key) { + return this._obj[key]; +}; + +// TODO use the stdlib Map in future... +// module.exports = typeof Map !== 'undefined' ? Map : ObjectMap; +module.exports = ObjectMap; + +/***/ }), +/* 29 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var util = __webpack_require__(1); + +var elesfn = {}; + +[__webpack_require__(30), __webpack_require__(31), __webpack_require__(34), __webpack_require__(35), __webpack_require__(36), __webpack_require__(37), __webpack_require__(38), __webpack_require__(39), __webpack_require__(40), __webpack_require__(41), __webpack_require__(42)].forEach(function (props) { + util.extend(elesfn, props); +}); + +module.exports = elesfn; + +/***/ }), +/* 30 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var is = __webpack_require__(0); + +var defineSearch = function defineSearch(params) { + params = { + bfs: params.bfs || !params.dfs, + dfs: params.dfs || !params.bfs + }; + + // from pseudocode on wikipedia + return function searchFn(roots, fn, directed) { + var options; + if (is.plainObject(roots) && !is.elementOrCollection(roots)) { + options = roots; + roots = options.roots || options.root; + fn = options.visit; + directed = options.directed; + } + + directed = arguments.length === 2 && !is.fn(fn) ? fn : directed; + fn = is.fn(fn) ? fn : function () {}; + + var cy = this._private.cy; + var v = roots = is.string(roots) ? this.filter(roots) : roots; + var Q = []; + var connectedNodes = []; + var connectedBy = {}; + var id2depth = {}; + var V = {}; + var j = 0; + var found; + var nodes = this.nodes(); + var edges = this.edges(); + + // enqueue v + for (var i = 0; i < v.length; i++) { + if (v[i].isNode()) { + Q.unshift(v[i]); + + if (params.bfs) { + V[v[i].id()] = true; + + connectedNodes.push(v[i]); + } + + id2depth[v[i].id()] = 0; + } + } + + while (Q.length !== 0) { + var v = params.bfs ? Q.shift() : Q.pop(); + + if (params.dfs) { + if (V[v.id()]) { + continue; + } + + V[v.id()] = true; + + connectedNodes.push(v); + } + + var depth = id2depth[v.id()]; + var prevEdge = connectedBy[v.id()]; + var prevNode = prevEdge == null ? undefined : prevEdge.connectedNodes().not(v)[0]; + var ret; + + ret = fn(v, prevEdge, prevNode, j++, depth); + + if (ret === true) { + found = v; + break; + } + + if (ret === false) { + break; + } + + var vwEdges = v.connectedEdges(directed ? function (ele) { + return ele.data('source') === v.id(); + } : undefined).intersect(edges); + for (var i = 0; i < vwEdges.length; i++) { + var e = vwEdges[i]; + var w = e.connectedNodes(function (n) { + return n.id() !== v.id(); + }).intersect(nodes); + + if (w.length !== 0 && !V[w.id()]) { + w = w[0]; + + Q.push(w); + + if (params.bfs) { + V[w.id()] = true; + + connectedNodes.push(w); + } + + connectedBy[w.id()] = e; + + id2depth[w.id()] = id2depth[v.id()] + 1; + } + } + } + + var connectedEles = []; + + for (var i = 0; i < connectedNodes.length; i++) { + var node = connectedNodes[i]; + var edge = connectedBy[node.id()]; + + if (edge) { + connectedEles.push(edge); + } + + connectedEles.push(node); + } + + return { + path: cy.collection(connectedEles, { unique: true }), + found: cy.collection(found) + }; + }; +}; + +// search, spanning trees, etc +var elesfn = { + breadthFirstSearch: defineSearch({ bfs: true }), + depthFirstSearch: defineSearch({ dfs: true }) +}; + +// nice, short mathemathical alias +elesfn.bfs = elesfn.breadthFirstSearch; +elesfn.dfs = elesfn.depthFirstSearch; + +module.exports = elesfn; + +/***/ }), +/* 31 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var is = __webpack_require__(0); +var Heap = __webpack_require__(9); + +var elesfn = { + + dijkstra: function dijkstra(root, weightFn, directed) { + var options; + if (is.plainObject(root) && !is.elementOrCollection(root)) { + options = root; + root = options.root; + weightFn = options.weight; + directed = options.directed; + } + + var cy = this._private.cy; + weightFn = is.fn(weightFn) ? weightFn : function () { + return 1; + }; // if not specified, assume each edge has equal weight (1) + + var source = is.string(root) ? this.filter(root)[0] : root[0]; + var dist = {}; + var prev = {}; + var knownDist = {}; + + var edges = this.edges().filter(function (ele) { + return !ele.isLoop(); + }); + var nodes = this.nodes(); + + var getDist = function getDist(node) { + return dist[node.id()]; + }; + + var setDist = function setDist(node, d) { + dist[node.id()] = d; + + Q.updateItem(node); + }; + + var Q = new Heap(function (a, b) { + return getDist(a) - getDist(b); + }); + + for (var i = 0; i < nodes.length; i++) { + var node = nodes[i]; + + dist[node.id()] = node.same(source) ? 0 : Infinity; + Q.push(node); + } + + var distBetween = function distBetween(u, v) { + var uvs = (directed ? u.edgesTo(v) : u.edgesWith(v)).intersect(edges); + var smallestDistance = Infinity; + var smallestEdge; + + for (var i = 0; i < uvs.length; i++) { + var edge = uvs[i]; + var weight = weightFn(edge); + + if (weight < smallestDistance || !smallestEdge) { + smallestDistance = weight; + smallestEdge = edge; + } + } + + return { + edge: smallestEdge, + dist: smallestDistance + }; + }; + + while (Q.size() > 0) { + var u = Q.pop(); + var smalletsDist = getDist(u); + var uid = u.id(); + + knownDist[uid] = smalletsDist; + + if (smalletsDist === Infinity) { + continue; + } + + var neighbors = u.neighborhood().intersect(nodes); + for (var i = 0; i < neighbors.length; i++) { + var v = neighbors[i]; + var vid = v.id(); + var vDist = distBetween(u, v); + + var alt = smalletsDist + vDist.dist; + + if (alt < getDist(v)) { + setDist(v, alt); + + prev[vid] = { + node: u, + edge: vDist.edge + }; + } + } // for + } // while + + return { + distanceTo: function distanceTo(node) { + var target = is.string(node) ? nodes.filter(node)[0] : node[0]; + + return knownDist[target.id()]; + }, + + pathTo: function pathTo(node) { + var target = is.string(node) ? nodes.filter(node)[0] : node[0]; + var S = []; + var u = target; + + if (target.length > 0) { + S.unshift(target); + + while (prev[u.id()]) { + var p = prev[u.id()]; + + S.unshift(p.edge); + S.unshift(p.node); + + u = p.node; + } + } + + return cy.collection(S); + } + }; + } +}; + +module.exports = elesfn; + +/***/ }), +/* 32 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = __webpack_require__(33); + + +/***/ }), +/* 33 */ +/***/ (function(module, exports, __webpack_require__) { + +var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;// Generated by CoffeeScript 1.8.0 +(function() { + var Heap, defaultCmp, floor, heapify, heappop, heappush, heappushpop, heapreplace, insort, min, nlargest, nsmallest, updateItem, _siftdown, _siftup; + + floor = Math.floor, min = Math.min; + + + /* + Default comparison function to be used + */ + + defaultCmp = function(x, y) { + if (x < y) { + return -1; + } + if (x > y) { + return 1; + } + return 0; + }; + + + /* + Insert item x in list a, and keep it sorted assuming a is sorted. + + If x is already in a, insert it to the right of the rightmost x. + + Optional args lo (default 0) and hi (default a.length) bound the slice + of a to be searched. + */ + + insort = function(a, x, lo, hi, cmp) { + var mid; + if (lo == null) { + lo = 0; + } + if (cmp == null) { + cmp = defaultCmp; + } + if (lo < 0) { + throw new Error('lo must be non-negative'); + } + if (hi == null) { + hi = a.length; + } + while (lo < hi) { + mid = floor((lo + hi) / 2); + if (cmp(x, a[mid]) < 0) { + hi = mid; + } else { + lo = mid + 1; + } + } + return ([].splice.apply(a, [lo, lo - lo].concat(x)), x); + }; + + + /* + Push item onto heap, maintaining the heap invariant. + */ + + heappush = function(array, item, cmp) { + if (cmp == null) { + cmp = defaultCmp; + } + array.push(item); + return _siftdown(array, 0, array.length - 1, cmp); + }; + + + /* + Pop the smallest item off the heap, maintaining the heap invariant. + */ + + heappop = function(array, cmp) { + var lastelt, returnitem; + if (cmp == null) { + cmp = defaultCmp; + } + lastelt = array.pop(); + if (array.length) { + returnitem = array[0]; + array[0] = lastelt; + _siftup(array, 0, cmp); + } else { + returnitem = lastelt; + } + return returnitem; + }; + + + /* + Pop and return the current smallest value, and add the new item. + + This is more efficient than heappop() followed by heappush(), and can be + more appropriate when using a fixed size heap. Note that the value + returned may be larger than item! That constrains reasonable use of + this routine unless written as part of a conditional replacement: + if item > array[0] + item = heapreplace(array, item) + */ + + heapreplace = function(array, item, cmp) { + var returnitem; + if (cmp == null) { + cmp = defaultCmp; + } + returnitem = array[0]; + array[0] = item; + _siftup(array, 0, cmp); + return returnitem; + }; + + + /* + Fast version of a heappush followed by a heappop. + */ + + heappushpop = function(array, item, cmp) { + var _ref; + if (cmp == null) { + cmp = defaultCmp; + } + if (array.length && cmp(array[0], item) < 0) { + _ref = [array[0], item], item = _ref[0], array[0] = _ref[1]; + _siftup(array, 0, cmp); + } + return item; + }; + + + /* + Transform list into a heap, in-place, in O(array.length) time. + */ + + heapify = function(array, cmp) { + var i, _i, _j, _len, _ref, _ref1, _results, _results1; + if (cmp == null) { + cmp = defaultCmp; + } + _ref1 = (function() { + _results1 = []; + for (var _j = 0, _ref = floor(array.length / 2); 0 <= _ref ? _j < _ref : _j > _ref; 0 <= _ref ? _j++ : _j--){ _results1.push(_j); } + return _results1; + }).apply(this).reverse(); + _results = []; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + i = _ref1[_i]; + _results.push(_siftup(array, i, cmp)); + } + return _results; + }; + + + /* + Update the position of the given item in the heap. + This function should be called every time the item is being modified. + */ + + updateItem = function(array, item, cmp) { + var pos; + if (cmp == null) { + cmp = defaultCmp; + } + pos = array.indexOf(item); + if (pos === -1) { + return; + } + _siftdown(array, 0, pos, cmp); + return _siftup(array, pos, cmp); + }; + + + /* + Find the n largest elements in a dataset. + */ + + nlargest = function(array, n, cmp) { + var elem, result, _i, _len, _ref; + if (cmp == null) { + cmp = defaultCmp; + } + result = array.slice(0, n); + if (!result.length) { + return result; + } + heapify(result, cmp); + _ref = array.slice(n); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + elem = _ref[_i]; + heappushpop(result, elem, cmp); + } + return result.sort(cmp).reverse(); + }; + + + /* + Find the n smallest elements in a dataset. + */ + + nsmallest = function(array, n, cmp) { + var elem, i, los, result, _i, _j, _len, _ref, _ref1, _results; + if (cmp == null) { + cmp = defaultCmp; + } + if (n * 10 <= array.length) { + result = array.slice(0, n).sort(cmp); + if (!result.length) { + return result; + } + los = result[result.length - 1]; + _ref = array.slice(n); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + elem = _ref[_i]; + if (cmp(elem, los) < 0) { + insort(result, elem, 0, null, cmp); + result.pop(); + los = result[result.length - 1]; + } + } + return result; + } + heapify(array, cmp); + _results = []; + for (i = _j = 0, _ref1 = min(n, array.length); 0 <= _ref1 ? _j < _ref1 : _j > _ref1; i = 0 <= _ref1 ? ++_j : --_j) { + _results.push(heappop(array, cmp)); + } + return _results; + }; + + _siftdown = function(array, startpos, pos, cmp) { + var newitem, parent, parentpos; + if (cmp == null) { + cmp = defaultCmp; + } + newitem = array[pos]; + while (pos > startpos) { + parentpos = (pos - 1) >> 1; + parent = array[parentpos]; + if (cmp(newitem, parent) < 0) { + array[pos] = parent; + pos = parentpos; + continue; + } + break; + } + return array[pos] = newitem; + }; + + _siftup = function(array, pos, cmp) { + var childpos, endpos, newitem, rightpos, startpos; + if (cmp == null) { + cmp = defaultCmp; + } + endpos = array.length; + startpos = pos; + newitem = array[pos]; + childpos = 2 * pos + 1; + while (childpos < endpos) { + rightpos = childpos + 1; + if (rightpos < endpos && !(cmp(array[childpos], array[rightpos]) < 0)) { + childpos = rightpos; + } + array[pos] = array[childpos]; + pos = childpos; + childpos = 2 * pos + 1; + } + array[pos] = newitem; + return _siftdown(array, startpos, pos, cmp); + }; + + Heap = (function() { + Heap.push = heappush; + + Heap.pop = heappop; + + Heap.replace = heapreplace; + + Heap.pushpop = heappushpop; + + Heap.heapify = heapify; + + Heap.updateItem = updateItem; + + Heap.nlargest = nlargest; + + Heap.nsmallest = nsmallest; + + function Heap(cmp) { + this.cmp = cmp != null ? cmp : defaultCmp; + this.nodes = []; + } + + Heap.prototype.push = function(x) { + return heappush(this.nodes, x, this.cmp); + }; + + Heap.prototype.pop = function() { + return heappop(this.nodes, this.cmp); + }; + + Heap.prototype.peek = function() { + return this.nodes[0]; + }; + + Heap.prototype.contains = function(x) { + return this.nodes.indexOf(x) !== -1; + }; + + Heap.prototype.replace = function(x) { + return heapreplace(this.nodes, x, this.cmp); + }; + + Heap.prototype.pushpop = function(x) { + return heappushpop(this.nodes, x, this.cmp); + }; + + Heap.prototype.heapify = function() { + return heapify(this.nodes, this.cmp); + }; + + Heap.prototype.updateItem = function(x) { + return updateItem(this.nodes, x, this.cmp); + }; + + Heap.prototype.clear = function() { + return this.nodes = []; + }; + + Heap.prototype.empty = function() { + return this.nodes.length === 0; + }; + + Heap.prototype.size = function() { + return this.nodes.length; + }; + + Heap.prototype.clone = function() { + var heap; + heap = new Heap(); + heap.nodes = this.nodes.slice(0); + return heap; + }; + + Heap.prototype.toArray = function() { + return this.nodes.slice(0); + }; + + Heap.prototype.insert = Heap.prototype.push; + + Heap.prototype.top = Heap.prototype.peek; + + Heap.prototype.front = Heap.prototype.peek; + + Heap.prototype.has = Heap.prototype.contains; + + Heap.prototype.copy = Heap.prototype.clone; + + return Heap; + + })(); + + (function(root, factory) { + if (true) { + return !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), + __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? + (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), + __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else if (typeof exports === 'object') { + return module.exports = factory(); + } else { + return root.Heap = factory(); + } + })(this, function() { + return Heap; + }); + +}).call(this); + + +/***/ }), +/* 34 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var is = __webpack_require__(0); + +// search, spanning trees, etc +var elesfn = { + + // kruskal's algorithm (finds min spanning tree, assuming undirected graph) + // implemented from pseudocode from wikipedia + kruskal: function kruskal(weightFn) { + var cy = this.cy(); + + weightFn = is.fn(weightFn) ? weightFn : function () { + return 1; + }; // if not specified, assume each edge has equal weight (1) + + function findSet(ele) { + for (var i = 0; i < forest.length; i++) { + var eles = forest[i]; + + if (eles.anySame(ele)) { + return { + eles: eles, + index: i + }; + } + } + } + + var A = cy.collection(cy, []); + var forest = []; + var nodes = this.nodes(); + + for (var i = 0; i < nodes.length; i++) { + forest.push(nodes[i].collection()); + } + + var edges = this.edges(); + var S = edges.toArray().sort(function (a, b) { + var weightA = weightFn(a); + var weightB = weightFn(b); + + return weightA - weightB; + }); + + for (var i = 0; i < S.length; i++) { + var edge = S[i]; + var u = edge.source()[0]; + var v = edge.target()[0]; + var setU = findSet(u); + var setV = findSet(v); + + if (setU.index !== setV.index) { + A = A.add(edge); + + // combine forests for u and v + forest[setU.index] = setU.eles.add(setV.eles); + forest.splice(setV.index, 1); + } + } + + return nodes.add(A); + } +}; + +module.exports = elesfn; + +/***/ }), +/* 35 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var is = __webpack_require__(0); + +var elesfn = { // Implemented from pseudocode from wikipedia - aStar: function( options ){ + aStar: function aStar(options) { var eles = this; options = options || {}; // Reconstructs the path from Start to End, acumulating the result in pathAcum - var reconstructPath = function( start, end, cameFromMap, pathAcum ){ + var reconstructPath = function reconstructPath(start, end, cameFromMap, pathAcum) { // Base case - if( start == end ){ - pathAcum.push( cy.getElementById( end ) ); + if (start == end) { + pathAcum.unshift(cy.getElementById(end)); return pathAcum; } - if( end in cameFromMap ){ + if (end in cameFromMap) { // We know which node is before the last one - var previous = cameFromMap[ end ]; - var previousEdge = cameFromEdge[ end ]; + var previous = cameFromMap[end]; + var previousEdge = cameFromEdge[end]; - pathAcum.push( cy.getElementById( end ) ); - pathAcum.push( cy.getElementById( previousEdge ) ); + pathAcum.unshift(cy.getElementById(previousEdge)); + pathAcum.unshift(cy.getElementById(end)); - - return reconstructPath( start, - previous, - cameFromMap, - pathAcum ); + return reconstructPath(start, previous, cameFromMap, pathAcum); } // We should not reach here! @@ -306,16 +6241,16 @@ var elesfn = ({ }; // Returns the index of the element in openSet which has minimum fScore - var findMin = function( openSet, fScore ){ - if( openSet.length === 0 ){ + var findMin = function findMin(openSet, fScore) { + if (openSet.length === 0) { // Should never be the case return undefined; } var minPos = 0; - var tempScore = fScore[ openSet[0] ]; - for( var i = 1; i < openSet.length; i++ ){ - var s = fScore[ openSet[ i ] ]; - if( s < tempScore ){ + var tempScore = fScore[openSet[0]]; + for (var i = 1; i < openSet.length; i++) { + var s = fScore[openSet[i]]; + if (s < tempScore) { tempScore = s; minPos = i; } @@ -326,103 +6261,124 @@ var elesfn = ({ var cy = this._private.cy; // root - mandatory! - if( options != null && options.root != null ){ - var source = is.string( options.root ) ? - // use it as a selector, e.g. "#rootID - this.filter( options.root )[0] : - options.root[0]; + if (options != null && options.root != null) { + var source = is.string(options.root) ? + // use it as a selector, e.g. "#rootID + this.filter(options.root)[0] : options.root[0]; } else { return undefined; } // goal - mandatory! - if( options.goal != null ){ - var target = is.string( options.goal ) ? - // use it as a selector, e.g. "#goalID - this.filter( options.goal )[0] : - options.goal[0]; + if (options.goal != null) { + var target = is.string(options.goal) ? + // use it as a selector, e.g. "#goalID + this.filter(options.goal)[0] : options.goal[0]; } else { return undefined; } // Heuristic function - optional - if( options.heuristic != null && is.fn( options.heuristic ) ){ + if (options.heuristic != null && is.fn(options.heuristic)) { var heuristic = options.heuristic; } else { - var heuristic = function(){ return 0; }; // use constant if unspecified + var heuristic = function heuristic() { + return 0; + }; // use constant if unspecified } // Weight function - optional - if( options.weight != null && is.fn( options.weight ) ){ + if (options.weight != null && is.fn(options.weight)) { var weightFn = options.weight; } else { // If not specified, assume each edge has equal weight (1) - var weightFn = function( e ){return 1;}; + var weightFn = function weightFn(e) { + return 1; + }; } // directed - optional - if( options.directed != null ){ + if (options.directed != null) { var directed = options.directed; } else { var directed = false; } + var sid = source.id(); + var tid = target.id(); + var closedSet = []; - var openSet = [ source.id() ]; + var openSet = [sid]; var cameFrom = {}; var cameFromEdge = {}; var gScore = {}; var fScore = {}; - gScore[ source.id() ] = 0; - fScore[ source.id() ] = heuristic( source ); - - var edges = this.edges().stdFilter( function( e ){ return !e.isLoop(); } ); - var nodes = this.nodes(); + gScore[sid] = 0; + fScore[sid] = heuristic(source); // Counter var steps = 0; // Main loop - while( openSet.length > 0 ){ - var minPos = findMin( openSet, fScore ); - var cMin = cy.getElementById( openSet[ minPos ] ); + while (openSet.length > 0) { + var minPos = findMin(openSet, fScore); + var cMin = cy.getElementById(openSet[minPos]); + var cMinId = cMin.id(); steps++; // If we've found our goal, then we are done - if( cMin.id() == target.id() ){ - var rPath = reconstructPath( source.id(), target.id(), cameFrom, [] ); - rPath.reverse(); + if (cMinId == tid) { + var rPath = reconstructPath(sid, tid, cameFrom, []); + return { found: true, - distance: gScore[ cMin.id() ], - path: eles.spawn( rPath ), + distance: gScore[cMinId], + path: eles.spawn(rPath), steps: steps }; } // Add cMin to processed nodes - closedSet.push( cMin.id() ); + closedSet.push(cMinId); // Remove cMin from boundary nodes - openSet.splice( minPos, 1 ); + openSet.splice(minPos, 1); // Update scores for neighbors of cMin // Take into account if graph is directed or not - var vwEdges = cMin.connectedEdges(); - if( directed ){ vwEdges = vwEdges.stdFilter( function( ele ){ return ele.data( 'source' ) === cMin.id(); } ); } - vwEdges = vwEdges.intersect( edges ); + var vwEdges = cMin._private.edges; - for( var i = 0; i < vwEdges.length; i++ ){ - var e = vwEdges[ i ]; - var w = e.connectedNodes().stdFilter( function( n ){ return n.id() !== cMin.id(); } ).intersect( nodes ); + for (var i = 0; i < vwEdges.length; i++) { + var e = vwEdges[i]; + + // edge must be in set of calling eles + if (!this.hasElementWithId(e.id())) { + continue; + } + + // cMin must be the source of edge if directed + if (directed && e.data('source') !== cMinId) { + continue; + } + + var wSrc = e.source(); + var wTgt = e.target(); + + var w = wSrc.id() !== cMinId ? wSrc : wTgt; + var wid = w.id(); + + // node must be in set of calling eles + if (!this.hasElementWithId(wid)) { + continue; + } // if node is in closedSet, ignore it - if( closedSet.indexOf( w.id() ) != -1 ){ + if (closedSet.indexOf(wid) != -1) { continue; } // New tentative score for node w - var tempScore = gScore[ cMin.id() ] + weightFn.apply( e, [ e ] ); + var tempScore = gScore[cMinId] + weightFn(e); // Update gScore for node w if: // w not present in openSet @@ -430,23 +6386,21 @@ var elesfn = ({ // tentative gScore is less than previous value // w not in openSet - if( openSet.indexOf( w.id() ) == -1 ){ - gScore[ w.id() ] = tempScore; - fScore[ w.id() ] = tempScore + heuristic( w ); - openSet.push( w.id() ); // Add node to openSet - cameFrom[ w.id() ] = cMin.id(); - cameFromEdge[ w.id() ] = e.id(); + if (openSet.indexOf(wid) == -1) { + gScore[wid] = tempScore; + fScore[wid] = tempScore + heuristic(w); + openSet.push(wid); // Add node to openSet + cameFrom[wid] = cMinId; + cameFromEdge[wid] = e.id(); continue; } // w already in openSet, but with greater gScore - if( tempScore < gScore[ w.id() ] ){ - gScore[ w.id() ] = tempScore; - fScore[ w.id() ] = tempScore + heuristic( w ); - cameFrom[ w.id() ] = cMin.id(); + if (tempScore < gScore[wid]) { + gScore[wid] = tempScore; + fScore[wid] = tempScore + heuristic(w); + cameFrom[wid] = cMinId; } - } // End of neighbors update - } // End of main loop // If we've reached here, then we've not reached our goal @@ -458,45 +6412,250 @@ var elesfn = ({ }; } -}); // elesfn +}; // elesfn module.exports = elesfn; -},{"../../is":83}],4:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 36 */ +/***/ (function(module, exports, __webpack_require__) { -var is = _dereq_( '../../is' ); -var util = _dereq_( '../../util' ); +"use strict"; -var elesfn = ({ + +var is = __webpack_require__(0); + +var elesfn = { // Implemented from pseudocode from wikipedia - bellmanFord: function( options ){ + floydWarshall: function floydWarshall(options) { + options = options || {}; + + var cy = this.cy(); + + // Weight function - optional + if (options.weight != null && is.fn(options.weight)) { + var weightFn = options.weight; + } else { + // If not specified, assume each edge has equal weight (1) + var weightFn = function weightFn(e) { + return 1; + }; + } + + // directed - optional + if (options.directed != null) { + var directed = options.directed; + } else { + var directed = false; + } + + var edges = this.edges().stdFilter(function (e) { + return !e.isLoop(); + }); + var nodes = this.nodes(); + var numNodes = nodes.length; + + // mapping: node id -> position in nodes array + var id2position = {}; + for (var i = 0; i < numNodes; i++) { + id2position[nodes[i].id()] = i; + } + + // Initialize distance matrix + var dist = []; + for (var i = 0; i < numNodes; i++) { + var newRow = new Array(numNodes); + for (var j = 0; j < numNodes; j++) { + if (i == j) { + newRow[j] = 0; + } else { + newRow[j] = Infinity; + } + } + dist.push(newRow); + } + + // Initialize matrix used for path reconstruction + // Initialize distance matrix + var next = []; + var edgeNext = []; + + var initMatrix = function initMatrix(next) { + for (var i = 0; i < numNodes; i++) { + var newRow = new Array(numNodes); + for (var j = 0; j < numNodes; j++) { + newRow[j] = undefined; + } + next.push(newRow); + } + }; + + initMatrix(next); + initMatrix(edgeNext); + + // Process edges + for (var i = 0; i < edges.length; i++) { + var sourceIndex = id2position[edges[i].source().id()]; + var targetIndex = id2position[edges[i].target().id()]; + var weight = weightFn(edges[i]); + + // Check if already process another edge between same 2 nodes + if (dist[sourceIndex][targetIndex] > weight) { + dist[sourceIndex][targetIndex] = weight; + next[sourceIndex][targetIndex] = targetIndex; + edgeNext[sourceIndex][targetIndex] = edges[i]; + } + } + + // If undirected graph, process 'reversed' edges + if (!directed) { + for (var i = 0; i < edges.length; i++) { + var sourceIndex = id2position[edges[i].target().id()]; + var targetIndex = id2position[edges[i].source().id()]; + var weight = weightFn(edges[i]); + + // Check if already process another edge between same 2 nodes + if (dist[sourceIndex][targetIndex] > weight) { + dist[sourceIndex][targetIndex] = weight; + next[sourceIndex][targetIndex] = targetIndex; + edgeNext[sourceIndex][targetIndex] = edges[i]; + } + } + } + + // Main loop + for (var k = 0; k < numNodes; k++) { + for (var i = 0; i < numNodes; i++) { + for (var j = 0; j < numNodes; j++) { + if (dist[i][k] + dist[k][j] < dist[i][j]) { + dist[i][j] = dist[i][k] + dist[k][j]; + next[i][j] = next[i][k]; + } + } + } + } + + // Build result object + var position2id = []; + for (var i = 0; i < numNodes; i++) { + position2id.push(nodes[i].id()); + } + + var res = { + distance: function distance(from, to) { + if (is.string(from)) { + // from is a selector string + var fromId = cy.filter(from)[0].id(); + } else { + // from is a node + var fromId = from.id(); + } + + if (is.string(to)) { + // to is a selector string + var toId = cy.filter(to)[0].id(); + } else { + // to is a node + var toId = to.id(); + } + + return dist[id2position[fromId]][id2position[toId]]; + }, + + path: function path(from, to) { + var reconstructPathAux = function reconstructPathAux(from, to, next, position2id, edgeNext) { + if (from === to) { + return cy.getElementById(position2id[from]); + } + if (next[from][to] === undefined) { + return undefined; + } + + var path = [cy.getElementById(position2id[from])]; + var prev = from; + while (from !== to) { + prev = from; + from = next[from][to]; + + var edge = edgeNext[prev][from]; + path.push(edge); + + path.push(cy.getElementById(position2id[from])); + } + return path; + }; + + if (is.string(from)) { + // from is a selector string + var fromId = cy.filter(from)[0].id(); + } else { + // from is a node + var fromId = from.id(); + } + + if (is.string(to)) { + // to is a selector string + var toId = cy.filter(to)[0].id(); + } else { + // to is a node + var toId = to.id(); + } + + var pathArr = reconstructPathAux(id2position[fromId], id2position[toId], next, position2id, edgeNext); + + return cy.collection(pathArr); + } + }; + + return res; + } // floydWarshall + +}; // elesfn + +module.exports = elesfn; + +/***/ }), +/* 37 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var is = __webpack_require__(0); +var util = __webpack_require__(1); + +var elesfn = { + + // Implemented from pseudocode from wikipedia + bellmanFord: function bellmanFord(options) { var eles = this; options = options || {}; // Weight function - optional - if( options.weight != null && is.fn( options.weight ) ){ + if (options.weight != null && is.fn(options.weight)) { var weightFn = options.weight; } else { // If not specified, assume each edge has equal weight (1) - var weightFn = function( e ){return 1;}; + var weightFn = function weightFn(e) { + return 1; + }; } // directed - optional - if( options.directed != null ){ + if (options.directed != null) { var directed = options.directed; } else { var directed = false; } // root - mandatory! - if( options.root != null ){ - if( is.string( options.root ) ){ + if (options.root != null) { + if (is.string(options.root)) { // use it as a selector, e.g. "#rootID - var source = this.filter( options.root )[0]; + var source = this.filter(options.root)[0]; } else { var source = options.root[0]; } @@ -505,14 +6664,16 @@ var elesfn = ({ } var cy = this._private.cy; - var edges = this.edges().stdFilter( function( e ){ return !e.isLoop(); } ); + var edges = this.edges().stdFilter(function (e) { + return !e.isLoop(); + }); var nodes = this.nodes(); var numNodes = nodes.length; // mapping: node id -> position in nodes array var id2position = {}; - for( var i = 0; i < numNodes; i++ ){ - id2position[ nodes[ i ].id() ] = i; + for (var i = 0; i < numNodes; i++) { + id2position[nodes[i].id()] = i; } // Initializations @@ -520,112 +6681,110 @@ var elesfn = ({ var predecessor = []; var predEdge = []; - for( var i = 0; i < numNodes; i++ ){ - if( nodes[ i ].id() === source.id() ){ - cost[ i ] = 0; + for (var i = 0; i < numNodes; i++) { + if (nodes[i].id() === source.id()) { + cost[i] = 0; } else { - cost[ i ] = Infinity; + cost[i] = Infinity; } - predecessor[ i ] = undefined; + predecessor[i] = undefined; } // Edges relaxation var flag = false; - for( var i = 1; i < numNodes; i++ ){ + for (var i = 1; i < numNodes; i++) { flag = false; - for( var e = 0; e < edges.length; e++ ){ - var sourceIndex = id2position[ edges[ e ].source().id() ]; - var targetIndex = id2position[ edges[ e ].target().id() ]; - var weight = weightFn.apply( edges[ e ], [ edges[ e ] ] ); + for (var e = 0; e < edges.length; e++) { + var sourceIndex = id2position[edges[e].source().id()]; + var targetIndex = id2position[edges[e].target().id()]; + var weight = weightFn(edges[e]); - var temp = cost[ sourceIndex ] + weight; - if( temp < cost[ targetIndex ] ){ - cost[ targetIndex ] = temp; - predecessor[ targetIndex ] = sourceIndex; - predEdge[ targetIndex ] = edges[ e ]; + var temp = cost[sourceIndex] + weight; + if (temp < cost[targetIndex]) { + cost[targetIndex] = temp; + predecessor[targetIndex] = sourceIndex; + predEdge[targetIndex] = edges[e]; flag = true; } // If undirected graph, we need to take into account the 'reverse' edge - if( !directed ){ - var temp = cost[ targetIndex ] + weight; - if( temp < cost[ sourceIndex ] ){ - cost[ sourceIndex ] = temp; - predecessor[ sourceIndex ] = targetIndex; - predEdge[ sourceIndex ] = edges[ e ]; + if (!directed) { + var temp = cost[targetIndex] + weight; + if (temp < cost[sourceIndex]) { + cost[sourceIndex] = temp; + predecessor[sourceIndex] = targetIndex; + predEdge[sourceIndex] = edges[e]; flag = true; } } } - if( !flag ){ + if (!flag) { break; } } - if( flag ){ + if (flag) { // Check for negative weight cycles - for( var e = 0; e < edges.length; e++ ){ - var sourceIndex = id2position[ edges[ e ].source().id() ]; - var targetIndex = id2position[ edges[ e ].target().id() ]; - var weight = weightFn.apply( edges[ e ], [ edges[ e ] ] ); + for (var e = 0; e < edges.length; e++) { + var sourceIndex = id2position[edges[e].source().id()]; + var targetIndex = id2position[edges[e].target().id()]; + var weight = weightFn(edges[e]); - if( cost[ sourceIndex ] + weight < cost[ targetIndex ] ){ - util.error( 'Graph contains a negative weight cycle for Bellman-Ford' ); + if (cost[sourceIndex] + weight < cost[targetIndex]) { + util.error('Graph contains a negative weight cycle for Bellman-Ford'); return { pathTo: undefined, - distanceTo: undefined, - hasNegativeWeightCycle: true}; + distanceTo: undefined, + hasNegativeWeightCycle: true }; } } } // Build result object var position2id = []; - for( var i = 0; i < numNodes; i++ ){ - position2id.push( nodes[ i ].id() ); + for (var i = 0; i < numNodes; i++) { + position2id.push(nodes[i].id()); } - var res = { - distanceTo: function( to ){ - if( is.string( to ) ){ + distanceTo: function distanceTo(to) { + if (is.string(to)) { // to is a selector string - var toId = (cy.filter( to )[0]).id(); + var toId = cy.filter(to)[0].id(); } else { // to is a node var toId = to.id(); } - return cost[ id2position[ toId ] ]; + return cost[id2position[toId]]; }, - pathTo: function( to ){ + pathTo: function pathTo(to) { - var reconstructPathAux = function( predecessor, fromPos, toPos, position2id, acumPath, predEdge ){ - for( ;; ){ + var reconstructPathAux = function reconstructPathAux(predecessor, fromPos, toPos, position2id, acumPath, predEdge) { + for (;;) { // Add toId to path - acumPath.push( cy.getElementById( position2id[ toPos ] ) ); - acumPath.push( predEdge[ toPos ] ); + acumPath.push(cy.getElementById(position2id[toPos])); + acumPath.push(predEdge[toPos]); - if( fromPos === toPos ){ + if (fromPos === toPos) { // reached starting node return acumPath; } // If no path exists, discart acumulated path and return undefined - var predPos = predecessor[ toPos ]; - if( typeof predPos === 'undefined' ){ + var predPos = predecessor[toPos]; + if (typeof predPos === 'undefined') { return undefined; } toPos = predPos; } - }; - if( is.string( to ) ){ + if (is.string(to)) { // to is a selector string - var toId = (cy.filter( to )[0]).id(); + var toId = cy.filter(to)[0].id(); } else { // to is a node var toId = to.id(); @@ -633,47 +6792,741 @@ var elesfn = ({ var path = []; // This returns a reversed path - var res = reconstructPathAux( predecessor, - id2position[ source.id() ], - id2position[ toId ], - position2id, - path, - predEdge ); + var res = reconstructPathAux(predecessor, id2position[source.id()], id2position[toId], position2id, path, predEdge); // Get it in the correct order and return it - if( res != null ){ + if (res != null) { res.reverse(); } - return eles.spawn( res ); + return eles.spawn(res); }, hasNegativeWeightCycle: false }; return res; - } // bellmanFord -}); // elesfn +}; // elesfn module.exports = elesfn; -},{"../../is":83,"../../util":100}],5:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 38 */ +/***/ (function(module, exports, __webpack_require__) { -var is = _dereq_( '../../is' ); -var Heap = _dereq_( '../../heap' ); +"use strict"; -var elesfn = ({ + +var util = __webpack_require__(1); + +var elesfn = { + + // Computes the minimum cut of an undirected graph + // Returns the correct answer with high probability + kargerStein: function kargerStein(options) { + var eles = this; + + options = options || {}; + + // Function which colapses 2 (meta) nodes into one + // Updates the remaining edge lists + // Receives as a paramater the edge which causes the collapse + var colapse = function colapse(edgeIndex, nodeMap, remainingEdges) { + var edgeInfo = remainingEdges[edgeIndex]; + var sourceIn = edgeInfo[1]; + var targetIn = edgeInfo[2]; + var partition1 = nodeMap[sourceIn]; + var partition2 = nodeMap[targetIn]; + + // Delete all edges between partition1 and partition2 + var newEdges = remainingEdges.filter(function (edge) { + if (nodeMap[edge[1]] === partition1 && nodeMap[edge[2]] === partition2) { + return false; + } + if (nodeMap[edge[1]] === partition2 && nodeMap[edge[2]] === partition1) { + return false; + } + return true; + }); + + // All edges pointing to partition2 should now point to partition1 + for (var i = 0; i < newEdges.length; i++) { + var edge = newEdges[i]; + if (edge[1] === partition2) { + // Check source + newEdges[i] = edge.slice(0); + newEdges[i][1] = partition1; + } else if (edge[2] === partition2) { + // Check target + newEdges[i] = edge.slice(0); + newEdges[i][2] = partition1; + } + } + + // Move all nodes from partition2 to partition1 + for (var i = 0; i < nodeMap.length; i++) { + if (nodeMap[i] === partition2) { + nodeMap[i] = partition1; + } + } + + return newEdges; + }; + + // Contracts a graph until we reach a certain number of meta nodes + var contractUntil = function contractUntil(metaNodeMap, remainingEdges, size, sizeLimit) { + // Stop condition + if (size <= sizeLimit) { + return remainingEdges; + } + + // Choose an edge randomly + var edgeIndex = Math.floor(Math.random() * remainingEdges.length); + + // Colapse graph based on edge + var newEdges = colapse(edgeIndex, metaNodeMap, remainingEdges); + + return contractUntil(metaNodeMap, newEdges, size - 1, sizeLimit); + }; + + var cy = this._private.cy; + var edges = this.edges().stdFilter(function (e) { + return !e.isLoop(); + }); + var nodes = this.nodes(); + var numNodes = nodes.length; + var numEdges = edges.length; + var numIter = Math.ceil(Math.pow(Math.log(numNodes) / Math.LN2, 2)); + var stopSize = Math.floor(numNodes / Math.sqrt(2)); + + if (numNodes < 2) { + util.error('At least 2 nodes are required for Karger-Stein algorithm'); + return undefined; + } + + // Create numerical identifiers for each node + // mapping: node id -> position in nodes array + // for reverse mapping, simply use nodes array + var id2position = {}; + for (var i = 0; i < numNodes; i++) { + id2position[nodes[i].id()] = i; + } + + // Now store edge destination as indexes + // Format for each edge (edge index, source node index, target node index) + var edgeIndexes = []; + for (var i = 0; i < numEdges; i++) { + var e = edges[i]; + edgeIndexes.push([i, id2position[e.source().id()], id2position[e.target().id()]]); + } + + // We will store the best cut found here + var minCutSize = Infinity; + var minCut; + + // Initial meta node partition + var originalMetaNode = []; + for (var i = 0; i < numNodes; i++) { + originalMetaNode.push(i); + } + + // Main loop + for (var iter = 0; iter <= numIter; iter++) { + // Create new meta node partition + var metaNodeMap = originalMetaNode.slice(0); + + // Contract until stop point (stopSize nodes) + var edgesState = contractUntil(metaNodeMap, edgeIndexes, numNodes, stopSize); + + // Create a copy of the colapsed nodes state + var metaNodeMap2 = metaNodeMap.slice(0); + + // Run 2 iterations starting in the stop state + var res1 = contractUntil(metaNodeMap, edgesState, stopSize, 2); + var res2 = contractUntil(metaNodeMap2, edgesState, stopSize, 2); + + // Is any of the 2 results the best cut so far? + if (res1.length <= res2.length && res1.length < minCutSize) { + minCutSize = res1.length; + minCut = [res1, metaNodeMap]; + } else if (res2.length <= res1.length && res2.length < minCutSize) { + minCutSize = res2.length; + minCut = [res2, metaNodeMap2]; + } + } // end of main loop + + + // Construct result + var resEdges = minCut[0].map(function (e) { + return edges[e[0]]; + }); + var partition1 = []; + var partition2 = []; + + // traverse metaNodeMap for best cut + var witnessNodePartition = minCut[1][0]; + for (var i = 0; i < minCut[1].length; i++) { + var partitionId = minCut[1][i]; + if (partitionId === witnessNodePartition) { + partition1.push(nodes[i]); + } else { + partition2.push(nodes[i]); + } + } + + var ret = { + cut: eles.spawn(cy, resEdges), + partition1: eles.spawn(partition1), + partition2: eles.spawn(partition2) + }; + + return ret; + } +}; // elesfn + + +module.exports = elesfn; + +/***/ }), +/* 39 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var is = __webpack_require__(0); + +var elesfn = { + + pageRank: function pageRank(options) { + options = options || {}; + + var normalizeVector = function normalizeVector(vector) { + var length = vector.length; + + // First, get sum of all elements + var total = 0; + for (var i = 0; i < length; i++) { + total += vector[i]; + } + + // Now, divide each by the sum of all elements + for (var i = 0; i < length; i++) { + vector[i] = vector[i] / total; + } + }; + + // dampingFactor - optional + if (options != null && options.dampingFactor != null) { + var dampingFactor = options.dampingFactor; + } else { + var dampingFactor = 0.8; // Default damping factor + } + + // desired precision - optional + if (options != null && options.precision != null) { + var epsilon = options.precision; + } else { + var epsilon = 0.000001; // Default precision + } + + // Max number of iterations - optional + if (options != null && options.iterations != null) { + var numIter = options.iterations; + } else { + var numIter = 200; // Default number of iterations + } + + // Weight function - optional + if (options != null && options.weight != null && is.fn(options.weight)) { + var weightFn = options.weight; + } else { + // If not specified, assume each edge has equal weight (1) + var weightFn = function weightFn(e) { + return 1; + }; + } + + var cy = this._private.cy; + var edges = this.edges().stdFilter(function (e) { + return !e.isLoop(); + }); + var nodes = this.nodes(); + var numNodes = nodes.length; + var numEdges = edges.length; + + // Create numerical identifiers for each node + // mapping: node id -> position in nodes array + // for reverse mapping, simply use nodes array + var id2position = {}; + for (var i = 0; i < numNodes; i++) { + id2position[nodes[i].id()] = i; + } + + // Construct transposed adjacency matrix + // First lets have a zeroed matrix of the right size + // We'll also keep track of the sum of each column + var matrix = []; + var columnSum = []; + var additionalProb = (1 - dampingFactor) / numNodes; + + // Create null matric + for (var i = 0; i < numNodes; i++) { + var newRow = []; + for (var j = 0; j < numNodes; j++) { + newRow.push(0.0); + } + matrix.push(newRow); + columnSum.push(0.0); + } + + // Now, process edges + for (var i = 0; i < numEdges; i++) { + var edge = edges[i]; + var s = id2position[edge.source().id()]; + var t = id2position[edge.target().id()]; + var w = weightFn(edge); + + // Update matrix + matrix[t][s] += w; + + // Update column sum + columnSum[s] += w; + } + + // Add additional probability based on damping factor + // Also, take into account columns that have sum = 0 + var p = 1.0 / numNodes + additionalProb; // Shorthand + // Traverse matrix, column by column + for (var j = 0; j < numNodes; j++) { + if (columnSum[j] === 0) { + // No 'links' out from node jth, assume equal probability for each possible node + for (var i = 0; i < numNodes; i++) { + matrix[i][j] = p; + } + } else { + // Node jth has outgoing link, compute normalized probabilities + for (var i = 0; i < numNodes; i++) { + matrix[i][j] = matrix[i][j] / columnSum[j] + additionalProb; + } + } + } + + // Compute dominant eigenvector using power method + var eigenvector = []; + var nullVector = []; + var previous; + + // Start with a vector of all 1's + // Also, initialize a null vector which will be used as shorthand + for (var i = 0; i < numNodes; i++) { + eigenvector.push(1.0); + nullVector.push(0.0); + } + + for (var iter = 0; iter < numIter; iter++) { + // New array with all 0's + var temp = nullVector.slice(0); + + // Multiply matrix with previous result + for (var i = 0; i < numNodes; i++) { + for (var j = 0; j < numNodes; j++) { + temp[i] += matrix[i][j] * eigenvector[j]; + } + } + + normalizeVector(temp); + previous = eigenvector; + eigenvector = temp; + + var diff = 0; + // Compute difference (squared module) of both vectors + for (var i = 0; i < numNodes; i++) { + diff += Math.pow(previous[i] - eigenvector[i], 2); + } + + // If difference is less than the desired threshold, stop iterating + if (diff < epsilon) { + break; + } + } + + // Construct result + var res = { + rank: function rank(node) { + if (is.string(node)) { + // is a selector string + var nodeId = cy.filter(node)[0].id(); + } else { + // is a node object + var nodeId = node.id(); + } + return eigenvector[id2position[nodeId]]; + } + }; + + return res; + } // pageRank + +}; // elesfn + +module.exports = elesfn; + +/***/ }), +/* 40 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var is = __webpack_require__(0); +var util = __webpack_require__(1); + +var elesfn = { + + degreeCentralityNormalized: function degreeCentralityNormalized(options) { + options = options || {}; + + var cy = this.cy(); + + // directed - optional + if (options.directed != null) { + var directed = options.directed; + } else { + var directed = false; + } + + var nodes = this.nodes(); + var numNodes = nodes.length; + + if (!directed) { + var degrees = {}; + var maxDegree = 0; + + for (var i = 0; i < numNodes; i++) { + var node = nodes[i]; + // add current node to the current options object and call degreeCentrality + var currDegree = this.degreeCentrality(util.extend({}, options, { root: node })); + if (maxDegree < currDegree.degree) maxDegree = currDegree.degree; + + degrees[node.id()] = currDegree.degree; + } + + return { + degree: function degree(node) { + if (maxDegree == 0) return 0; + + if (is.string(node)) { + // from is a selector string + var node = cy.filter(node)[0].id(); + } else { + // from is a node + var node = node.id(); + } + + return degrees[node] / maxDegree; + } + }; + } else { + var indegrees = {}; + var outdegrees = {}; + var maxIndegree = 0; + var maxOutdegree = 0; + + for (var i = 0; i < numNodes; i++) { + var node = nodes[i]; + // add current node to the current options object and call degreeCentrality + var currDegree = this.degreeCentrality(util.extend({}, options, { root: node })); + + if (maxIndegree < currDegree.indegree) maxIndegree = currDegree.indegree; + + if (maxOutdegree < currDegree.outdegree) maxOutdegree = currDegree.outdegree; + + indegrees[node.id()] = currDegree.indegree; + outdegrees[node.id()] = currDegree.outdegree; + } + + return { + indegree: function indegree(node) { + if (maxIndegree == 0) return 0; + + if (is.string(node)) { + // from is a selector string + var node = cy.filter(node)[0].id(); + } else { + // from is a node + var node = node.id(); + } + + return indegrees[node] / maxIndegree; + }, + outdegree: function outdegree(node) { + if (maxOutdegree == 0) return 0; + + if (is.string(node)) { + // from is a selector string + var node = cy.filter(node)[0].id(); + } else { + // from is a node + var node = node.id(); + } + + return outdegrees[node] / maxOutdegree; + } + + }; + } + }, // degreeCentralityNormalized + + // Implemented from the algorithm in Opsahl's paper + // "Node centrality in weighted networks: Generalizing degree and shortest paths" + // check the heading 2 "Degree" + degreeCentrality: function degreeCentrality(options) { + options = options || {}; + + var callingEles = this; + + // root - mandatory! + if (options != null && options.root != null) { + var root = is.string(options.root) ? this.filter(options.root)[0] : options.root[0]; + } else { + return undefined; + } + + // weight - optional + if (options.weight != null && is.fn(options.weight)) { + var weightFn = options.weight; + } else { + // If not specified, assume each edge has equal weight (1) + var weightFn = function weightFn(e) { + return 1; + }; + } + + // directed - optional + if (options.directed != null) { + var directed = options.directed; + } else { + var directed = false; + } + + // alpha - optional + if (options.alpha != null && is.number(options.alpha)) { + var alpha = options.alpha; + } else { + alpha = 0; + } + + if (!directed) { + var connEdges = root.connectedEdges().intersection(callingEles); + var k = connEdges.length; + var s = 0; + + // Now, sum edge weights + for (var i = 0; i < connEdges.length; i++) { + var edge = connEdges[i]; + s += weightFn(edge); + } + + return { + degree: Math.pow(k, 1 - alpha) * Math.pow(s, alpha) + }; + } else { + var incoming = root.connectedEdges('edge[target = "' + root.id() + '"]').intersection(callingEles); + var outgoing = root.connectedEdges('edge[source = "' + root.id() + '"]').intersection(callingEles); + var k_in = incoming.length; + var k_out = outgoing.length; + var s_in = 0; + var s_out = 0; + + // Now, sum incoming edge weights + for (var i = 0; i < incoming.length; i++) { + var edge = incoming[i]; + s_in += weightFn(edge); + } + + // Now, sum outgoing edge weights + for (var i = 0; i < outgoing.length; i++) { + var edge = outgoing[i]; + s_out += weightFn(edge); + } + + return { + indegree: Math.pow(k_in, 1 - alpha) * Math.pow(s_in, alpha), + outdegree: Math.pow(k_out, 1 - alpha) * Math.pow(s_out, alpha) + }; + } + } // degreeCentrality + +}; // elesfn + +// nice, short mathemathical alias +elesfn.dc = elesfn.degreeCentrality; +elesfn.dcn = elesfn.degreeCentralityNormalised = elesfn.degreeCentralityNormalized; + +module.exports = elesfn; + +/***/ }), +/* 41 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var is = __webpack_require__(0); + +var elesfn = { + + closenessCentralityNormalized: function closenessCentralityNormalized(options) { + options = options || {}; + + var cy = this.cy(); + + var harmonic = options.harmonic; + if (harmonic === undefined) { + harmonic = true; + } + + var closenesses = {}; + var maxCloseness = 0; + var nodes = this.nodes(); + var fw = this.floydWarshall({ weight: options.weight, directed: options.directed }); + + // Compute closeness for every node and find the maximum closeness + for (var i = 0; i < nodes.length; i++) { + var currCloseness = 0; + for (var j = 0; j < nodes.length; j++) { + if (i != j) { + var d = fw.distance(nodes[i], nodes[j]); + + if (harmonic) { + currCloseness += 1 / d; + } else { + currCloseness += d; + } + } + } + + if (!harmonic) { + currCloseness = 1 / currCloseness; + } + + if (maxCloseness < currCloseness) { + maxCloseness = currCloseness; + } + + closenesses[nodes[i].id()] = currCloseness; + } + + return { + closeness: function closeness(node) { + if (maxCloseness == 0) { + return 0; + } + + if (is.string(node)) { + // from is a selector string + var node = cy.filter(node)[0].id(); + } else { + // from is a node + var node = node.id(); + } + + return closenesses[node] / maxCloseness; + } + }; + }, + + // Implemented from pseudocode from wikipedia + closenessCentrality: function closenessCentrality(options) { + options = options || {}; + + // root - mandatory! + if (options.root != null) { + if (is.string(options.root)) { + // use it as a selector, e.g. "#rootID + var root = this.filter(options.root)[0]; + } else { + var root = options.root[0]; + } + } else { + return undefined; + } + + // weight - optional + if (options.weight != null && is.fn(options.weight)) { + var weight = options.weight; + } else { + var weight = function weight() { + return 1; + }; + } + + // directed - optional + if (options.directed != null && is.bool(options.directed)) { + var directed = options.directed; + } else { + var directed = false; + } + + var harmonic = options.harmonic; + if (harmonic === undefined) { + harmonic = true; + } + + // we need distance from this node to every other node + var dijkstra = this.dijkstra({ + root: root, + weight: weight, + directed: directed + }); + var totalDistance = 0; + + var nodes = this.nodes(); + for (var i = 0; i < nodes.length; i++) { + if (nodes[i].id() != root.id()) { + var d = dijkstra.distanceTo(nodes[i]); + + if (harmonic) { + totalDistance += 1 / d; + } else { + totalDistance += d; + } + } + } + + return harmonic ? totalDistance : 1 / totalDistance; + } // closenessCentrality + +}; // elesfn + +// nice, short mathemathical alias +elesfn.cc = elesfn.closenessCentrality; +elesfn.ccn = elesfn.closenessCentralityNormalised = elesfn.closenessCentralityNormalized; + +module.exports = elesfn; + +/***/ }), +/* 42 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var is = __webpack_require__(0); +var Heap = __webpack_require__(9); + +var elesfn = { // Implemented from the algorithm in the paper "On Variants of Shortest-Path Betweenness Centrality and their Generic Computation" by Ulrik Brandes - betweennessCentrality: function( options ){ + betweennessCentrality: function betweennessCentrality(options) { options = options || {}; // Weight - optional var weighted, weightFn; - if( is.fn( options.weight ) ){ + if (is.fn(options.weight)) { weightFn = options.weight; weighted = true; } else { @@ -689,151 +7542,159 @@ var elesfn = ({ var V = this.nodes(); var A = {}; var _C = {}; - var max; + var max = 0; var C = { - set: function( key, val ){ - _C[ key ] = val; + set: function set(key, val) { + _C[key] = val; - if( val > max ){ max = val; } + if (val > max) { + max = val; + } }, - get: function( key ){ return _C[ key ]; } + get: function get(key) { + return _C[key]; + } }; // A contains the neighborhoods of every node - for( var i = 0; i < V.length; i++ ){ - var v = V[ i ]; + for (var i = 0; i < V.length; i++) { + var v = V[i]; var vid = v.id(); - if( directed ){ - A[ vid ] = v.outgoers().nodes(); // get outgoers of every node + if (directed) { + A[vid] = v.outgoers().nodes(); // get outgoers of every node } else { - A[ vid ] = v.openNeighborhood().nodes(); // get neighbors of every node + A[vid] = v.openNeighborhood().nodes(); // get neighbors of every node } - C.set( vid, 0 ); + C.set(vid, 0); } - for( var s = 0; s < V.length; s++ ){ + for (var s = 0; s < V.length; s++) { var sid = V[s].id(); var S = []; // stack var P = {}; var g = {}; var d = {}; - var Q = new Heap(function( a, b ){ + var Q = new Heap(function (a, b) { return d[a] - d[b]; }); // queue // init dictionaries - for( var i = 0; i < V.length; i++ ){ - var vid = V[ i ].id(); + for (var i = 0; i < V.length; i++) { + var vid = V[i].id(); - P[ vid ] = []; - g[ vid ] = 0; - d[ vid ] = Infinity; + P[vid] = []; + g[vid] = 0; + d[vid] = Infinity; } - g[ sid ] = 1; // sigma - d[ sid ] = 0; // distance to s + g[sid] = 1; // sigma + d[sid] = 0; // distance to s - Q.push( sid ); + Q.push(sid); - while( !Q.empty() ){ + while (!Q.empty()) { var v = Q.pop(); - S.push( v ); + S.push(v); - if( weighted ){ - for( var j = 0; j < A[v].length; j++ ){ + if (weighted) { + for (var j = 0; j < A[v].length; j++) { var w = A[v][j]; - var vEle = cy.getElementById( v ); + var vEle = cy.getElementById(v); var edge; - if( vEle.edgesTo( w ).length > 0 ){ - edge = vEle.edgesTo( w )[0]; + if (vEle.edgesTo(w).length > 0) { + edge = vEle.edgesTo(w)[0]; } else { - edge = w.edgesTo( vEle )[0]; + edge = w.edgesTo(vEle)[0]; } - var edgeWeight = weightFn.apply( edge, [ edge ] ); + var edgeWeight = weightFn(edge); w = w.id(); - if( d[w] > d[v] + edgeWeight ){ + if (d[w] > d[v] + edgeWeight) { d[w] = d[v] + edgeWeight; - if( Q.nodes.indexOf( w ) < 0 ){ //if w is not in Q - Q.push( w ); - } else { // update position if w is in Q - Q.updateItem( w ); + if (Q.nodes.indexOf(w) < 0) { + //if w is not in Q + Q.push(w); + } else { + // update position if w is in Q + Q.updateItem(w); } g[w] = 0; P[w] = []; } - if( d[w] == d[v] + edgeWeight ){ + if (d[w] == d[v] + edgeWeight) { g[w] = g[w] + g[v]; - P[w].push( v ); + P[w].push(v); } } } else { - for( var j = 0; j < A[v].length; j++ ){ + for (var j = 0; j < A[v].length; j++) { var w = A[v][j].id(); - if( d[w] == Infinity ){ - Q.push( w ); + if (d[w] == Infinity) { + Q.push(w); d[w] = d[v] + 1; } - if( d[w] == d[v] + 1 ){ + if (d[w] == d[v] + 1) { g[w] = g[w] + g[v]; - P[w].push( v ); + P[w].push(v); } } } } var e = {}; - for( var i = 0; i < V.length; i++ ){ - e[ V[ i ].id() ] = 0; + for (var i = 0; i < V.length; i++) { + e[V[i].id()] = 0; } - while( S.length > 0 ){ + while (S.length > 0) { var w = S.pop(); - for( var j = 0; j < P[w].length; j++ ){ + for (var j = 0; j < P[w].length; j++) { var v = P[w][j]; - e[v] = e[v] + (g[v] / g[w]) * (1 + e[w]); + e[v] = e[v] + g[v] / g[w] * (1 + e[w]); - if( w != V[s].id() ){ - C.set( w, C.get( w ) + e[w] ); + if (w != V[s].id()) { + C.set(w, C.get(w) + e[w]); } } } } var ret = { - betweenness: function( node ){ - if( is.string( node ) ){ - var node = cy.filter( node ).id(); + betweenness: function betweenness(node) { + if (is.string(node)) { + var node = cy.filter(node).id(); } else { var node = node.id(); } - return C.get( node ); + return C.get(node); }, - betweennessNormalized: function( node ){ - if( is.string( node ) ){ - var node = cy.filter( node ).id(); + betweennessNormalized: function betweennessNormalized(node) { + if (max == 0) return 0; + + if (is.string(node)) { + var node = cy.filter(node).id(); } else { var node = node.id(); } - return C.get( node ) / max; + return C.get(node) / max; } }; @@ -843,1257 +7704,23 @@ var elesfn = ({ return ret; } // betweennessCentrality -}); // elesfn +}; // elesfn // nice, short mathemathical alias elesfn.bc = elesfn.betweennessCentrality; module.exports = elesfn; -},{"../../heap":81,"../../is":83}],6:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 43 */ +/***/ (function(module, exports, __webpack_require__) { -var is = _dereq_( '../../is' ); +"use strict"; -var defineSearch = function( params ){ - params = { - bfs: params.bfs || !params.dfs, - dfs: params.dfs || !params.bfs - }; - // from pseudocode on wikipedia - return function searchFn( roots, fn, directed ){ - var options; - var std; - var thisArg; - if( is.plainObject( roots ) && !is.elementOrCollection( roots ) ){ - options = roots; - roots = options.roots || options.root; - fn = options.visit; - directed = options.directed; - std = options.std; - thisArg = options.thisArg; - } +var define = __webpack_require__(4); - directed = arguments.length === 2 && !is.fn( fn ) ? fn : directed; - fn = is.fn( fn ) ? fn : function(){}; - - var cy = this._private.cy; - var v = roots = is.string( roots ) ? this.filter( roots ) : roots; - var Q = []; - var connectedNodes = []; - var connectedBy = {}; - var id2depth = {}; - var V = {}; - var j = 0; - var found; - var nodes = this.nodes(); - var edges = this.edges(); - - // enqueue v - for( var i = 0; i < v.length; i++ ){ - if( v[ i ].isNode() ){ - Q.unshift( v[ i ] ); - - if( params.bfs ){ - V[ v[ i ].id() ] = true; - - connectedNodes.push( v[ i ] ); - } - - id2depth[ v[ i ].id() ] = 0; - } - } - - while( Q.length !== 0 ){ - var v = params.bfs ? Q.shift() : Q.pop(); - - if( params.dfs ){ - if( V[ v.id() ] ){ continue; } - - V[ v.id() ] = true; - - connectedNodes.push( v ); - } - - var depth = id2depth[ v.id() ]; - var prevEdge = connectedBy[ v.id() ]; - var prevNode = prevEdge == null ? undefined : prevEdge.connectedNodes().not( v )[0]; - var ret; - - if( std ){ - ret = fn.call( thisArg, v, prevEdge, prevNode, j++, depth ); - } else { - ret = fn.call( v, j++, depth, v, prevEdge, prevNode ); - } - - if( ret === true ){ - found = v; - break; - } - - if( ret === false ){ - break; - } - - var vwEdges = v.connectedEdges( directed ? function(){ return this.data( 'source' ) === v.id(); } : undefined ).intersect( edges ); - for( var i = 0; i < vwEdges.length; i++ ){ - var e = vwEdges[ i ]; - var w = e.connectedNodes( function(){ return this.id() !== v.id(); } ).intersect( nodes ); - - if( w.length !== 0 && !V[ w.id() ] ){ - w = w[0]; - - Q.push( w ); - - if( params.bfs ){ - V[ w.id() ] = true; - - connectedNodes.push( w ); - } - - connectedBy[ w.id() ] = e; - - id2depth[ w.id() ] = id2depth[ v.id() ] + 1; - } - } - - } - - var connectedEles = []; - - for( var i = 0; i < connectedNodes.length; i++ ){ - var node = connectedNodes[ i ]; - var edge = connectedBy[ node.id() ]; - - if( edge ){ - connectedEles.push( edge ); - } - - connectedEles.push( node ); - } - - return { - path: cy.collection( connectedEles, { unique: true } ), - found: cy.collection( found ) - }; - }; -}; - -// search, spanning trees, etc -var elesfn = ({ - breadthFirstSearch: defineSearch( { bfs: true } ), - depthFirstSearch: defineSearch( { dfs: true } ) -}); - -// nice, short mathemathical alias -elesfn.bfs = elesfn.breadthFirstSearch; -elesfn.dfs = elesfn.depthFirstSearch; - -module.exports = elesfn; - -},{"../../is":83}],7:[function(_dereq_,module,exports){ -'use strict'; - -var is = _dereq_( '../../is' ); - -var elesfn = ({ - - closenessCentralityNormalized: function( options ){ - options = options || {}; - - var cy = this.cy(); - - var harmonic = options.harmonic; - if( harmonic === undefined ){ - harmonic = true; - } - - var closenesses = {}; - var maxCloseness = 0; - var nodes = this.nodes(); - var fw = this.floydWarshall( { weight: options.weight, directed: options.directed } ); - - // Compute closeness for every node and find the maximum closeness - for( var i = 0; i < nodes.length; i++ ){ - var currCloseness = 0; - for( var j = 0; j < nodes.length; j++ ){ - if( i != j ){ - var d = fw.distance( nodes[ i ], nodes[ j ] ); - - if( harmonic ){ - currCloseness += 1 / d; - } else { - currCloseness += d; - } - } - } - - if( !harmonic ){ - currCloseness = 1 / currCloseness; - } - - if( maxCloseness < currCloseness ){ - maxCloseness = currCloseness; - } - - closenesses[ nodes[ i ].id() ] = currCloseness; - } - - return { - closeness: function( node ){ - if( is.string( node ) ){ - // from is a selector string - var node = (cy.filter( node )[0]).id(); - } else { - // from is a node - var node = node.id(); - } - - return closenesses[ node ] / maxCloseness; - } - }; - }, - - // Implemented from pseudocode from wikipedia - closenessCentrality: function( options ){ - options = options || {}; - - // root - mandatory! - if( options.root != null ){ - if( is.string( options.root ) ){ - // use it as a selector, e.g. "#rootID - var root = this.filter( options.root )[0]; - } else { - var root = options.root[0]; - } - } else { - return undefined; - } - - // weight - optional - if( options.weight != null && is.fn( options.weight ) ){ - var weight = options.weight; - } else { - var weight = function(){return 1;}; - } - - // directed - optional - if( options.directed != null && is.bool( options.directed ) ){ - var directed = options.directed; - } else { - var directed = false; - } - - var harmonic = options.harmonic; - if( harmonic === undefined ){ - harmonic = true; - } - - // we need distance from this node to every other node - var dijkstra = this.dijkstra( { - root: root, - weight: weight, - directed: directed - } ); - var totalDistance = 0; - - var nodes = this.nodes(); - for( var i = 0; i < nodes.length; i++ ){ - if( nodes[ i ].id() != root.id() ){ - var d = dijkstra.distanceTo( nodes[ i ] ); - - if( harmonic ){ - totalDistance += 1 / d; - } else { - totalDistance += d; - } - } - } - - return harmonic ? totalDistance : 1 / totalDistance; - } // closenessCentrality - -}); // elesfn - -// nice, short mathemathical alias -elesfn.cc = elesfn.closenessCentrality; -elesfn.ccn = elesfn.closenessCentralityNormalised = elesfn.closenessCentralityNormalized; - -module.exports = elesfn; - -},{"../../is":83}],8:[function(_dereq_,module,exports){ -'use strict'; - -var is = _dereq_( '../../is' ); -var util = _dereq_( '../../util' ); - -var elesfn = ({ - - degreeCentralityNormalized: function( options ){ - options = options || {}; - - var cy = this.cy(); - - // directed - optional - if( options.directed != null ){ - var directed = options.directed; - } else { - var directed = false; - } - - var nodes = this.nodes(); - var numNodes = nodes.length; - - if( !directed ){ - var degrees = {}; - var maxDegree = 0; - - for( var i = 0; i < numNodes; i++ ){ - var node = nodes[ i ]; - // add current node to the current options object and call degreeCentrality - var currDegree = this.degreeCentrality( util.extend( {}, options, {root: node} ) ); - if( maxDegree < currDegree.degree ) - maxDegree = currDegree.degree; - - degrees[ node.id() ] = currDegree.degree; - } - - return { - degree: function( node ){ - if( is.string( node ) ){ - // from is a selector string - var node = (cy.filter( node )[0]).id(); - } else { - // from is a node - var node = node.id(); - } - - return degrees[ node ] / maxDegree; - } - }; - } else { - var indegrees = {}; - var outdegrees = {}; - var maxIndegree = 0; - var maxOutdegree = 0; - - for( var i = 0; i < numNodes; i++ ){ - var node = nodes[ i ]; - // add current node to the current options object and call degreeCentrality - var currDegree = this.degreeCentrality( util.extend( {}, options, {root: node} ) ); - - if( maxIndegree < currDegree.indegree ) - maxIndegree = currDegree.indegree; - - if( maxOutdegree < currDegree.outdegree ) - maxOutdegree = currDegree.outdegree; - - indegrees[ node.id() ] = currDegree.indegree; - outdegrees[ node.id() ] = currDegree.outdegree; - } - - return { - indegree: function( node ){ - if( is.string( node ) ){ - // from is a selector string - var node = (cy.filter( node )[0]).id(); - } else { - // from is a node - var node = node.id(); - } - - return indegrees[ node ] / maxIndegree; - }, - outdegree: function( node ){ - if( is.string( node ) ){ - // from is a selector string - var node = (cy.filter( node )[0]).id(); - } else { - // from is a node - var node = node.id(); - } - - return outdegrees[ node ] / maxOutdegree; - } - - }; - } - - }, // degreeCentralityNormalized - - // Implemented from the algorithm in Opsahl's paper - // "Node centrality in weighted networks: Generalizing degree and shortest paths" - // check the heading 2 "Degree" - degreeCentrality: function( options ){ - options = options || {}; - - var callingEles = this; - - // root - mandatory! - if( options != null && options.root != null ){ - var root = is.string( options.root ) ? this.filter( options.root )[0] : options.root[0]; - } else { - return undefined; - } - - // weight - optional - if( options.weight != null && is.fn( options.weight ) ){ - var weightFn = options.weight; - } else { - // If not specified, assume each edge has equal weight (1) - var weightFn = function( e ){ - return 1; - }; - } - - // directed - optional - if( options.directed != null ){ - var directed = options.directed; - } else { - var directed = false; - } - - // alpha - optional - if( options.alpha != null && is.number( options.alpha ) ){ - var alpha = options.alpha; - } else { - alpha = 0; - } - - - if( !directed ){ - var connEdges = root.connectedEdges().intersection( callingEles ); - var k = connEdges.length; - var s = 0; - - // Now, sum edge weights - for( var i = 0; i < connEdges.length; i++ ){ - var edge = connEdges[ i ]; - s += weightFn.apply( edge, [ edge ] ); - } - - return { - degree: Math.pow( k, 1 - alpha ) * Math.pow( s, alpha ) - }; - } else { - var incoming = root.connectedEdges( 'edge[target = "' + root.id() + '"]' ).intersection( callingEles ); - var outgoing = root.connectedEdges( 'edge[source = "' + root.id() + '"]' ).intersection( callingEles ); - var k_in = incoming.length; - var k_out = outgoing.length; - var s_in = 0; - var s_out = 0; - - // Now, sum incoming edge weights - for( var i = 0; i < incoming.length; i++ ){ - var edge = incoming[ i ]; - s_in += weightFn.apply( edge, [ edge ] ); - } - - // Now, sum outgoing edge weights - for( var i = 0; i < outgoing.length; i++ ){ - var edge = outgoing[ i ]; - s_out += weightFn.apply( edge, [ edge ] ); - } - - return { - indegree: Math.pow( k_in, 1 - alpha ) * Math.pow( s_in, alpha ), - outdegree: Math.pow( k_out, 1 - alpha ) * Math.pow( s_out, alpha ) - }; - } - } // degreeCentrality - -}); // elesfn - -// nice, short mathemathical alias -elesfn.dc = elesfn.degreeCentrality; -elesfn.dcn = elesfn.degreeCentralityNormalised = elesfn.degreeCentralityNormalized; - -module.exports = elesfn; - -},{"../../is":83,"../../util":100}],9:[function(_dereq_,module,exports){ -'use strict'; - -var is = _dereq_( '../../is' ); -var Heap = _dereq_( '../../heap' ); - -var elesfn = ({ - - dijkstra: function( root, weightFn, directed ){ - var options; - if( is.plainObject( root ) && !is.elementOrCollection( root ) ){ - options = root; - root = options.root; - weightFn = options.weight; - directed = options.directed; - } - - var cy = this._private.cy; - weightFn = is.fn( weightFn ) ? weightFn : function(){ return 1; }; // if not specified, assume each edge has equal weight (1) - - var source = is.string( root ) ? this.filter( root )[0] : root[0]; - var dist = {}; - var prev = {}; - var knownDist = {}; - - var edges = this.edges().filter( function(){ return !this.isLoop(); } ); - var nodes = this.nodes(); - - var getDist = function( node ){ - return dist[ node.id() ]; - }; - - var setDist = function( node, d ){ - dist[ node.id() ] = d; - - Q.updateItem( node ); - }; - - var Q = new Heap( function( a, b ){ - return getDist( a ) - getDist( b ); - } ); - - for( var i = 0; i < nodes.length; i++ ){ - var node = nodes[ i ]; - - dist[ node.id() ] = node.same( source ) ? 0 : Infinity; - Q.push( node ); - } - - var distBetween = function( u, v ){ - var uvs = ( directed ? u.edgesTo( v ) : u.edgesWith( v ) ).intersect( edges ); - var smallestDistance = Infinity; - var smallestEdge; - - for( var i = 0; i < uvs.length; i++ ){ - var edge = uvs[ i ]; - var weight = weightFn.apply( edge, [ edge ] ); - - if( weight < smallestDistance || !smallestEdge ){ - smallestDistance = weight; - smallestEdge = edge; - } - } - - return { - edge: smallestEdge, - dist: smallestDistance - }; - }; - - while( Q.size() > 0 ){ - var u = Q.pop(); - var smalletsDist = getDist( u ); - var uid = u.id(); - - knownDist[ uid ] = smalletsDist; - - if( smalletsDist === Math.Infinite ){ - break; - } - - var neighbors = u.neighborhood().intersect( nodes ); - for( var i = 0; i < neighbors.length; i++ ){ - var v = neighbors[ i ]; - var vid = v.id(); - var vDist = distBetween( u, v ); - - var alt = smalletsDist + vDist.dist; - - if( alt < getDist( v ) ){ - setDist( v, alt ); - - prev[ vid ] = { - node: u, - edge: vDist.edge - }; - } - } // for - } // while - - return { - distanceTo: function( node ){ - var target = is.string( node ) ? nodes.filter( node )[0] : node[0]; - - return knownDist[ target.id() ]; - }, - - pathTo: function( node ){ - var target = is.string( node ) ? nodes.filter( node )[0] : node[0]; - var S = []; - var u = target; - - if( target.length > 0 ){ - S.unshift( target ); - - while( prev[ u.id() ] ){ - var p = prev[ u.id() ]; - - S.unshift( p.edge ); - S.unshift( p.node ); - - u = p.node; - } - } - - return cy.collection( S ); - } - }; - } -}); - -module.exports = elesfn; - -},{"../../heap":81,"../../is":83}],10:[function(_dereq_,module,exports){ -'use strict'; - -var is = _dereq_( '../../is' ); - -var elesfn = ({ - - // Implemented from pseudocode from wikipedia - floydWarshall: function( options ){ - options = options || {}; - - var cy = this.cy(); - - // Weight function - optional - if( options.weight != null && is.fn( options.weight ) ){ - var weightFn = options.weight; - } else { - // If not specified, assume each edge has equal weight (1) - var weightFn = function( e ){return 1;}; - } - - // directed - optional - if( options.directed != null ){ - var directed = options.directed; - } else { - var directed = false; - } - - var edges = this.edges().stdFilter( function( e ){ return !e.isLoop(); } ); - var nodes = this.nodes(); - var numNodes = nodes.length; - - // mapping: node id -> position in nodes array - var id2position = {}; - for( var i = 0; i < numNodes; i++ ){ - id2position[ nodes[ i ].id() ] = i; - } - - // Initialize distance matrix - var dist = []; - for( var i = 0; i < numNodes; i++ ){ - var newRow = new Array( numNodes ); - for( var j = 0; j < numNodes; j++ ){ - if( i == j ){ - newRow[ j ] = 0; - } else { - newRow[ j ] = Infinity; - } - } - dist.push( newRow ); - } - - // Initialize matrix used for path reconstruction - // Initialize distance matrix - var next = []; - var edgeNext = []; - - var initMatrix = function( next ){ - for( var i = 0; i < numNodes; i++ ){ - var newRow = new Array( numNodes ); - for( var j = 0; j < numNodes; j++ ){ - newRow[ j ] = undefined; - } - next.push( newRow ); - } - }; - - initMatrix( next ); - initMatrix( edgeNext ); - - // Process edges - for( var i = 0; i < edges.length ; i++ ){ - var sourceIndex = id2position[ edges[ i ].source().id() ]; - var targetIndex = id2position[ edges[ i ].target().id() ]; - var weight = weightFn.apply( edges[ i ], [ edges[ i ] ] ); - - // Check if already process another edge between same 2 nodes - if( dist[ sourceIndex ][ targetIndex ] > weight ){ - dist[ sourceIndex ][ targetIndex ] = weight; - next[ sourceIndex ][ targetIndex ] = targetIndex; - edgeNext[ sourceIndex ][ targetIndex ] = edges[ i ]; - } - } - - // If undirected graph, process 'reversed' edges - if( !directed ){ - for( var i = 0; i < edges.length ; i++ ){ - var sourceIndex = id2position[ edges[ i ].target().id() ]; - var targetIndex = id2position[ edges[ i ].source().id() ]; - var weight = weightFn.apply( edges[ i ], [ edges[ i ] ] ); - - // Check if already process another edge between same 2 nodes - if( dist[ sourceIndex ][ targetIndex ] > weight ){ - dist[ sourceIndex ][ targetIndex ] = weight; - next[ sourceIndex ][ targetIndex ] = targetIndex; - edgeNext[ sourceIndex ][ targetIndex ] = edges[ i ]; - } - } - } - - // Main loop - for( var k = 0; k < numNodes; k++ ){ - for( var i = 0; i < numNodes; i++ ){ - for( var j = 0; j < numNodes; j++ ){ - if( dist[ i ][ k ] + dist[ k ][ j ] < dist[ i ][ j ] ){ - dist[ i ][ j ] = dist[ i ][ k ] + dist[ k ][ j ]; - next[ i ][ j ] = next[ i ][ k ]; - } - } - } - } - - // Build result object - var position2id = []; - for( var i = 0; i < numNodes; i++ ){ - position2id.push( nodes[ i ].id() ); - } - - var res = { - distance: function( from, to ){ - if( is.string( from ) ){ - // from is a selector string - var fromId = (cy.filter( from )[0]).id(); - } else { - // from is a node - var fromId = from.id(); - } - - if( is.string( to ) ){ - // to is a selector string - var toId = (cy.filter( to )[0]).id(); - } else { - // to is a node - var toId = to.id(); - } - - return dist[ id2position[ fromId ] ][ id2position[ toId ] ]; - }, - - path: function( from, to ){ - var reconstructPathAux = function( from, to, next, position2id, edgeNext ){ - if( from === to ){ - return cy.getElementById( position2id[ from ] ); - } - if( next[ from ][ to ] === undefined ){ - return undefined; - } - - var path = [ cy.getElementById( position2id[ from ] ) ]; - var prev = from; - while( from !== to ){ - prev = from; - from = next[ from ][ to ]; - - var edge = edgeNext[ prev ][ from ]; - path.push( edge ); - - path.push( cy.getElementById( position2id[ from ] ) ); - } - return path; - }; - - if( is.string( from ) ){ - // from is a selector string - var fromId = (cy.filter( from )[0]).id(); - } else { - // from is a node - var fromId = from.id(); - } - - if( is.string( to ) ){ - // to is a selector string - var toId = (cy.filter( to )[0]).id(); - } else { - // to is a node - var toId = to.id(); - } - - var pathArr = reconstructPathAux( id2position[ fromId ], - id2position[ toId ], - next, - position2id, - edgeNext ); - - return cy.collection( pathArr ); - } - }; - - return res; - - } // floydWarshall - -}); // elesfn - -module.exports = elesfn; - -},{"../../is":83}],11:[function(_dereq_,module,exports){ -'use strict'; - -var util = _dereq_( '../../util' ); - -var elesfn = {}; - -[ - _dereq_( './bfs-dfs' ), - _dereq_( './dijkstra' ), - _dereq_( './kruskal' ), - _dereq_( './a-star' ), - _dereq_( './floyd-warshall' ), - _dereq_( './bellman-ford' ), - _dereq_( './kerger-stein' ), - _dereq_( './page-rank' ), - _dereq_( './degree-centrality' ), - _dereq_( './closeness-centrality' ), - _dereq_( './betweenness-centrality' ) -].forEach( function( props ){ - util.extend( elesfn, props ); -} ); - -module.exports = elesfn; - -},{"../../util":100,"./a-star":3,"./bellman-ford":4,"./betweenness-centrality":5,"./bfs-dfs":6,"./closeness-centrality":7,"./degree-centrality":8,"./dijkstra":9,"./floyd-warshall":10,"./kerger-stein":12,"./kruskal":13,"./page-rank":14}],12:[function(_dereq_,module,exports){ -'use strict'; - -var util = _dereq_( '../../util' ); - -var elesfn = ({ - - // Computes the minimum cut of an undirected graph - // Returns the correct answer with high probability - kargerStein: function( options ){ - var eles = this; - - options = options || {}; - - // Function which colapses 2 (meta) nodes into one - // Updates the remaining edge lists - // Receives as a paramater the edge which causes the collapse - var colapse = function( edgeIndex, nodeMap, remainingEdges ){ - var edgeInfo = remainingEdges[ edgeIndex ]; - var sourceIn = edgeInfo[1]; - var targetIn = edgeInfo[2]; - var partition1 = nodeMap[ sourceIn ]; - var partition2 = nodeMap[ targetIn ]; - - // Delete all edges between partition1 and partition2 - var newEdges = remainingEdges.filter( function( edge ){ - if( nodeMap[ edge[1] ] === partition1 && nodeMap[ edge[2] ] === partition2 ){ - return false; - } - if( nodeMap[ edge[1] ] === partition2 && nodeMap[ edge[2] ] === partition1 ){ - return false; - } - return true; - } ); - - // All edges pointing to partition2 should now point to partition1 - for( var i = 0; i < newEdges.length; i++ ){ - var edge = newEdges[ i ]; - if( edge[1] === partition2 ){ // Check source - newEdges[ i ] = edge.slice( 0 ); - newEdges[ i ][1] = partition1; - } else if( edge[2] === partition2 ){ // Check target - newEdges[ i ] = edge.slice( 0 ); - newEdges[ i ][2] = partition1; - } - } - - // Move all nodes from partition2 to partition1 - for( var i = 0; i < nodeMap.length; i++ ){ - if( nodeMap[ i ] === partition2 ){ - nodeMap[ i ] = partition1; - } - } - - return newEdges; - }; - - - // Contracts a graph until we reach a certain number of meta nodes - var contractUntil = function( metaNodeMap, - remainingEdges, - size, - sizeLimit ){ - // Stop condition - if( size <= sizeLimit ){ - return remainingEdges; - } - - // Choose an edge randomly - var edgeIndex = Math.floor( (Math.random() * remainingEdges.length) ); - - // Colapse graph based on edge - var newEdges = colapse( edgeIndex, metaNodeMap, remainingEdges ); - - return contractUntil( metaNodeMap, - newEdges, - size - 1, - sizeLimit ); - }; - - var cy = this._private.cy; - var edges = this.edges().stdFilter( function( e ){ return !e.isLoop(); } ); - var nodes = this.nodes(); - var numNodes = nodes.length; - var numEdges = edges.length; - var numIter = Math.ceil( Math.pow( Math.log( numNodes ) / Math.LN2, 2 ) ); - var stopSize = Math.floor( numNodes / Math.sqrt( 2 ) ); - - if( numNodes < 2 ){ - util.error( 'At least 2 nodes are required for Karger-Stein algorithm' ); - return undefined; - } - - // Create numerical identifiers for each node - // mapping: node id -> position in nodes array - // for reverse mapping, simply use nodes array - var id2position = {}; - for( var i = 0; i < numNodes; i++ ){ - id2position[ nodes[ i ].id() ] = i; - } - - // Now store edge destination as indexes - // Format for each edge (edge index, source node index, target node index) - var edgeIndexes = []; - for( var i = 0; i < numEdges; i++ ){ - var e = edges[ i ]; - edgeIndexes.push( [ i, id2position[ e.source().id() ], id2position[ e.target().id() ] ] ); - } - - // We will store the best cut found here - var minCutSize = Infinity; - var minCut; - - // Initial meta node partition - var originalMetaNode = []; - for( var i = 0; i < numNodes; i++ ){ - originalMetaNode.push( i ); - } - - // Main loop - for( var iter = 0; iter <= numIter; iter++ ){ - // Create new meta node partition - var metaNodeMap = originalMetaNode.slice( 0 ); - - // Contract until stop point (stopSize nodes) - var edgesState = contractUntil( metaNodeMap, edgeIndexes, numNodes, stopSize ); - - // Create a copy of the colapsed nodes state - var metaNodeMap2 = metaNodeMap.slice( 0 ); - - // Run 2 iterations starting in the stop state - var res1 = contractUntil( metaNodeMap, edgesState, stopSize, 2 ); - var res2 = contractUntil( metaNodeMap2, edgesState, stopSize, 2 ); - - // Is any of the 2 results the best cut so far? - if( res1.length <= res2.length && res1.length < minCutSize ){ - minCutSize = res1.length; - minCut = [ res1, metaNodeMap ]; - } else if( res2.length <= res1.length && res2.length < minCutSize ){ - minCutSize = res2.length; - minCut = [ res2, metaNodeMap2 ]; - } - } // end of main loop - - - // Construct result - var resEdges = (minCut[0]).map( function( e ){ return edges[ e[0] ]; } ); - var partition1 = []; - var partition2 = []; - - // traverse metaNodeMap for best cut - var witnessNodePartition = minCut[1][0]; - for( var i = 0; i < minCut[1].length; i++ ){ - var partitionId = minCut[1][ i ]; - if( partitionId === witnessNodePartition ){ - partition1.push( nodes[ i ] ); - } else { - partition2.push( nodes[ i ] ); - } - } - - var ret = { - cut: eles.spawn( cy, resEdges ), - partition1: eles.spawn( partition1 ), - partition2: eles.spawn( partition2 ) - }; - - return ret; - } -}); // elesfn - - -module.exports = elesfn; - -},{"../../util":100}],13:[function(_dereq_,module,exports){ -'use strict'; - -var is = _dereq_( '../../is' ); - -// search, spanning trees, etc -var elesfn = ({ - - // kruskal's algorithm (finds min spanning tree, assuming undirected graph) - // implemented from pseudocode from wikipedia - kruskal: function( weightFn ){ - var cy = this.cy(); - - weightFn = is.fn( weightFn ) ? weightFn : function(){ return 1; }; // if not specified, assume each edge has equal weight (1) - - function findSet( ele ){ - for( var i = 0; i < forest.length; i++ ){ - var eles = forest[ i ]; - - if( eles.anySame( ele ) ){ - return { - eles: eles, - index: i - }; - } - } - } - - var A = cy.collection( cy, [] ); - var forest = []; - var nodes = this.nodes(); - - for( var i = 0; i < nodes.length; i++ ){ - forest.push( nodes[ i ].collection() ); - } - - var edges = this.edges(); - var S = edges.toArray().sort( function( a, b ){ - var weightA = weightFn.call( a, a ); - var weightB = weightFn.call( b, b ); - - return weightA - weightB; - } ); - - for( var i = 0; i < S.length; i++ ){ - var edge = S[ i ]; - var u = edge.source()[0]; - var v = edge.target()[0]; - var setU = findSet( u ); - var setV = findSet( v ); - - if( setU.index !== setV.index ){ - A = A.add( edge ); - - // combine forests for u and v - forest[ setU.index ] = setU.eles.add( setV.eles ); - forest.splice( setV.index, 1 ); - } - } - - return nodes.add( A ); - } -}); - -module.exports = elesfn; - -},{"../../is":83}],14:[function(_dereq_,module,exports){ -'use strict'; - -var is = _dereq_( '../../is' ); - -var elesfn = ({ - - pageRank: function( options ){ - options = options || {}; - - var normalizeVector = function( vector ){ - var length = vector.length; - - // First, get sum of all elements - var total = 0; - for( var i = 0; i < length; i++ ){ - total += vector[ i ]; - } - - // Now, divide each by the sum of all elements - for( var i = 0; i < length; i++ ){ - vector[ i ] = vector[ i ] / total; - } - }; - - // dampingFactor - optional - if( options != null && - options.dampingFactor != null ){ - var dampingFactor = options.dampingFactor; - } else { - var dampingFactor = 0.8; // Default damping factor - } - - // desired precision - optional - if( options != null && - options.precision != null ){ - var epsilon = options.precision; - } else { - var epsilon = 0.000001; // Default precision - } - - // Max number of iterations - optional - if( options != null && - options.iterations != null ){ - var numIter = options.iterations; - } else { - var numIter = 200; // Default number of iterations - } - - // Weight function - optional - if( options != null && - options.weight != null && - is.fn( options.weight ) ){ - var weightFn = options.weight; - } else { - // If not specified, assume each edge has equal weight (1) - var weightFn = function( e ){return 1;}; - } - - var cy = this._private.cy; - var edges = this.edges().stdFilter( function( e ){ return !e.isLoop(); } ); - var nodes = this.nodes(); - var numNodes = nodes.length; - var numEdges = edges.length; - - // Create numerical identifiers for each node - // mapping: node id -> position in nodes array - // for reverse mapping, simply use nodes array - var id2position = {}; - for( var i = 0; i < numNodes; i++ ){ - id2position[ nodes[ i ].id() ] = i; - } - - // Construct transposed adjacency matrix - // First lets have a zeroed matrix of the right size - // We'll also keep track of the sum of each column - var matrix = []; - var columnSum = []; - var additionalProb = (1 - dampingFactor) / numNodes; - - // Create null matric - for( var i = 0; i < numNodes; i++ ){ - var newRow = []; - for( var j = 0; j < numNodes; j++ ){ - newRow.push( 0.0 ); - } - matrix.push( newRow ); - columnSum.push( 0.0 ); - } - - // Now, process edges - for( var i = 0; i < numEdges; i++ ){ - var edge = edges[ i ]; - var s = id2position[ edge.source().id() ]; - var t = id2position[ edge.target().id() ]; - var w = weightFn.apply( edge, [ edge ] ); - - // Update matrix - matrix[ t ][ s ] += w; - - // Update column sum - columnSum[ s ] += w; - } - - // Add additional probability based on damping factor - // Also, take into account columns that have sum = 0 - var p = 1.0 / numNodes + additionalProb; // Shorthand - // Traverse matrix, column by column - for( var j = 0; j < numNodes; j++ ){ - if( columnSum[ j ] === 0 ){ - // No 'links' out from node jth, assume equal probability for each possible node - for( var i = 0; i < numNodes; i++ ){ - matrix[ i ][ j ] = p; - } - } else { - // Node jth has outgoing link, compute normalized probabilities - for( var i = 0; i < numNodes; i++ ){ - matrix[ i ][ j ] = matrix[ i ][ j ] / columnSum[ j ] + additionalProb; - } - } - } - - // Compute dominant eigenvector using power method - var eigenvector = []; - var nullVector = []; - var previous; - - // Start with a vector of all 1's - // Also, initialize a null vector which will be used as shorthand - for( var i = 0; i < numNodes; i++ ){ - eigenvector.push( 1.0 ); - nullVector.push( 0.0 ); - } - - for( var iter = 0; iter < numIter; iter++ ){ - // New array with all 0's - var temp = nullVector.slice( 0 ); - - // Multiply matrix with previous result - for( var i = 0; i < numNodes; i++ ){ - for( var j = 0; j < numNodes; j++ ){ - temp[ i ] += matrix[ i ][ j ] * eigenvector[ j ]; - } - } - - normalizeVector( temp ); - previous = eigenvector; - eigenvector = temp; - - var diff = 0; - // Compute difference (squared module) of both vectors - for( var i = 0; i < numNodes; i++ ){ - diff += Math.pow( previous[ i ] - eigenvector[ i ], 2 ); - } - - // If difference is less than the desired threshold, stop iterating - if( diff < epsilon ){ - break; - } - } - - // Construct result - var res = { - rank: function( node ){ - if( is.string( node ) ){ - // is a selector string - var nodeId = (cy.filter( node )[0]).id(); - } else { - // is a node object - var nodeId = node.id(); - } - return eigenvector[ id2position[ nodeId ] ]; - } - }; - - - return res; - } // pageRank - -}); // elesfn - -module.exports = elesfn; - -},{"../../is":83}],15:[function(_dereq_,module,exports){ -'use strict'; - -var define = _dereq_( '../define' ); - -var elesfn = ({ +var elesfn = { animate: define.animate(), animation: define.animation(), animated: define.animated(), @@ -2101,176 +7728,955 @@ var elesfn = ({ delay: define.delay(), delayAnimation: define.delayAnimation(), stop: define.stop() -}); +}; module.exports = elesfn; -},{"../define":44}],16:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 44 */ +/***/ (function(module, exports, __webpack_require__) { -var util = _dereq_( '../util' ); +"use strict"; -var elesfn = ({ - classes: function( classes ){ - classes = classes.match( /\S+/g ) || []; - var self = this; - var changed = []; - var classesMap = {}; - // fill in classes map - for( var i = 0; i < classes.length; i++ ){ - var cls = classes[ i ]; +var util = __webpack_require__(1); +var Animation = __webpack_require__(45); +var math = __webpack_require__(2); +var is = __webpack_require__(0); - classesMap[ cls ] = true; +var define = { + + animated: function animated() { + return function animatedImpl() { + var self = this; + var selfIsArrayLike = self.length !== undefined; + var all = selfIsArrayLike ? self : [self]; // put in array if not array-like + var cy = this._private.cy || this; + + if (!cy.styleEnabled()) { + return false; + } + + var ele = all[0]; + + if (ele) { + return ele._private.animation.current.length > 0; + } + }; + }, // animated + + clearQueue: function clearQueue() { + return function clearQueueImpl() { + var self = this; + var selfIsArrayLike = self.length !== undefined; + var all = selfIsArrayLike ? self : [self]; // put in array if not array-like + var cy = this._private.cy || this; + + if (!cy.styleEnabled()) { + return this; + } + + for (var i = 0; i < all.length; i++) { + var ele = all[i]; + ele._private.animation.queue = []; + } + + return this; + }; + }, // clearQueue + + delay: function delay() { + return function delayImpl(time, complete) { + var cy = this._private.cy || this; + + if (!cy.styleEnabled()) { + return this; + } + + return this.animate({ + delay: time, + duration: time, + complete: complete + }); + }; + }, // delay + + delayAnimation: function delayAnimation() { + return function delayAnimationImpl(time, complete) { + var cy = this._private.cy || this; + + if (!cy.styleEnabled()) { + return this; + } + + return this.animation({ + delay: time, + duration: time, + complete: complete + }); + }; + }, // delay + + animation: function animation() { + return function animationImpl(properties, params) { + var self = this; + var selfIsArrayLike = self.length !== undefined; + var all = selfIsArrayLike ? self : [self]; // put in array if not array-like + var cy = this._private.cy || this; + var isCore = !selfIsArrayLike; + var isEles = !isCore; + + if (!cy.styleEnabled()) { + return this; + } + + var style = cy.style(); + + properties = util.assign({}, properties, params); + + var propertiesEmpty = Object.keys(properties).length === 0; + + if (propertiesEmpty) { + return new Animation(all[0], properties); // nothing to animate + } + + if (properties.duration === undefined) { + properties.duration = 400; + } + + switch (properties.duration) { + case 'slow': + properties.duration = 600; + break; + case 'fast': + properties.duration = 200; + break; + } + + if (isEles) { + properties.style = style.getPropsList(properties.style || properties.css); + + properties.css = undefined; + } + + if (isEles && properties.renderedPosition != null) { + var rpos = properties.renderedPosition; + var pan = cy.pan(); + var zoom = cy.zoom(); + + properties.position = math.renderedToModelPosition(rpos, zoom, pan); + } + + // override pan w/ panBy if set + if (isCore && properties.panBy != null) { + var panBy = properties.panBy; + var cyPan = cy.pan(); + + properties.pan = { + x: cyPan.x + panBy.x, + y: cyPan.y + panBy.y + }; + } + + // override pan w/ center if set + var center = properties.center || properties.centre; + if (isCore && center != null) { + var centerPan = cy.getCenterPan(center.eles, properties.zoom); + + if (centerPan != null) { + properties.pan = centerPan; + } + } + + // override pan & zoom w/ fit if set + if (isCore && properties.fit != null) { + var fit = properties.fit; + var fitVp = cy.getFitViewport(fit.eles || fit.boundingBox, fit.padding); + + if (fitVp != null) { + properties.pan = fitVp.pan; + properties.zoom = fitVp.zoom; + } + } + + // override zoom (& potentially pan) w/ zoom obj if set + if (isCore && is.plainObject(properties.zoom)) { + var vp = cy.getZoomedViewport(properties.zoom); + + if (vp != null) { + if (vp.zoomed) { + properties.zoom = vp.zoom; + } + + if (vp.panned) { + properties.pan = vp.pan; + } + } + } + + return new Animation(all[0], properties); + }; + }, // animate + + animate: function animate() { + return function animateImpl(properties, params) { + var self = this; + var selfIsArrayLike = self.length !== undefined; + var all = selfIsArrayLike ? self : [self]; // put in array if not array-like + var cy = this._private.cy || this; + + if (!cy.styleEnabled()) { + return this; + } + + if (params) { + properties = util.extend({}, properties, params); + } + + // manually hook and run the animation + for (var i = 0; i < all.length; i++) { + var ele = all[i]; + var queue = ele.animated() && (properties.queue === undefined || properties.queue); + + var ani = ele.animation(properties, queue ? { queue: true } : undefined); + + ani.play(); + } + + return this; // chaining + }; + }, // animate + + stop: function stop() { + return function stopImpl(clearQueue, jumpToEnd) { + var self = this; + var selfIsArrayLike = self.length !== undefined; + var all = selfIsArrayLike ? self : [self]; // put in array if not array-like + var cy = this._private.cy || this; + + if (!cy.styleEnabled()) { + return this; + } + + for (var i = 0; i < all.length; i++) { + var ele = all[i]; + var _p = ele._private; + var anis = _p.animation.current; + + for (var j = 0; j < anis.length; j++) { + var ani = anis[j]; + var ani_p = ani._private; + + if (jumpToEnd) { + // next iteration of the animation loop, the animation + // will go straight to the end and be removed + ani_p.duration = 0; + } + } + + // clear the queue of future animations + if (clearQueue) { + _p.animation.queue = []; + } + + if (!jumpToEnd) { + _p.animation.current = []; + } + } + + // we have to notify (the animation loop doesn't do it for us on `stop`) + cy.notify({ + eles: this, + type: 'draw' + }); + + return this; + }; + } // stop + +}; // define + +module.exports = define; + +/***/ }), +/* 45 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var util = __webpack_require__(1); +var is = __webpack_require__(0); +var Promise = __webpack_require__(5); + +var Animation = function Animation(target, opts, opts2) { + var _p = this._private = util.extend({ + duration: 1000 + }, opts, opts2); + + _p.target = target; + _p.style = _p.style || _p.css; + _p.started = false; + _p.playing = false; + _p.hooked = false; + _p.applying = false; + _p.progress = 0; + _p.completes = []; + _p.frames = []; + + if (_p.complete && is.fn(_p.complete)) { + _p.completes.push(_p.complete); + } + + // for future timeline/animations impl + this.length = 1; + this[0] = this; +}; + +var anifn = Animation.prototype; + +util.extend(anifn, { + + instanceString: function instanceString() { + return 'animation'; + }, + + hook: function hook() { + var _p = this._private; + + if (!_p.hooked) { + // add to target's animation queue + var q = void 0; + var tAni = _p.target._private.animation; + if (_p.queue) { + q = tAni.queue; + } else { + q = tAni.current; + } + q.push(this); + + // add to the animation loop pool + if (is.elementOrCollection(_p.target)) { + _p.target.cy().addToAnimationPool(_p.target); + } + + _p.hooked = true; } + return this; + }, + + play: function play() { + var _p = this._private; + + // autorewind + if (_p.progress === 1) { + _p.progress = 0; + } + + _p.playing = true; + _p.started = false; // needs to be started by animation loop + _p.stopped = false; + + this.hook(); + + // the animation loop will start the animation... + + return this; + }, + + playing: function playing() { + return this._private.playing; + }, + + apply: function apply() { + var _p = this._private; + + _p.applying = true; + _p.started = false; // needs to be started by animation loop + _p.stopped = false; + + this.hook(); + + // the animation loop will apply the animation at this progress + + return this; + }, + + applying: function applying() { + return this._private.applying; + }, + + pause: function pause() { + var _p = this._private; + + _p.playing = false; + _p.started = false; + + return this; + }, + + stop: function stop() { + var _p = this._private; + + _p.playing = false; + _p.started = false; + _p.stopped = true; // to be removed from animation queues + + return this; + }, + + rewind: function rewind() { + return this.progress(0); + }, + + fastforward: function fastforward() { + return this.progress(1); + }, + + time: function time(t) { + var _p = this._private; + + if (t === undefined) { + return _p.progress * _p.duration; + } else { + return this.progress(t / _p.duration); + } + }, + + progress: function progress(p) { + var _p = this._private; + var wasPlaying = _p.playing; + + if (p === undefined) { + return _p.progress; + } else { + if (wasPlaying) { + this.pause(); + } + + _p.progress = p; + _p.started = false; + + if (wasPlaying) { + this.play(); + } + } + + return this; + }, + + completed: function completed() { + return this._private.progress === 1; + }, + + reverse: function reverse() { + var _p = this._private; + var wasPlaying = _p.playing; + + if (wasPlaying) { + this.pause(); + } + + _p.progress = 1 - _p.progress; + _p.started = false; + + var swap = function swap(a, b) { + var _pa = _p[a]; + + if (_pa == null) { + return; + } + + _p[a] = _p[b]; + _p[b] = _pa; + }; + + swap('zoom', 'startZoom'); + swap('pan', 'startPan'); + swap('position', 'startPosition'); + + // swap styles + if (_p.style) { + for (var i = 0; i < _p.style.length; i++) { + var prop = _p.style[i]; + var name = prop.name; + var startStyleProp = _p.startStyle[name]; + + _p.startStyle[name] = prop; + _p.style[i] = startStyleProp; + } + } + + if (wasPlaying) { + this.play(); + } + + return this; + }, + + promise: function promise(type) { + var _p = this._private; + + var arr = void 0; + + switch (type) { + case 'frame': + arr = _p.frames; + break; + default: + case 'complete': + case 'completed': + arr = _p.completes; + } + + return new Promise(function (resolve, reject) { + arr.push(function () { + resolve(); + }); + }); + } + +}); + +anifn.complete = anifn.completed; + +module.exports = Animation; + +/***/ }), +/* 46 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +var util = __webpack_require__(1); +var is = __webpack_require__(0); + +var define = { + + // access data field + data: function data(params) { + var defaults = { + field: 'data', + bindingEvent: 'data', + allowBinding: false, + allowSetting: false, + allowGetting: false, + settingEvent: 'data', + settingTriggersEvent: false, + triggerFnName: 'trigger', + immutableKeys: {}, // key => true if immutable + updateStyle: false, + beforeGet: function beforeGet(self) {}, + beforeSet: function beforeSet(self, obj) {}, + onSet: function onSet(self) {}, + canSet: function canSet(self) { + return true; + } + }; + params = util.extend({}, defaults, params); + + return function dataImpl(name, value) { + var p = params; + var self = this; + var selfIsArrayLike = self.length !== undefined; + var all = selfIsArrayLike ? self : [self]; // put in array if not array-like + var single = selfIsArrayLike ? self[0] : self; + + // .data('foo', ...) + if (is.string(name)) { + // set or get property + + // .data('foo') + if (p.allowGetting && value === undefined) { + // get + + var ret = void 0; + if (single) { + p.beforeGet(single); + + ret = single._private[p.field][name]; + } + return ret; + + // .data('foo', 'bar') + } else if (p.allowSetting && value !== undefined) { + // set + var valid = !p.immutableKeys[name]; + if (valid) { + var change = _defineProperty({}, name, value); + + p.beforeSet(self, change); + + for (var i = 0, l = all.length; i < l; i++) { + var ele = all[i]; + + if (p.canSet(ele)) { + ele._private[p.field][name] = value; + } + } + + // update mappers if asked + if (p.updateStyle) { + self.updateStyle(); + } + + // call onSet callback + p.onSet(self); + + if (p.settingTriggersEvent) { + self[p.triggerFnName](p.settingEvent); + } + } + } + + // .data({ 'foo': 'bar' }) + } else if (p.allowSetting && is.plainObject(name)) { + // extend + var obj = name; + var k = void 0, + v = void 0; + var keys = Object.keys(obj); + + p.beforeSet(self, obj); + + for (var _i = 0; _i < keys.length; _i++) { + k = keys[_i]; + v = obj[k]; + + var _valid = !p.immutableKeys[k]; + if (_valid) { + for (var j = 0; j < all.length; j++) { + var _ele = all[j]; + + if (p.canSet(_ele)) { + _ele._private[p.field][k] = v; + } + } + } + } + + // update mappers if asked + if (p.updateStyle) { + self.updateStyle(); + } + + // call onSet callback + p.onSet(self); + + if (p.settingTriggersEvent) { + self[p.triggerFnName](p.settingEvent); + } + + // .data(function(){ ... }) + } else if (p.allowBinding && is.fn(name)) { + // bind to event + var fn = name; + self.on(p.bindingEvent, fn); + + // .data() + } else if (p.allowGetting && name === undefined) { + // get whole object + var _ret = void 0; + if (single) { + p.beforeGet(single); + + _ret = single._private[p.field]; + } + return _ret; + } + + return self; // maintain chainability + }; // function + }, // data + + // remove data field + removeData: function removeData(params) { + var defaults = { + field: 'data', + event: 'data', + triggerFnName: 'trigger', + triggerEvent: false, + immutableKeys: {} // key => true if immutable + }; + params = util.extend({}, defaults, params); + + return function removeDataImpl(names) { + var p = params; + var self = this; + var selfIsArrayLike = self.length !== undefined; + var all = selfIsArrayLike ? self : [self]; // put in array if not array-like + + // .removeData('foo bar') + if (is.string(names)) { + // then get the list of keys, and delete them + var keys = names.split(/\s+/); + var l = keys.length; + + for (var i = 0; i < l; i++) { + // delete each non-empty key + var key = keys[i]; + if (is.emptyString(key)) { + continue; + } + + var valid = !p.immutableKeys[key]; // not valid if immutable + if (valid) { + for (var i_a = 0, l_a = all.length; i_a < l_a; i_a++) { + all[i_a]._private[p.field][key] = undefined; + } + } + } + + if (p.triggerEvent) { + self[p.triggerFnName](p.event); + } + + // .removeData() + } else if (names === undefined) { + // then delete all keys + + for (var _i_a = 0, _l_a = all.length; _i_a < _l_a; _i_a++) { + var _privateFields = all[_i_a]._private[p.field]; + var _keys = Object.keys(_privateFields); + + for (var _i2 = 0; _i2 < _keys.length; _i2++) { + var _key = _keys[_i2]; + var validKeyToDelete = !p.immutableKeys[_key]; + + if (validKeyToDelete) { + _privateFields[_key] = undefined; + } + } + } + + if (p.triggerEvent) { + self[p.triggerFnName](p.event); + } + } + + return self; // maintain chaining + }; // function + } // removeData +}; // define + +module.exports = define; + +/***/ }), +/* 47 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var Promise = __webpack_require__(5); + +var define = { + + eventAliasesOn: function eventAliasesOn(proto) { + var p = proto; + + p.addListener = p.listen = p.bind = p.on; + p.unlisten = p.unbind = p.off = p.removeListener; + p.trigger = p.emit; + + // this is just a wrapper alias of .on() + p.pon = p.promiseOn = function (events, selector) { + var self = this; + var args = Array.prototype.slice.call(arguments, 0); + + return new Promise(function (resolve, reject) { + var callback = function callback(e) { + self.off.apply(self, offArgs); + + resolve(e); + }; + + var onArgs = args.concat([callback]); + var offArgs = onArgs.concat([]); + + self.on.apply(self, onArgs); + }); + }; + } + +}; // define + +module.exports = define; + +/***/ }), +/* 48 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var Set = __webpack_require__(8); + +var elesfn = { + classes: function classes(_classes) { + _classes = (_classes || '').match(/\S+/g) || []; + var self = this; + var changed = []; + var classesMap = new Set(_classes); + // check and update each ele - for( var j = 0; j < self.length; j++ ){ - var ele = self[ j ]; + + var _loop = function _loop(j) { + var ele = self[j]; var _p = ele._private; var eleClasses = _p.classes; var changedEle = false; // check if ele has all of the passed classes - for( var i = 0; i < classes.length; i++ ){ - var cls = classes[ i ]; - var eleHasClass = eleClasses[ cls ]; + classesMap.forEach(function (cls) { + var eleHasClass = eleClasses.has(cls); - if( !eleHasClass ){ + if (!eleHasClass) { changedEle = true; - break; } - } + }); // check if ele has classes outside of those passed - if( !changedEle ){ - var classes = Object.keys( eleClasses ); + if (!changedEle) { + eleClasses.forEach(function (eleCls) { + var specdClass = classesMap.has(eleCls); - for( var i = 0; i < classes.length; i++ ){ - var eleCls = classes[i]; - var eleHasClass = eleClasses[ eleCls ]; - var specdClass = classesMap[ eleCls ]; // i.e. this class is passed to the function - - if( eleHasClass && !specdClass ){ + if (!specdClass) { changedEle = true; - break; } - } + }); } - if( changedEle ){ - _p.classes = util.copy( classesMap ); + if (changedEle) { + _p.classes = new Set(classesMap); - changed.push( ele ); + changed.push(ele); } + }; + + for (var j = 0; j < self.length; j++) { + _loop(j); } // trigger update style on those eles that had class changes - if( changed.length > 0 ){ - this.spawn( changed ) - .updateStyle() - .trigger( 'class' ) - ; + if (changed.length > 0) { + this.spawn(changed).updateStyle().emit('class'); } return self; }, - addClass: function( classes ){ - return this.toggleClass( classes, true ); + addClass: function addClass(classes) { + return this.toggleClass(classes, true); }, - hasClass: function( className ){ + hasClass: function hasClass(className) { var ele = this[0]; - return ( ele != null && ele._private.classes[ className ] ) ? true : false; + return ele != null && ele._private.classes.has(className); }, - toggleClass: function( classesStr, toggle ){ - var classes = classesStr.match( /\S+/g ) || []; + toggleClass: function toggleClass(classesStr, toggle) { + var classes = classesStr.match(/\S+/g) || []; var self = this; var changed = []; // eles who had classes changed - for( var i = 0, il = self.length; i < il; i++ ){ - var ele = self[ i ]; - var changedEle = false; + for (var i = 0, il = self.length; i < il; i++) { + var _ele = self[i]; + var _changedEle = false; - for( var j = 0; j < classes.length; j++ ){ - var cls = classes[ j ]; - var eleClasses = ele._private.classes; - var hasClass = eleClasses[ cls ]; - var shouldAdd = toggle || (toggle === undefined && !hasClass); + for (var j = 0; j < classes.length; j++) { + var cls = classes[j]; + var _eleClasses = _ele._private.classes; + var hasClass = _eleClasses.has(cls); + var shouldAdd = toggle || toggle === undefined && !hasClass; - if( shouldAdd ){ - eleClasses[ cls ] = true; + if (shouldAdd) { + _eleClasses.add(cls); - if( !hasClass && !changedEle ){ - changed.push( ele ); - changedEle = true; + if (!hasClass && !_changedEle) { + changed.push(_ele); + _changedEle = true; } - } else { // then remove - eleClasses[ cls ] = false; + } else { + // then remove + _eleClasses.delete(cls); - if( hasClass && !changedEle ){ - changed.push( ele ); - changedEle = true; + if (hasClass && !_changedEle) { + changed.push(_ele); + _changedEle = true; } } - } // for j classes } // for i eles // trigger update style on those eles that had class changes - if( changed.length > 0 ){ - this.spawn( changed ) - .updateStyle() - .trigger( 'class' ) - ; + if (changed.length > 0) { + this.spawn(changed).updateStyle().emit('class'); } return self; }, - removeClass: function( classes ){ - return this.toggleClass( classes, false ); + removeClass: function removeClass(classes) { + return this.toggleClass(classes, false); }, - flashClass: function( classes, duration ){ + flashClass: function flashClass(classes, duration) { var self = this; - if( duration == null ){ + if (duration == null) { duration = 250; - } else if( duration === 0 ){ + } else if (duration === 0) { return self; // nothing to do really } - self.addClass( classes ); - setTimeout( function(){ - self.removeClass( classes ); - }, duration ); + self.addClass(classes); + setTimeout(function () { + self.removeClass(classes); + }, duration); return self; } -}); +}; module.exports = elesfn; -},{"../util":100}],17:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 49 */ +/***/ (function(module, exports, __webpack_require__) { -var elesfn = ({ - allAre: function( selector ){ - return this.filter( selector ).length === this.length; +"use strict"; + + +var is = __webpack_require__(0); +var Selector = __webpack_require__(6); + +var elesfn = { + allAre: function allAre(selector) { + var selObj = new Selector(selector); + + return this.every(function (ele) { + return selObj.matches(ele); + }); }, - is: function( selector ){ - return this.filter( selector ).length > 0; + is: function is(selector) { + var selObj = new Selector(selector); + + return this.some(function (ele) { + return selObj.matches(ele); + }); }, - some: function( fn, thisArg ){ - for( var i = 0; i < this.length; i++ ){ - var ret = !thisArg ? fn( this[ i ], i, this ) : fn.apply( thisArg, [ this[ i ], i, this ] ); + some: function some(fn, thisArg) { + for (var i = 0; i < this.length; i++) { + var ret = !thisArg ? fn(this[i], i, this) : fn.apply(thisArg, [this[i], i, this]); - if( ret ){ + if (ret) { return true; } } @@ -2278,11 +8684,11 @@ var elesfn = ({ return false; }, - every: function( fn, thisArg ){ - for( var i = 0; i < this.length; i++ ){ - var ret = !thisArg ? fn( this[ i ], i, this ) : fn.apply( thisArg, [ this[ i ], i, this ] ); + every: function every(fn, thisArg) { + for (var i = 0; i < this.length; i++) { + var ret = !thisArg ? fn(this[i], i, this) : fn.apply(thisArg, [this[i], i, this]); - if( !ret ){ + if (!ret) { return false; } } @@ -2290,163 +8696,1083 @@ var elesfn = ({ return true; }, - same: function( collection ){ - collection = this.cy().collection( collection ); + same: function same(collection) { + collection = this.cy().collection(collection); // cheap extra check - if( this.length !== collection.length ){ + if (this.length !== collection.length) { return false; } - return this.intersect( collection ).length === this.length; + return this.every(function (ele) { + return collection.hasElementWithId(ele.id()); + }); }, - anySame: function( collection ){ - collection = this.cy().collection( collection ); + anySame: function anySame(collection) { + collection = this.cy().collection(collection); - return this.intersect( collection ).length > 0; + return this.some(function (ele) { + return collection.hasElementWithId(ele.id()); + }); }, - allAreNeighbors: function( collection ){ - collection = this.cy().collection( collection ); + allAreNeighbors: function allAreNeighbors(collection) { + collection = this.cy().collection(collection); - return this.neighborhood().intersect( collection ).length === collection.length; + var nhood = this.neighborhood(); + + return collection.every(function (ele) { + return nhood.hasElementWithId(ele.id()); + }); + }, + + contains: function contains(collection) { + collection = this.cy().collection(collection); + + var self = this; + + return collection.every(function (ele) { + return self.hasElementWithId(ele.id()); + }); } -}); +}; elesfn.allAreNeighbours = elesfn.allAreNeighbors; +elesfn.has = elesfn.contains; module.exports = elesfn; -},{}],18:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 50 */ +/***/ (function(module, exports, __webpack_require__) { -var elesfn = ({ - parent: function( selector ){ - var parents = []; - var cy = this._private.cy; +"use strict"; - for( var i = 0; i < this.length; i++ ){ - var ele = this[ i ]; - var parent = cy.getElementById( ele._private.data.parent ); - if( parent.size() > 0 ){ - parents.push( parent ); +var util = __webpack_require__(1); +var exprs = __webpack_require__(51); +var newQuery = __webpack_require__(10); + +// of all the expressions, find the first match in the remaining text +var consumeExpr = function consumeExpr(remaining) { + var expr = void 0; + var match = void 0; + var name = void 0; + + for (var j = 0; j < exprs.length; j++) { + var e = exprs[j]; + var n = e.name; + + var m = remaining.match(e.regexObj); + + if (m != null) { + match = m; + expr = e; + name = n; + + var consumed = m[0]; + remaining = remaining.substring(consumed.length); + + break; // we've consumed one expr, so we can return now + } + } + + return { + expr: expr, + match: match, + name: name, + remaining: remaining + }; +}; + +// consume all leading whitespace +var consumeWhitespace = function consumeWhitespace(remaining) { + var match = remaining.match(/^\s+/); + + if (match) { + var consumed = match[0]; + remaining = remaining.substring(consumed.length); + } + + return remaining; +}; + +var parse = function parse(selector) { + var self = this; + + var remaining = self._private.selectorText = selector; + + var currentQuery = self[0] = newQuery(); + self.length = 1; + + remaining = consumeWhitespace(remaining); // get rid of leading whitespace + + for (;;) { + var check = consumeExpr(remaining); + + if (check.expr == null) { + util.error('The selector `' + selector + '`is invalid'); + return false; + } else { + var args = check.match.slice(1); + + // let the token populate the selector object in currentQuery + var ret = check.expr.populate(self, currentQuery, args); + + if (ret === false) { + return false; // exit if population failed + } else if (ret != null) { + currentQuery = ret; // change the current query to be filled if the expr specifies } } - return this.spawn( parents, { unique: true } ).filter( selector ); + remaining = check.remaining; + + // we're done when there's nothing left to parse + if (remaining.match(/^\s*$/)) { + break; + } + } + + // adjust references for subject + for (var j = 0; j < self.length; j++) { + var query = self[j]; + + if (query.subject != null) { + // go up the tree until we reach the subject + for (;;) { + if (query.subject === query) { + break; + } // done if subject is self + + if (query.parent != null) { + // swap parent/child reference + var parent = query.parent; + var child = query; + + child.parent = null; + parent.child = child; + + query = parent; // go up the tree + } else if (query.ancestor != null) { + // swap ancestor/descendant + var ancestor = query.ancestor; + var descendant = query; + + descendant.ancestor = null; + ancestor.descendant = descendant; + + query = ancestor; // go up the tree + } else if (query.source || query.target || query.connectedNodes) { + util.error('The selector `' + self.text() + '` can not contain a subject selector that applies to the source or target of an edge selector'); + return false; + } else { + util.error('When adjusting references for the selector `' + self.text() + '`, neither parent nor ancestor was found'); + return false; + } + } // for + + self[j] = query.subject; // subject should be the root query + } // if + } // for + + return true; // success +}; + +module.exports = { parse: parse }; + +/***/ }), +/* 51 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + +var _require = __webpack_require__(15), + stateSelectorRegex = _require.stateSelectorRegex; + +var tokens = __webpack_require__(52); +var util = __webpack_require__(1); +var newQuery = __webpack_require__(10); + +// when a token like a variable has escaped meta characters, we need to clean the backslashes out +// so that values get compared properly in Selector.filter() +var cleanMetaChars = function cleanMetaChars(str) { + return str.replace(new RegExp('\\\\(' + tokens.metaChar + ')', 'g'), function (match, $1) { + return $1; + }); +}; + +var replaceLastQuery = function replaceLastQuery(selector, examiningQuery, replacementQuery) { + if (examiningQuery === selector[selector.length - 1]) { + selector[selector.length - 1] = replacementQuery; + } +}; + +// NOTE: add new expression syntax here to have it recognised by the parser; +// - a query contains all adjacent (i.e. no separator in between) expressions; +// - the current query is stored in selector[i] --- you can use the reference to `this` in the populate function; +// - you need to check the query objects in Selector.filter() for it actually filter properly, but that's pretty straight forward +// - when you add something here, also add to Selector.toString() +var exprs = [{ + name: 'group', + query: true, + regex: '(' + tokens.group + ')', + populate: function populate(selector, query, _ref) { + var _ref2 = _slicedToArray(_ref, 1), + group = _ref2[0]; + + query.group = group === '*' ? group : group + 's'; + } +}, { + name: 'state', + query: true, + regex: stateSelectorRegex, + populate: function populate(selector, query, _ref3) { + var _ref4 = _slicedToArray(_ref3, 1), + state = _ref4[0]; + + query.colonSelectors.push(state); + } +}, { + name: 'id', + query: true, + regex: '\\#(' + tokens.id + ')', + populate: function populate(selector, query, _ref5) { + var _ref6 = _slicedToArray(_ref5, 1), + id = _ref6[0]; + + query.ids.push(cleanMetaChars(id)); + } +}, { + name: 'className', + query: true, + regex: '\\.(' + tokens.className + ')', + populate: function populate(selector, query, _ref7) { + var _ref8 = _slicedToArray(_ref7, 1), + className = _ref8[0]; + + query.classes.push(cleanMetaChars(className)); + } +}, { + name: 'dataExists', + query: true, + regex: '\\[\\s*(' + tokens.variable + ')\\s*\\]', + populate: function populate(selector, query, _ref9) { + var _ref10 = _slicedToArray(_ref9, 1), + variable = _ref10[0]; + + query.data.push({ + field: cleanMetaChars(variable) + }); + } +}, { + name: 'dataCompare', + query: true, + regex: '\\[\\s*(' + tokens.variable + ')\\s*(' + tokens.comparatorOp + ')\\s*(' + tokens.value + ')\\s*\\]', + populate: function populate(selector, query, _ref11) { + var _ref12 = _slicedToArray(_ref11, 3), + variable = _ref12[0], + comparatorOp = _ref12[1], + value = _ref12[2]; + + var valueIsString = new RegExp('^' + tokens.string + '$').exec(value) != null; + + if (valueIsString) { + value = value.substring(1, value.length - 1); + } else { + value = parseFloat(value); + } + + query.data.push({ + field: cleanMetaChars(variable), + operator: comparatorOp, + value: value + }); + } +}, { + name: 'dataBool', + query: true, + regex: '\\[\\s*(' + tokens.boolOp + ')\\s*(' + tokens.variable + ')\\s*\\]', + populate: function populate(selector, query, _ref13) { + var _ref14 = _slicedToArray(_ref13, 2), + boolOp = _ref14[0], + variable = _ref14[1]; + + query.data.push({ + field: cleanMetaChars(variable), + operator: boolOp + }); + } +}, { + name: 'metaCompare', + query: true, + regex: '\\[\\[\\s*(' + tokens.meta + ')\\s*(' + tokens.comparatorOp + ')\\s*(' + tokens.number + ')\\s*\\]\\]', + populate: function populate(selector, query, _ref15) { + var _ref16 = _slicedToArray(_ref15, 3), + meta = _ref16[0], + comparatorOp = _ref16[1], + number = _ref16[2]; + + query.meta.push({ + field: cleanMetaChars(meta), + operator: comparatorOp, + value: parseFloat(number) + }); + } +}, { + name: 'nextQuery', + separator: true, + regex: tokens.separator, + populate: function populate(selector) { + // go on to next query + var nextQuery = selector[selector.length++] = newQuery(); + selector.currentSubject = null; + + return nextQuery; + } +}, { + name: 'directedEdge', + separator: true, + regex: tokens.directedEdge, + populate: function populate(selector, query) { + var edgeQuery = newQuery(); + var source = query; + var target = newQuery(); + + edgeQuery.group = 'edges'; + edgeQuery.target = target; + edgeQuery.source = source; + edgeQuery.subject = selector.currentSubject; + + // the query in the selector should be the edge rather than the source + replaceLastQuery(selector, query, edgeQuery); + + // we're now populating the target query with expressions that follow + return target; + } +}, { + name: 'undirectedEdge', + separator: true, + regex: tokens.undirectedEdge, + populate: function populate(selector, query) { + var edgeQuery = newQuery(); + var source = query; + var target = newQuery(); + + edgeQuery.group = 'edges'; + edgeQuery.connectedNodes = [source, target]; + edgeQuery.subject = selector.currentSubject; + + // the query in the selector should be the edge rather than the source + replaceLastQuery(selector, query, edgeQuery); + + // we're now populating the target query with expressions that follow + return target; + } +}, { + name: 'child', + separator: true, + regex: tokens.child, + populate: function populate(selector, query) { + // this query is the parent of the following query + var childQuery = newQuery(); + childQuery.parent = query; + childQuery.subject = selector.currentSubject; + + // it's cheaper to compare children first and go up so replace the parent + replaceLastQuery(selector, query, childQuery); + + // we're now populating the child query with expressions that follow + return childQuery; + } +}, { + name: 'descendant', + separator: true, + regex: tokens.descendant, + populate: function populate(selector, query) { + // this query is the ancestor of the following query + var descendantQuery = newQuery(); + descendantQuery.ancestor = query; + descendantQuery.subject = selector.currentSubject; + + // it's cheaper to compare descendants first and go up so replace the ancestor + replaceLastQuery(selector, query, descendantQuery); + + // we're now populating the descendant query with expressions that follow + return descendantQuery; + } +}, { + name: 'subject', + modifier: true, + regex: tokens.subject, + populate: function populate(selector, query) { + if (selector.currentSubject != null && query.subject != query) { + util.error('Redefinition of subject in selector `' + selector.toString() + '`'); + return false; + } + + selector.currentSubject = query; + query.subject = query; + selector[selector.length - 1].subject = query; + } +}]; + +exprs.forEach(function (e) { + return e.regexObj = new RegExp('^' + e.regex); +}); + +module.exports = exprs; + +/***/ }), +/* 52 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var util = __webpack_require__(1); + +// tokens in the query language +var tokens = { + metaChar: '[\\!\\"\\#\\$\\%\\&\\\'\\(\\)\\*\\+\\,\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\]\\^\\`\\{\\|\\}\\~]', // chars we need to escape in let names, etc + comparatorOp: '=|\\!=|>|>=|<|<=|\\$=|\\^=|\\*=', // binary comparison op (used in data selectors) + boolOp: '\\?|\\!|\\^', // boolean (unary) operators (used in data selectors) + string: '"(?:\\\\"|[^"])*"' + '|' + "'(?:\\\\'|[^'])*'", // string literals (used in data selectors) -- doublequotes | singlequotes + number: util.regex.number, // number literal (used in data selectors) --- e.g. 0.1234, 1234, 12e123 + meta: 'degree|indegree|outdegree', // allowed metadata fields (i.e. allowed functions to use from Collection) + separator: '\\s*,\\s*', // queries are separated by commas, e.g. edge[foo = 'bar'], node.someClass + descendant: '\\s+', + child: '\\s+>\\s+', + subject: '\\$', + group: 'node|edge|\\*', + directedEdge: '\\s+->\\s+', + undirectedEdge: '\\s+<->\\s+' +}; +tokens.variable = '(?:[\\w-]|(?:\\\\' + tokens.metaChar + '))+'; // a variable name +tokens.value = tokens.string + '|' + tokens.number; // a value literal, either a string or number +tokens.className = tokens.variable; // a class name (follows variable conventions) +tokens.id = tokens.variable; // an element id (follows variable conventions) + +(function () { + var ops = void 0, + op = void 0, + i = void 0; + + // add @ variants to comparatorOp + ops = tokens.comparatorOp.split('|'); + for (i = 0; i < ops.length; i++) { + op = ops[i]; + tokens.comparatorOp += '|@' + op; + } + + // add ! variants to comparatorOp + ops = tokens.comparatorOp.split('|'); + for (i = 0; i < ops.length; i++) { + op = ops[i]; + + if (op.indexOf('!') >= 0) { + continue; + } // skip ops that explicitly contain ! + if (op === '=') { + continue; + } // skip = b/c != is explicitly defined + + tokens.comparatorOp += '|\\!' + op; + } +})(); + +module.exports = tokens; + +/***/ }), +/* 53 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var _require = __webpack_require__(15), + stateSelectorMatches = _require.stateSelectorMatches; + +var is = __webpack_require__(0); + +// generic checking for data/metadata +var operandsMatch = function operandsMatch(query, params) { + var allDataMatches = true; + for (var k = 0; k < query[params.name].length; k++) { + var data = query[params.name][k]; + var operator = data.operator; + var value = data.value; + var field = data.field; + var _matches = void 0; + var fieldVal = params.fieldValue(field); + + if (operator != null && value != null) { + var fieldStr = !is.string(fieldVal) && !is.number(fieldVal) ? '' : '' + fieldVal; + var valStr = '' + value; + + var caseInsensitive = false; + if (operator.indexOf('@') >= 0) { + fieldStr = fieldStr.toLowerCase(); + valStr = valStr.toLowerCase(); + + operator = operator.replace('@', ''); + caseInsensitive = true; + } + + var notExpr = false; + if (operator.indexOf('!') >= 0) { + operator = operator.replace('!', ''); + notExpr = true; + } + + // if we're doing a case insensitive comparison, then we're using a STRING comparison + // even if we're comparing numbers + if (caseInsensitive) { + value = valStr.toLowerCase(); + fieldVal = fieldStr.toLowerCase(); + } + + var isIneqCmp = false; + + switch (operator) { + case '*=': + _matches = fieldStr.indexOf(valStr) >= 0; + break; + case '$=': + _matches = fieldStr.indexOf(valStr, fieldStr.length - valStr.length) >= 0; + break; + case '^=': + _matches = fieldStr.indexOf(valStr) === 0; + break; + case '=': + _matches = fieldVal === value; + break; + case '>': + isIneqCmp = true; + _matches = fieldVal > value; + break; + case '>=': + isIneqCmp = true; + _matches = fieldVal >= value; + break; + case '<': + isIneqCmp = true; + _matches = fieldVal < value; + break; + case '<=': + isIneqCmp = true; + _matches = fieldVal <= value; + break; + default: + _matches = false; + break; + } + + // apply the not op, but null vals for inequalities should always stay non-matching + if (notExpr && (fieldVal != null || !isIneqCmp)) { + _matches = !_matches; + } + } else if (operator != null) { + switch (operator) { + case '?': + _matches = fieldVal ? true : false; + break; + case '!': + _matches = fieldVal ? false : true; + break; + case '^': + _matches = fieldVal === undefined; + break; + } + } else { + _matches = fieldVal !== undefined; + } + + if (!_matches) { + allDataMatches = false; + break; + } + } // for + + return allDataMatches; +}; // operandsMatch + +// check parent/child relations +var confirmRelations = function confirmRelations(query, isNecessary, eles) { + if (query != null) { + var _matches2 = false; + + if (!isNecessary) { + return false; + } + + eles = eles(); // save cycles if query == null + + // query must match for at least one element (may be recursive) + for (var i = 0; i < eles.length; i++) { + if (queryMatches(query, eles[i])) { + _matches2 = true; + break; + } + } + + return _matches2; + } else { + return true; + } +}; + +var queryMatches = function queryMatches(query, ele) { + // make single group-only selectors really cheap to check since they're the most common ones + if (query.groupOnly) { + return query.group === '*' || query.group === ele.group(); + } + + // check group + if (query.group != null && query.group != '*' && query.group != ele.group()) { + return false; + } + + var cy = ele.cy(); + var k = void 0; + + // check colon selectors + var allColonSelectorsMatch = true; + for (k = 0; k < query.colonSelectors.length; k++) { + var sel = query.colonSelectors[k]; + + allColonSelectorsMatch = stateSelectorMatches(sel, ele); + + if (!allColonSelectorsMatch) break; + } + if (!allColonSelectorsMatch) return false; + + // check id + var allIdsMatch = true; + for (k = 0; k < query.ids.length; k++) { + var id = query.ids[k]; + var actualId = ele.id(); + + allIdsMatch = allIdsMatch && id == actualId; + + if (!allIdsMatch) break; + } + if (!allIdsMatch) return false; + + // check classes + var allClassesMatch = true; + for (k = 0; k < query.classes.length; k++) { + var cls = query.classes[k]; + + allClassesMatch = allClassesMatch && ele.hasClass(cls); + + if (!allClassesMatch) break; + } + if (!allClassesMatch) return false; + + // check data matches + var allDataMatches = operandsMatch(query, { + name: 'data', + fieldValue: function fieldValue(field) { + return ele.data(field); + } + }); + + if (!allDataMatches) { + return false; + } + + // check metadata matches + var allMetaMatches = operandsMatch(query, { + name: 'meta', + fieldValue: function fieldValue(field) { + return ele[field](); + } + }); + + if (!allMetaMatches) { + return false; + } + + // check collection + if (query.collection != null) { + var matchesAny = query.collection.hasElementWithId(ele.id()); + + if (!matchesAny) { + return false; + } + } + + // check filter function + if (query.filter != null && ele.collection().some(query.filter)) { + return false; + } + + var isCompound = cy.hasCompoundNodes(); + var getSource = function getSource() { + return ele.source(); + }; + var getTarget = function getTarget() { + return ele.target(); + }; + + if (!confirmRelations(query.parent, isCompound, function () { + return ele.parent(); + })) { + return false; + } + + if (!confirmRelations(query.ancestor, isCompound, function () { + return ele.parents(); + })) { + return false; + } + + if (!confirmRelations(query.child, isCompound, function () { + return ele.children(); + })) { + return false; + } + + if (!confirmRelations(query.descendant, isCompound, function () { + return ele.descendants(); + })) { + return false; + } + + if (!confirmRelations(query.source, true, getSource)) { + return false; + } + + if (!confirmRelations(query.target, true, getTarget)) { + return false; + } + + if (query.connectedNodes) { + var q0 = query.connectedNodes[0]; + var q1 = query.connectedNodes[1]; + + if (confirmRelations(q0, true, getSource) && confirmRelations(q1, true, getTarget)) { + // match + } else if (confirmRelations(q0, true, getTarget) && confirmRelations(q1, true, getSource)) { + // match + } else { + return false; + } + } + + // we've reached the end, so we've matched everything for this query + return true; +}; // queryMatches + +// filter an existing collection +var filter = function filter(collection) { + var self = this; + var cy = collection.cy(); + + // don't bother trying if it's invalid + if (self.invalid()) { + return cy.collection(); + } + + // for 1 id #foo queries, just get the element + if (self.length === 1 && self[0].length === 1 && self[0].ids.length === 1) { + return collection.getElementById(self[0].ids[0]).collection(); + } + + var selectorFunction = function selectorFunction(element) { + for (var j = 0; j < self.length; j++) { + var query = self[j]; + + if (queryMatches(query, element)) { + return true; + } + } + + return false; + }; + + if (self.text() == null) { + selectorFunction = function selectorFunction() { + return true; + }; + } + + var filteredCollection = collection.filter(selectorFunction); + + return filteredCollection; +}; // filter + +// does selector match a single element? +var matches = function matches(ele) { + var self = this; + + // don't bother trying if it's invalid + if (self.invalid()) { + return false; + } + + for (var j = 0; j < self.length; j++) { + var query = self[j]; + + if (queryMatches(query, ele)) { + return true; + } + } + + return false; +}; // filter + +module.exports = { matches: matches, filter: filter }; + +/***/ }), +/* 54 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var Set = __webpack_require__(8); + +var elesfn = { + parent: function parent(selector) { + var parents = []; + + // optimisation for single ele call + if (this.length === 1) { + var parent = this[0]._private.parent; + + if (parent) { + return parent; + } + } + + for (var i = 0; i < this.length; i++) { + var ele = this[i]; + var _parent = ele._private.parent; + + if (_parent) { + parents.push(_parent); + } + } + + return this.spawn(parents, { unique: true }).filter(selector); }, - parents: function( selector ){ + parents: function parents(selector) { var parents = []; var eles = this.parent(); - while( eles.nonempty() ){ - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[ i ]; - parents.push( ele ); + while (eles.nonempty()) { + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; + parents.push(ele); } eles = eles.parent(); } - return this.spawn( parents, { unique: true } ).filter( selector ); + return this.spawn(parents, { unique: true }).filter(selector); }, - commonAncestors: function( selector ){ - var ancestors; + commonAncestors: function commonAncestors(selector) { + var ancestors = void 0; - for( var i = 0; i < this.length; i++ ){ - var ele = this[ i ]; + for (var i = 0; i < this.length; i++) { + var ele = this[i]; var parents = ele.parents(); ancestors = ancestors || parents; - ancestors = ancestors.intersect( parents ); // current list must be common with current ele parents set + ancestors = ancestors.intersect(parents); // current list must be common with current ele parents set } - return ancestors.filter( selector ); + return ancestors.filter(selector); }, - orphans: function( selector ){ - return this.stdFilter( function( ele ){ - return ele.isNode() && ele.parent().empty(); - } ).filter( selector ); + orphans: function orphans(selector) { + return this.stdFilter(function (ele) { + return ele.isOrphan(); + }).filter(selector); }, - nonorphans: function( selector ){ - return this.stdFilter( function( ele ){ - return ele.isNode() && ele.parent().nonempty(); - } ).filter( selector ); + nonorphans: function nonorphans(selector) { + return this.stdFilter(function (ele) { + return ele.isChild(); + }).filter(selector); }, - children: function( selector ){ + children: function children(selector) { var children = []; - for( var i = 0; i < this.length; i++ ){ - var ele = this[ i ]; - children = children.concat( ele._private.children ); + for (var i = 0; i < this.length; i++) { + var ele = this[i]; + children = children.concat(ele._private.children); } - return this.spawn( children, { unique: true } ).filter( selector ); + return this.spawn(children, { unique: true }).filter(selector); }, - siblings: function( selector ){ - return this.parent().children().not( this ).filter( selector ); + siblings: function siblings(selector) { + return this.parent().children().not(this).filter(selector); }, - isParent: function(){ + isParent: function isParent() { var ele = this[0]; - if( ele ){ - return ele._private.children.length !== 0; + if (ele) { + return ele.isNode() && ele._private.children.length !== 0; } }, - isChild: function(){ + isChildless: function isChildless() { var ele = this[0]; - if( ele ){ - return ele._private.data.parent !== undefined && ele.parent().length !== 0; + if (ele) { + return ele.isNode() && ele._private.children.length === 0; } }, - descendants: function( selector ){ + isChild: function isChild() { + var ele = this[0]; + + if (ele) { + return ele.isNode() && ele._private.parent != null; + } + }, + + isOrphan: function isOrphan() { + var ele = this[0]; + + if (ele) { + return ele.isNode() && ele._private.parent == null; + } + }, + + descendants: function descendants(selector) { var elements = []; - function add( eles ){ - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[ i ]; + function add(eles) { + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; - elements.push( ele ); + elements.push(ele); - if( ele.children().nonempty() ){ - add( ele.children() ); + if (ele.children().nonempty()) { + add(ele.children()); } } } - add( this.children() ); + add(this.children()); - return this.spawn( elements, { unique: true } ).filter( selector ); + return this.spawn(elements, { unique: true }).filter(selector); } -}); +}; + +function forEachCompound(eles, fn, includeSelf, recursiveStep) { + var q = []; + var did = new Set(); + var cy = eles.cy(); + var hasCompounds = cy.hasCompoundNodes(); + + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; + + if (includeSelf) { + q.push(ele); + } else if (hasCompounds) { + recursiveStep(q, did, ele); + } + } + + while (q.length > 0) { + var _ele = q.shift(); + + fn(_ele); + + did.add(_ele.id()); + + if (hasCompounds) { + recursiveStep(q, did, _ele); + } + } + + return eles; +} + +function addChildren(q, did, ele) { + if (ele.isParent()) { + var children = ele._private.children; + + for (var i = 0; i < children.length; i++) { + var child = children[i]; + + if (!did.has(child.id())) { + q.push(child); + } + } + } +} + +// very efficient version of eles.add( eles.descendants() ).forEach() +// for internal use +elesfn.forEachDown = function (fn) { + var includeSelf = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + + return forEachCompound(this, fn, includeSelf, addChildren); +}; + +function addParent(q, did, ele) { + if (ele.isChild()) { + var parent = ele._private.parent; + + if (!did.has(parent.id())) { + q.push(parent); + } + } +} + +elesfn.forEachUp = function (fn) { + var includeSelf = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + + return forEachCompound(this, fn, includeSelf, addParent); +}; + +function addParentAndChildren(q, did, ele) { + addParent(q, did, ele); + addChildren(q, did, ele); +} + +elesfn.forEachUpAndDown = function (fn) { + var includeSelf = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + + return forEachCompound(this, fn, includeSelf, addParentAndChildren); +}; // aliases elesfn.ancestors = elesfn.parents; module.exports = elesfn; -},{}],19:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 55 */ +/***/ (function(module, exports, __webpack_require__) { -var define = _dereq_( '../define' ); -var fn, elesfn; +"use strict"; -fn = elesfn = ({ - data: define.data( { +var define = __webpack_require__(4); +var fn = void 0, + elesfn = void 0; + +fn = elesfn = { + + data: define.data({ field: 'data', bindingEvent: 'data', allowBinding: true, @@ -2462,9 +9788,9 @@ fn = elesfn = ({ 'parent': true }, updateStyle: true - } ), + }), - removeData: define.removeData( { + removeData: define.removeData({ field: 'data', event: 'data', triggerFnName: 'trigger', @@ -2476,9 +9802,9 @@ fn = elesfn = ({ 'parent': true }, updateStyle: true - } ), + }), - scratch: define.data( { + scratch: define.data({ field: 'scratch', bindingEvent: 'scratch', allowBinding: true, @@ -2488,38 +9814,38 @@ fn = elesfn = ({ triggerFnName: 'trigger', allowGetting: true, updateStyle: true - } ), + }), - removeScratch: define.removeData( { + removeScratch: define.removeData({ field: 'scratch', event: 'scratch', triggerFnName: 'trigger', triggerEvent: true, updateStyle: true - } ), + }), - rscratch: define.data( { + rscratch: define.data({ field: 'rscratch', allowBinding: false, allowSetting: true, settingTriggersEvent: false, allowGetting: true - } ), + }), - removeRscratch: define.removeData( { + removeRscratch: define.removeData({ field: 'rscratch', triggerEvent: false - } ), + }), - id: function(){ + id: function id() { var ele = this[0]; - if( ele ){ + if (ele) { return ele._private.data.id; } } -}); +}; // aliases fn.attr = fn.data; @@ -2527,36 +9853,42 @@ fn.removeAttr = fn.removeData; module.exports = elesfn; -},{"../define":44}],20:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 56 */ +/***/ (function(module, exports, __webpack_require__) { -var util = _dereq_( '../util' ); +"use strict"; + + +var util = __webpack_require__(1); var elesfn = {}; -function defineDegreeFunction( callback ){ - return function( includeLoops ){ +function defineDegreeFunction(callback) { + return function (includeLoops) { var self = this; - if( includeLoops === undefined ){ + if (includeLoops === undefined) { includeLoops = true; } - if( self.length === 0 ){ return; } + if (self.length === 0) { + return; + } - if( self.isNode() && !self.removed() ){ + if (self.isNode() && !self.removed()) { var degree = 0; var node = self[0]; var connectedEdges = node._private.edges; - for( var i = 0; i < connectedEdges.length; i++ ){ - var edge = connectedEdges[ i ]; + for (var i = 0; i < connectedEdges.length; i++) { + var edge = connectedEdges[i]; - if( !includeLoops && edge.isLoop() ){ + if (!includeLoops && edge.isLoop()) { continue; } - degree += callback( node, edge ); + degree += callback(node, edge); } return degree; @@ -2566,41 +9898,41 @@ function defineDegreeFunction( callback ){ }; } -util.extend( elesfn, { - degree: defineDegreeFunction( function( node, edge ){ - if( edge.source().same( edge.target() ) ){ +util.extend(elesfn, { + degree: defineDegreeFunction(function (node, edge) { + if (edge.source().same(edge.target())) { return 2; } else { return 1; } - } ), + }), - indegree: defineDegreeFunction( function( node, edge ){ - if( edge.target().same( node ) ){ + indegree: defineDegreeFunction(function (node, edge) { + if (edge.target().same(node)) { return 1; } else { return 0; } - } ), + }), - outdegree: defineDegreeFunction( function( node, edge ){ - if( edge.source().same( node ) ){ + outdegree: defineDegreeFunction(function (node, edge) { + if (edge.source().same(node)) { return 1; } else { return 0; } - } ) -} ); + }) +}); -function defineDegreeBoundsFunction( degreeFn, callback ){ - return function( includeLoops ){ - var ret; +function defineDegreeBoundsFunction(degreeFn, callback) { + return function (includeLoops) { + var ret = void 0; var nodes = this.nodes(); - for( var i = 0; i < nodes.length; i++ ){ - var ele = nodes[ i ]; - var degree = ele[ degreeFn ]( includeLoops ); - if( degree !== undefined && (ret === undefined || callback( degree, ret )) ){ + for (var i = 0; i < nodes.length; i++) { + var ele = nodes[i]; + var degree = ele[degreeFn](includeLoops); + if (degree !== undefined && (ret === undefined || callback(degree, ret))) { ret = degree; } } @@ -2609,79 +9941,117 @@ function defineDegreeBoundsFunction( degreeFn, callback ){ }; } -util.extend( elesfn, { - minDegree: defineDegreeBoundsFunction( 'degree', function( degree, min ){ +util.extend(elesfn, { + minDegree: defineDegreeBoundsFunction('degree', function (degree, min) { return degree < min; - } ), + }), - maxDegree: defineDegreeBoundsFunction( 'degree', function( degree, max ){ + maxDegree: defineDegreeBoundsFunction('degree', function (degree, max) { return degree > max; - } ), + }), - minIndegree: defineDegreeBoundsFunction( 'indegree', function( degree, min ){ + minIndegree: defineDegreeBoundsFunction('indegree', function (degree, min) { return degree < min; - } ), + }), - maxIndegree: defineDegreeBoundsFunction( 'indegree', function( degree, max ){ + maxIndegree: defineDegreeBoundsFunction('indegree', function (degree, max) { return degree > max; - } ), + }), - minOutdegree: defineDegreeBoundsFunction( 'outdegree', function( degree, min ){ + minOutdegree: defineDegreeBoundsFunction('outdegree', function (degree, min) { return degree < min; - } ), + }), - maxOutdegree: defineDegreeBoundsFunction( 'outdegree', function( degree, max ){ + maxOutdegree: defineDegreeBoundsFunction('outdegree', function (degree, max) { return degree > max; - } ) -} ); + }) +}); -util.extend( elesfn, { - totalDegree: function( includeLoops ){ +util.extend(elesfn, { + totalDegree: function totalDegree(includeLoops) { var total = 0; var nodes = this.nodes(); - for( var i = 0; i < nodes.length; i++ ){ - total += nodes[ i ].degree( includeLoops ); + for (var i = 0; i < nodes.length; i++) { + total += nodes[i].degree(includeLoops); } return total; } -} ); +}); module.exports = elesfn; -},{"../util":100}],21:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 57 */ +/***/ (function(module, exports, __webpack_require__) { -var define = _dereq_( '../define' ); -var is = _dereq_( '../is' ); -var util = _dereq_( '../util' ); -var math = _dereq_( '../math' ); -var fn, elesfn; +"use strict"; -fn = elesfn = ({ - position: define.data( { +var util = __webpack_require__(1); +var position = __webpack_require__(58); +var bounds = __webpack_require__(59); +var widthHeight = __webpack_require__(60); +var edgePoints = __webpack_require__(61); + +module.exports = util.assign({}, position, bounds, widthHeight, edgePoints); + +/***/ }), +/* 58 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var define = __webpack_require__(4); +var is = __webpack_require__(0); +var math = __webpack_require__(2); +var fn = void 0, + elesfn = void 0; + +var beforePositionSet = function beforePositionSet(eles, newPos) { + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; + + if (ele.isParent() && !ele.locked()) { + var oldPos = ele._private.position; + var delta = { + x: newPos.x - oldPos.x, + y: newPos.y - oldPos.y + }; + + eles.children().shift(delta); + } + } +}; + +fn = elesfn = { + + position: define.data({ field: 'position', bindingEvent: 'position', allowBinding: true, allowSetting: true, settingEvent: 'position', settingTriggersEvent: true, - triggerFnName: 'rtrigger', + triggerFnName: 'emitAndNotify', allowGetting: true, - validKeys: [ 'x', 'y' ], - onSet: function( eles ){ - var updatedEles = eles.updateCompoundBounds(); - updatedEles.rtrigger( 'position' ); + validKeys: ['x', 'y'], + beforeGet: function beforeGet(ele) { + ele.updateCompoundBounds(); }, - canSet: function( ele ){ - return !ele.locked() && !ele.isParent(); + beforeSet: beforePositionSet, + onSet: function onSet(eles) { + eles.dirtyCompoundBoundsCache(); + }, + canSet: function canSet(ele) { + return !ele.locked(); } - } ), + }), // position but no notification to renderer - silentPosition: define.data( { + silentPosition: define.data({ field: 'position', bindingEvent: 'position', allowBinding: false, @@ -2689,91 +10059,116 @@ fn = elesfn = ({ settingEvent: 'position', settingTriggersEvent: false, triggerFnName: 'trigger', - allowGetting: true, - validKeys: [ 'x', 'y' ], - onSet: function( eles ){ - eles.updateCompoundBounds(); + allowGetting: false, + validKeys: ['x', 'y'], + beforeSet: beforePositionSet, + onSet: function onSet(eles) { + eles.dirtyCompoundBoundsCache(); }, - canSet: function( ele ){ - return !ele.locked() && !ele.isParent(); + canSet: function canSet(ele) { + return !ele.locked(); } - } ), + }), - positions: function( pos, silent ){ - if( is.plainObject( pos ) ){ - this.position( pos ); + positions: function positions(pos, silent) { + if (is.plainObject(pos)) { + if (silent) { + this.silentPosition(pos); + } else { + this.position(pos); + } + } else if (is.fn(pos)) { + var _fn = pos; + var cy = this.cy(); - } else if( is.fn( pos ) ){ - var fn = pos; + cy.startBatch(); - for( var i = 0; i < this.length; i++ ){ - var ele = this[ i ]; + for (var i = 0; i < this.length; i++) { + var ele = this[i]; + var _pos = void 0; - var pos = fn.apply( ele, [ i, ele ] ); - - if( pos && !ele.locked() && !ele.isParent() ){ - var elePos = ele._private.position; - elePos.x = pos.x; - elePos.y = pos.y; + if (_pos = _fn(ele, i)) { + if (silent) { + ele.silentPosition(_pos); + } else { + ele.position(_pos); + } } } - var updatedEles = this.updateCompoundBounds(); - var toTrigger = updatedEles.length > 0 ? this.add( updatedEles ) : this; - - if( silent ){ - toTrigger.trigger( 'position' ); - } else { - toTrigger.rtrigger( 'position' ); - } + cy.endBatch(); } return this; // chaining }, - silentPositions: function( pos ){ - return this.positions( pos, true ); + silentPositions: function silentPositions(pos) { + return this.positions(pos, true); + }, + + shift: function shift(dim, val) { + var delta = void 0; + + if (is.plainObject(dim)) { + delta = dim; + } else if (is.string(dim) && is.number(val)) { + delta = { x: 0, y: 0 }; + + delta[dim] = val; + } + + if (delta != null) { + for (var i = 0; i < this.length; i++) { + var ele = this[i]; + var pos = ele.position(); + + ele.position({ + x: pos.x + delta.x, + y: pos.y + delta.y + }); + } + } + + return this; }, // get/set the rendered (i.e. on screen) positon of the element - renderedPosition: function( dim, val ){ + renderedPosition: function renderedPosition(dim, val) { var ele = this[0]; var cy = this.cy(); var zoom = cy.zoom(); var pan = cy.pan(); - var rpos = is.plainObject( dim ) ? dim : undefined; - var setting = rpos !== undefined || ( val !== undefined && is.string( dim ) ); + var rpos = is.plainObject(dim) ? dim : undefined; + var setting = rpos !== undefined || val !== undefined && is.string(dim); - if( ele && ele.isNode() ){ // must have an element and must be a node to return position - if( setting ){ - for( var i = 0; i < this.length; i++ ){ - var ele = this[ i ]; + if (ele && ele.isNode()) { + // must have an element and must be a node to return position + if (setting) { + for (var i = 0; i < this.length; i++) { + var _ele = this[i]; - if( val !== undefined ){ // set one dimension - ele._private.position[ dim ] = ( val - pan[ dim ] ) / zoom; - } else if( rpos !== undefined ){ // set whole position - ele._private.position = { - x: ( rpos.x - pan.x ) / zoom, - y: ( rpos.y - pan.y ) / zoom - }; + if (val !== undefined) { + // set one dimension + _ele.position(dim, (val - pan[dim]) / zoom); + } else if (rpos !== undefined) { + // set whole position + _ele.position(math.renderedToModelPosition(rpos, zoom, pan)); } } + } else { + // getting + var pos = ele.position(); + rpos = math.modelToRenderedPosition(pos, zoom, pan); - this.rtrigger( 'position' ); - } else { // getting - var pos = ele._private.position; - rpos = { - x: pos.x * zoom + pan.x, - y: pos.y * zoom + pan.y - }; - - if( dim === undefined ){ // then return the whole rendered position + if (dim === undefined) { + // then return the whole rendered position return rpos; - } else { // then return the specified dimension - return rpos[ dim ]; + } else { + // then return the specified dimension + return rpos[dim]; } } - } else if( !setting ){ + } else if (!setting) { return undefined; // for empty collection case } @@ -2781,161 +10176,306 @@ fn = elesfn = ({ }, // get/set the position relative to the parent - relativePosition: function( dim, val ){ + relativePosition: function relativePosition(dim, val) { var ele = this[0]; var cy = this.cy(); - var ppos = is.plainObject( dim ) ? dim : undefined; - var setting = ppos !== undefined || ( val !== undefined && is.string( dim ) ); + var ppos = is.plainObject(dim) ? dim : undefined; + var setting = ppos !== undefined || val !== undefined && is.string(dim); var hasCompoundNodes = cy.hasCompoundNodes(); - if( ele && ele.isNode() ){ // must have an element and must be a node to return position - if( setting ){ - for( var i = 0; i < this.length; i++ ){ - var ele = this[ i ]; - var parent = hasCompoundNodes ? ele.parent() : null; + if (ele && ele.isNode()) { + // must have an element and must be a node to return position + if (setting) { + for (var i = 0; i < this.length; i++) { + var _ele2 = this[i]; + var parent = hasCompoundNodes ? _ele2.parent() : null; var hasParent = parent && parent.length > 0; var relativeToParent = hasParent; - if( hasParent ){ + if (hasParent) { parent = parent[0]; } - var origin = relativeToParent ? parent._private.position : { x: 0, y: 0 }; + var origin = relativeToParent ? parent.position() : { x: 0, y: 0 }; - if( val !== undefined ){ // set one dimension - ele._private.position[ dim ] = val + origin[ dim ]; - } else if( ppos !== undefined ){ // set whole position - ele._private.position = { + if (val !== undefined) { + // set one dimension + _ele2.position(dim, val + origin[dim]); + } else if (ppos !== undefined) { + // set whole position + _ele2.position({ x: ppos.x + origin.x, y: ppos.y + origin.y - }; + }); } } + } else { + // getting + var pos = ele.position(); + var _parent = hasCompoundNodes ? ele.parent() : null; + var _hasParent = _parent && _parent.length > 0; + var _relativeToParent = _hasParent; - this.rtrigger( 'position' ); - - } else { // getting - var pos = ele._private.position; - var parent = hasCompoundNodes ? ele.parent() : null; - var hasParent = parent && parent.length > 0; - var relativeToParent = hasParent; - - if( hasParent ){ - parent = parent[0]; + if (_hasParent) { + _parent = _parent[0]; } - var origin = relativeToParent ? parent._private.position : { x: 0, y: 0 }; + var _origin = _relativeToParent ? _parent.position() : { x: 0, y: 0 }; ppos = { - x: pos.x - origin.x, - y: pos.y - origin.y + x: pos.x - _origin.x, + y: pos.y - _origin.y }; - if( dim === undefined ){ // then return the whole rendered position + if (dim === undefined) { + // then return the whole rendered position return ppos; - } else { // then return the specified dimension - return ppos[ dim ]; + } else { + // then return the specified dimension + return ppos[dim]; } } - } else if( !setting ){ + } else if (!setting) { return undefined; // for empty collection case } return this; // chaining - }, - - renderedBoundingBox: function( options ){ - var bb = this.boundingBox( options ); - var cy = this.cy(); - var zoom = cy.zoom(); - var pan = cy.pan(); - - var x1 = bb.x1 * zoom + pan.x; - var x2 = bb.x2 * zoom + pan.x; - var y1 = bb.y1 * zoom + pan.y; - var y2 = bb.y2 * zoom + pan.y; - - return { - x1: x1, - x2: x2, - y1: y1, - y2: y2, - w: x2 - x1, - h: y2 - y1 - }; - }, - - updateCompoundBounds: function(){ - var cy = this.cy(); - - // save cycles for non compound graphs or when style disabled - if( !cy.styleEnabled() || !cy.hasCompoundNodes() ){ return cy.collection(); } - - var updated = []; - - function update( parent ){ - if( !parent.isParent() ){ return; } - - var _p = parent._private; - var children = parent.children(); - var includeLabels = parent.pstyle( 'compound-sizing-wrt-labels' ).value === 'include'; - var bb = children.boundingBox( { - includeLabels: includeLabels, - includeShadows: false, - includeOverlays: false, - - // updating the compound bounds happens outside of the regular - // cache cycle (i.e. before fired events) - useCache: false - } ); - var padding = { - top: parent.pstyle( 'padding-top' ).pfValue, - bottom: parent.pstyle( 'padding-bottom' ).pfValue, - left: parent.pstyle( 'padding-left' ).pfValue, - right: parent.pstyle( 'padding-right' ).pfValue - }; - var pos = _p.position; - - _p.autoWidth = bb.w; - pos.x = (bb.x1 + bb.x2 - padding.left + padding.right) / 2; - - _p.autoHeight = bb.h; - pos.y = (bb.y1 + bb.y2 - padding.top + padding.bottom) / 2; - - updated.push( parent ); - } - - // go up, level by level - var eles = this; - while( eles.nonempty() ){ - - // update each parent node in this level - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[ i ]; - - update( ele ); - } - - // next level - eles = eles.parent(); - } - - // return changed - return this.spawn( updated ); } -}); +}; -var noninf = function( x ){ - if( x === Infinity || x === -Infinity ){ +// aliases +fn.modelPosition = fn.point = fn.position; +fn.modelPositions = fn.points = fn.positions; +fn.renderedPoint = fn.renderedPosition; +fn.relativePoint = fn.relativePosition; + +module.exports = elesfn; + +/***/ }), +/* 59 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var is = __webpack_require__(0); +var util = __webpack_require__(1); +var math = __webpack_require__(2); +var fn = void 0, + elesfn = void 0; + +fn = elesfn = {}; + +elesfn.renderedBoundingBox = function (options) { + var bb = this.boundingBox(options); + var cy = this.cy(); + var zoom = cy.zoom(); + var pan = cy.pan(); + + var x1 = bb.x1 * zoom + pan.x; + var x2 = bb.x2 * zoom + pan.x; + var y1 = bb.y1 * zoom + pan.y; + var y2 = bb.y2 * zoom + pan.y; + + return { + x1: x1, + x2: x2, + y1: y1, + y2: y2, + w: x2 - x1, + h: y2 - y1 + }; +}; + +elesfn.dirtyCompoundBoundsCache = function () { + var cy = this.cy(); + + if (!cy.styleEnabled() || !cy.hasCompoundNodes()) { + return this; + } + + this.forEachUp(function (ele) { + ele._private.compoundBoundsClean = false; + + if (ele.isParent()) { + ele.emit('bounds'); + } + }); + + return this; +}; + +elesfn.updateCompoundBounds = function () { + var cy = this.cy(); + + // save cycles for non compound graphs or when style disabled + if (!cy.styleEnabled() || !cy.hasCompoundNodes()) { + return this; + } + + // save cycles when batching -- but bounds will be stale (or not exist yet) + if (cy.batching()) { + return this; + } + + var updated = []; + + function update(parent) { + if (!parent.isParent()) { + return; + } + + var _p = parent._private; + var children = parent.children(); + var includeLabels = parent.pstyle('compound-sizing-wrt-labels').value === 'include'; + + var min = { + width: { + val: parent.pstyle('min-width').pfValue, + left: parent.pstyle('min-width-bias-left'), + right: parent.pstyle('min-width-bias-right') + }, + height: { + val: parent.pstyle('min-height').pfValue, + top: parent.pstyle('min-height-bias-top'), + bottom: parent.pstyle('min-height-bias-bottom') + } + }; + + var bb = children.boundingBox({ + includeLabels: includeLabels, + includeOverlays: false, + + // updating the compound bounds happens outside of the regular + // cache cycle (i.e. before fired events) + useCache: false + }); + var pos = _p.position; + + // if children take up zero area then keep position and fall back on stylesheet w/h + if (bb.w === 0 || bb.h === 0) { + bb = { + w: parent.pstyle('width').pfValue, + h: parent.pstyle('height').pfValue + }; + + bb.x1 = pos.x - bb.w / 2; + bb.x2 = pos.x + bb.w / 2; + bb.y1 = pos.y - bb.h / 2; + bb.y2 = pos.y + bb.h / 2; + } + + function computeBiasValues(propDiff, propBias, propBiasComplement) { + var biasDiff = 0; + var biasComplementDiff = 0; + var biasTotal = propBias + propBiasComplement; + + if (propDiff > 0 && biasTotal > 0) { + biasDiff = propBias / biasTotal * propDiff; + biasComplementDiff = propBiasComplement / biasTotal * propDiff; + } + return { + biasDiff: biasDiff, + biasComplementDiff: biasComplementDiff + }; + } + + function computePaddingValues(width, height, paddingObject, relativeTo) { + // Assuming percentage is number from 0 to 1 + if (paddingObject.units === '%') { + switch (relativeTo) { + case 'width': + return width > 0 ? paddingObject.pfValue * width : 0; + case 'height': + return height > 0 ? paddingObject.pfValue * height : 0; + case 'average': + return width > 0 && height > 0 ? paddingObject.pfValue * (width + height) / 2 : 0; + case 'min': + return width > 0 && height > 0 ? width > height ? paddingObject.pfValue * height : paddingObject.pfValue * width : 0; + case 'max': + return width > 0 && height > 0 ? width > height ? paddingObject.pfValue * width : paddingObject.pfValue * height : 0; + default: + return 0; + } + } else if (paddingObject.units === 'px') { + return paddingObject.pfValue; + } else { + return 0; + } + } + + var leftVal = min.width.left.value; + if (min.width.left.units === 'px' && min.width.val > 0) { + leftVal = leftVal * 100 / min.width.val; + } + var rightVal = min.width.right.value; + if (min.width.right.units === 'px' && min.width.val > 0) { + rightVal = rightVal * 100 / min.width.val; + } + + var topVal = min.height.top.value; + if (min.height.top.units === 'px' && min.height.val > 0) { + topVal = topVal * 100 / min.height.val; + } + + var bottomVal = min.height.bottom.value; + if (min.height.bottom.units === 'px' && min.height.val > 0) { + bottomVal = bottomVal * 100 / min.height.val; + } + + var widthBiasDiffs = computeBiasValues(min.width.val - bb.w, leftVal, rightVal); + var diffLeft = widthBiasDiffs.biasDiff; + var diffRight = widthBiasDiffs.biasComplementDiff; + + var heightBiasDiffs = computeBiasValues(min.height.val - bb.h, topVal, bottomVal); + var diffTop = heightBiasDiffs.biasDiff; + var diffBottom = heightBiasDiffs.biasComplementDiff; + + _p.autoPadding = computePaddingValues(bb.w, bb.h, parent.pstyle('padding'), parent.pstyle('padding-relative-to').value); + + _p.autoWidth = Math.max(bb.w, min.width.val); + pos.x = (-diffLeft + bb.x1 + bb.x2 + diffRight) / 2; + + _p.autoHeight = Math.max(bb.h, min.height.val); + pos.y = (-diffTop + bb.y1 + bb.y2 + diffBottom) / 2; + + updated.push(parent); + } + + for (var i = 0; i < this.length; i++) { + var ele = this[i]; + var _p = ele._private; + + if (!_p.compoundBoundsClean) { + update(ele); + + if (!cy._private.batchingStyle) { + _p.compoundBoundsClean = true; + } + } + } + + return this; +}; + +var noninf = function noninf(x) { + if (x === Infinity || x === -Infinity) { return 0; } return x; }; -var updateBounds = function( b, x1, y1, x2, y2 ){ +var updateBounds = function updateBounds(b, x1, y1, x2, y2) { // don't update with zero area boxes - if( x2 - x1 === 0 || y2 - y1 === 0 ){ return; } + if (x2 - x1 === 0 || y2 - y1 === 0) { + return; + } + + // don't update with null dim + if (x1 == null || y1 == null || x2 == null || y2 == null) { + return; + } b.x1 = x1 < b.x1 ? x1 : b.x1; b.x2 = x2 > b.x2 ? x2 : b.x2; @@ -2943,27 +10483,31 @@ var updateBounds = function( b, x1, y1, x2, y2 ){ b.y2 = y2 > b.y2 ? y2 : b.y2; }; -var updateBoundsFromBox = function( b, b2 ){ - return updateBounds( b, b2.x1, b2.y1, b2.x2, b2.y2 ); +var updateBoundsFromBox = function updateBoundsFromBox(b, b2) { + return updateBounds(b, b2.x1, b2.y1, b2.x2, b2.y2); }; -var prefixedProperty = function( obj, field, prefix ){ - return util.getPrefixedProperty( obj, field, prefix ); +var prefixedProperty = function prefixedProperty(obj, field, prefix) { + return util.getPrefixedProperty(obj, field, prefix); }; -var updateBoundsFromArrow = function( bounds, ele, prefix, options ){ +var updateBoundsFromArrow = function updateBoundsFromArrow(bounds, ele, prefix) { + if (ele.cy().headless()) { + return; + } + var _p = ele._private; var rstyle = _p.rstyle; var halfArW = rstyle.arrowWidth / 2; - var arrowType = ele.pstyle( prefix + '-arrow-shape' ).value; - var x; - var y; + var arrowType = ele.pstyle(prefix + '-arrow-shape').value; + var x = void 0; + var y = void 0; - if( arrowType !== 'none' ){ - if( prefix === 'source' ){ + if (arrowType !== 'none') { + if (prefix === 'source') { x = rstyle.srcX; y = rstyle.srcY; - } else if( prefix === 'target' ){ + } else if (prefix === 'target') { x = rstyle.tgtX; y = rstyle.tgtY; } else { @@ -2971,14 +10515,18 @@ var updateBoundsFromArrow = function( bounds, ele, prefix, options ){ y = rstyle.midY; } - updateBounds( bounds, x - halfArW, y - halfArW, x + halfArW, y + halfArW ); + updateBounds(bounds, x - halfArW, y - halfArW, x + halfArW, y + halfArW); } }; -var updateBoundsFromLabel = function( bounds, ele, prefix, options ){ - var prefixDash; +var updateBoundsFromLabel = function updateBoundsFromLabel(bounds, ele, prefix) { + if (ele.cy().headless()) { + return; + } - if( prefix ){ + var prefixDash = void 0; + + if (prefix) { prefixDash = prefix + '-'; } else { prefixDash = ''; @@ -2986,40 +10534,40 @@ var updateBoundsFromLabel = function( bounds, ele, prefix, options ){ var _p = ele._private; var rstyle = _p.rstyle; - var label = ele.pstyle( prefixDash + 'label' ).strValue; + var label = ele.pstyle(prefixDash + 'label').strValue; - if( label ){ - var halign = ele.pstyle( 'text-halign' ); - var valign = ele.pstyle( 'text-valign' ); - var labelWidth = prefixedProperty( rstyle, 'labelWidth', prefix ); - var labelHeight = prefixedProperty( rstyle, 'labelHeight', prefix ); - var labelX = prefixedProperty( rstyle, 'labelX', prefix ); - var labelY = prefixedProperty( rstyle, 'labelY', prefix ); - var marginX = ele.pstyle( prefixDash + 'text-margin-x' ).pfValue; - var marginY = ele.pstyle( prefixDash + 'text-margin-y' ).pfValue; + if (label) { + var halign = ele.pstyle('text-halign'); + var valign = ele.pstyle('text-valign'); + var labelWidth = prefixedProperty(rstyle, 'labelWidth', prefix); + var labelHeight = prefixedProperty(rstyle, 'labelHeight', prefix); + var labelX = prefixedProperty(rstyle, 'labelX', prefix); + var labelY = prefixedProperty(rstyle, 'labelY', prefix); + var marginX = ele.pstyle(prefixDash + 'text-margin-x').pfValue; + var marginY = ele.pstyle(prefixDash + 'text-margin-y').pfValue; var isEdge = ele.isEdge(); - var rotation = ele.pstyle( prefixDash + 'text-rotation' ); - var shadowR = ele.pstyle( 'text-shadow-blur' ).pfValue / 2; - var shadowX = ele.pstyle( 'text-shadow-offset-x' ).pfValue; - var shadowY = ele.pstyle( 'text-shadow-offset-y' ).pfValue; - var shadowOpacity = ele.pstyle( 'text-shadow-opacity' ).value; - var outlineWidth = ele.pstyle( 'text-outline-width' ).pfValue; - var borderWidth = ele.pstyle( 'text-border-width' ).pfValue; + var rotation = ele.pstyle(prefixDash + 'text-rotation'); + var outlineWidth = ele.pstyle('text-outline-width').pfValue; + var borderWidth = ele.pstyle('text-border-width').pfValue; var halfBorderWidth = borderWidth / 2; + var padding = ele.pstyle('text-background-padding').pfValue; - var lh = labelHeight; - var lw = labelWidth; + var lh = labelHeight + 2 * padding; + var lw = labelWidth + 2 * padding; var lw_2 = lw / 2; var lh_2 = lh / 2; - var lx1, lx2, ly1, ly2; + var lx1 = void 0, + lx2 = void 0, + ly1 = void 0, + ly2 = void 0; - if( isEdge ){ + if (isEdge) { lx1 = labelX - lw_2; lx2 = labelX + lw_2; ly1 = labelY - lh_2; ly2 = labelY + lh_2; } else { - switch( halign.value ){ + switch (halign.value) { case 'left': lx1 = labelX - lw; lx2 = labelX; @@ -3036,7 +10584,7 @@ var updateBoundsFromLabel = function( bounds, ele, prefix, options ){ break; } - switch( valign.value ){ + switch (valign.value) { case 'top': ly1 = labelY - lh; ly2 = labelY; @@ -3054,15 +10602,15 @@ var updateBoundsFromLabel = function( bounds, ele, prefix, options ){ } } - var isAutorotate = ( isEdge && rotation.strValue === 'autorotate' ); - var isPfValue = ( rotation.pfValue != null && rotation.pfValue !== 0 ); + var isAutorotate = isEdge && rotation.strValue === 'autorotate'; + var isPfValue = rotation.pfValue != null && rotation.pfValue !== 0; - if( isAutorotate || isPfValue ){ - var theta = isAutorotate ? prefixedProperty( _p.rstyle, 'labelAngle', prefix ) : rotation.pfValue; - var cos = Math.cos( theta ); - var sin = Math.sin( theta ); + if (isAutorotate || isPfValue) { + var theta = isAutorotate ? prefixedProperty(_p.rstyle, 'labelAngle', prefix) : rotation.pfValue; + var cos = Math.cos(theta); + var sin = Math.sin(theta); - var rotate = function( x, y ){ + var rotate = function rotate(x, y) { x = x - labelX; y = y - labelY; @@ -3072,42 +10620,33 @@ var updateBoundsFromLabel = function( bounds, ele, prefix, options ){ }; }; - var px1y1 = rotate( lx1, ly1 ); - var px1y2 = rotate( lx1, ly2 ); - var px2y1 = rotate( lx2, ly1 ); - var px2y2 = rotate( lx2, ly2 ); + var px1y1 = rotate(lx1, ly1); + var px1y2 = rotate(lx1, ly2); + var px2y1 = rotate(lx2, ly1); + var px2y2 = rotate(lx2, ly2); - lx1 = Math.min( px1y1.x, px1y2.x, px2y1.x, px2y2.x ); - lx2 = Math.max( px1y1.x, px1y2.x, px2y1.x, px2y2.x ); - ly1 = Math.min( px1y1.y, px1y2.y, px2y1.y, px2y2.y ); - ly2 = Math.max( px1y1.y, px1y2.y, px2y1.y, px2y2.y ); + lx1 = Math.min(px1y1.x, px1y2.x, px2y1.x, px2y2.x); + lx2 = Math.max(px1y1.x, px1y2.x, px2y1.x, px2y2.x); + ly1 = Math.min(px1y1.y, px1y2.y, px2y1.y, px2y2.y); + ly2 = Math.max(px1y1.y, px1y2.y, px2y1.y, px2y2.y); } - lx1 += marginX - Math.max( outlineWidth, halfBorderWidth ); - lx2 += marginX + Math.max( outlineWidth, halfBorderWidth ); - ly1 += marginY - Math.max( outlineWidth, halfBorderWidth ); - ly2 += marginY + Math.max( outlineWidth, halfBorderWidth ); + lx1 += marginX - Math.max(outlineWidth, halfBorderWidth); + lx2 += marginX + Math.max(outlineWidth, halfBorderWidth); + ly1 += marginY - Math.max(outlineWidth, halfBorderWidth); + ly2 += marginY + Math.max(outlineWidth, halfBorderWidth); - updateBounds( bounds, lx1, ly1, lx2, ly2 ); - - if( options.includeShadows && shadowOpacity > 0 ){ - lx1 += - shadowR + shadowX; - lx2 += + shadowR + shadowX; - ly1 += - shadowR + shadowY; - ly2 += + shadowR + shadowY; - - updateBounds( bounds, lx1, ly1, lx2, ly2 ); - } + updateBounds(bounds, lx1, ly1, lx2, ly2); } return bounds; }; // get the bounding box of the elements (in raw model position) -var boundingBoxImpl = function( ele, options ){ +var boundingBoxImpl = function boundingBoxImpl(ele, options) { var cy = ele._private.cy; - var cy_p = cy._private; - var styleEnabled = cy_p.styleEnabled; + var styleEnabled = cy.styleEnabled(); + var headless = cy.headless(); var bounds = { x1: Infinity, @@ -3117,38 +10656,43 @@ var boundingBoxImpl = function( ele, options ){ }; var _p = ele._private; - var display = styleEnabled ? ele.pstyle( 'display' ).value : 'element'; + var display = styleEnabled ? ele.pstyle('display').value : 'element'; var isNode = ele.isNode(); var isEdge = ele.isEdge(); - var ex1, ex2, ey1, ey2, x, y; + var ex1 = void 0, + ex2 = void 0, + ey1 = void 0, + ey2 = void 0; // extrema of body / lines + var x = void 0, + y = void 0; // node pos var displayed = display !== 'none'; - if( displayed ){ + if (displayed) { var overlayOpacity = 0; var overlayPadding = 0; - if( styleEnabled && options.includeOverlays ){ - overlayOpacity = ele.pstyle( 'overlay-opacity' ).value; + if (styleEnabled && options.includeOverlays) { + overlayOpacity = ele.pstyle('overlay-opacity').value; - if( overlayOpacity !== 0 ){ - overlayPadding = ele.pstyle( 'overlay-padding' ).value; + if (overlayOpacity !== 0) { + overlayPadding = ele.pstyle('overlay-padding').value; } } var w = 0; var wHalf = 0; - if( styleEnabled ){ - w = ele.pstyle( 'width' ).pfValue; + if (styleEnabled) { + w = ele.pstyle('width').pfValue; wHalf = w / 2; } - if( isNode && options.includeNodes ){ - var pos = _p.position; + if (isNode && options.includeNodes) { + var pos = ele.position(); x = pos.x; y = pos.y; - var w = ele.outerWidth(); - var halfW = w / 2; + var _w = ele.outerWidth(); + var halfW = _w / 2; var h = ele.outerHeight(); var halfH = h / 2; @@ -3160,18 +10704,17 @@ var boundingBoxImpl = function( ele, options ){ ey1 = y - halfH - overlayPadding; ey2 = y + halfH + overlayPadding; - updateBounds( bounds, ex1, ey1, ex2, ey2 ); - - } else if( isEdge && options.includeEdges ){ + updateBounds(bounds, ex1, ey1, ex2, ey2); + } else if (isEdge && options.includeEdges) { var rstyle = _p.rstyle || {}; // handle edge dimensions (rough box estimate) ////////////////////////////////////////////// - if( styleEnabled ){ - ex1 = Math.min( rstyle.srcX, rstyle.midX, rstyle.tgtX ); - ex2 = Math.max( rstyle.srcX, rstyle.midX, rstyle.tgtX ); - ey1 = Math.min( rstyle.srcY, rstyle.midY, rstyle.tgtY ); - ey2 = Math.max( rstyle.srcY, rstyle.midY, rstyle.tgtY ); + if (styleEnabled && !headless) { + ex1 = Math.min(rstyle.srcX, rstyle.midX, rstyle.tgtX); + ex2 = Math.max(rstyle.srcX, rstyle.midX, rstyle.tgtX); + ey1 = Math.min(rstyle.srcY, rstyle.midY, rstyle.tgtY); + ey2 = Math.max(rstyle.srcY, rstyle.midY, rstyle.tgtY); // take into account edge width ex1 -= wHalf; @@ -3179,75 +10722,73 @@ var boundingBoxImpl = function( ele, options ){ ey1 -= wHalf; ey2 += wHalf; - updateBounds( bounds, ex1, ey1, ex2, ey2 ); + updateBounds(bounds, ex1, ey1, ex2, ey2); } // precise haystacks //////////////////// - if( styleEnabled && ele.pstyle( 'curve-style' ).strValue === 'haystack' ){ - var hpts = rstyle.haystackPts; + if (styleEnabled && !headless && ele.pstyle('curve-style').strValue === 'haystack') { + var hpts = rstyle.haystackPts || []; ex1 = hpts[0].x; ey1 = hpts[0].y; ex2 = hpts[1].x; ey2 = hpts[1].y; - if( ex1 > ex2 ){ + if (ex1 > ex2) { var temp = ex1; ex1 = ex2; ex2 = temp; } - if( ey1 > ey2 ){ - var temp = ey1; + if (ey1 > ey2) { + var _temp = ey1; ey1 = ey2; - ey2 = temp; + ey2 = _temp; } - updateBounds( bounds, ex1 - wHalf, ey1 - wHalf, ex2 + wHalf, ey2 + wHalf ); + updateBounds(bounds, ex1 - wHalf, ey1 - wHalf, ex2 + wHalf, ey2 + wHalf); - // handle points along edge - /////////////////////////// + // handle points along edge + /////////////////////////// } else { var pts = rstyle.bezierPts || rstyle.linePts || []; - for( var j = 0; j < pts.length; j++ ){ - var pt = pts[ j ]; + for (var j = 0; j < pts.length; j++) { + var pt = pts[j]; ex1 = pt.x - wHalf; ex2 = pt.x + wHalf; ey1 = pt.y - wHalf; ey2 = pt.y + wHalf; - updateBounds( bounds, ex1, ey1, ex2, ey2 ); + updateBounds(bounds, ex1, ey1, ex2, ey2); } // fallback on source and target positions ////////////////////////////////////////// - if( pts.length === 0 ){ - var n1 = _p.source; - var n1_p = n1._private; - var n1pos = n1_p.position; + if (pts.length === 0) { + var n1 = ele.source(); + var n1pos = n1.position(); - var n2 = _p.target; - var n2_p = n2._private; - var n2pos = n2_p.position; + var n2 = ele.target(); + var n2pos = n2.position(); ex1 = n1pos.x; ex2 = n2pos.x; ey1 = n1pos.y; ey2 = n2pos.y; - if( ex1 > ex2 ){ - var temp = ex1; + if (ex1 > ex2) { + var _temp2 = ex1; ex1 = ex2; - ex2 = temp; + ex2 = _temp2; } - if( ey1 > ey2 ){ - var temp = ey1; + if (ey1 > ey2) { + var _temp3 = ey1; ey1 = ey2; - ey2 = temp; + ey2 = _temp3; } // take into account edge width @@ -3256,101 +10797,106 @@ var boundingBoxImpl = function( ele, options ){ ey1 -= wHalf; ey2 += wHalf; - updateBounds( bounds, ex1, ey1, ex2, ey2 ); + updateBounds(bounds, ex1, ey1, ex2, ey2); } } - } // edges - // shadow and overlay - ///////////////////// - if( styleEnabled ){ + // handle edge arrow size + ///////////////////////// + + if (styleEnabled && options.includeEdges && isEdge) { + updateBoundsFromArrow(bounds, ele, 'mid-source', options); + updateBoundsFromArrow(bounds, ele, 'mid-target', options); + updateBoundsFromArrow(bounds, ele, 'source', options); + updateBoundsFromArrow(bounds, ele, 'target', options); + } + + // ghost + //////// + + if (styleEnabled) { + var ghost = ele.pstyle('ghost').value === 'yes'; + + if (ghost) { + var gx = ele.pstyle('ghost-offset-x').pfValue; + var gy = ele.pstyle('ghost-offset-y').pfValue; + + updateBounds(bounds, bounds.x1 + gx, bounds.y1 + gy, bounds.x2 + gx, bounds.y2 + gy); + } + } + + // overlay + ////////// + + if (styleEnabled) { ex1 = bounds.x1; ex2 = bounds.x2; ey1 = bounds.y1; ey2 = bounds.y2; - if( options.includeShadows && ele.pstyle('shadow-opacity').value > 0 ){ - var r = ele.pstyle('shadow-blur').pfValue / 2; - var ox = ele.pstyle('shadow-offset-x').pfValue; - var oy = ele.pstyle('shadow-offset-y').pfValue; - - updateBounds( bounds, ex1 - r + ox, ey1 - r + oy, ex2 + r + ox, ey2 + r + oy ); - } - - updateBounds( bounds, ex1 - overlayPadding, ey1 - overlayPadding, ex2 + overlayPadding, ey2 + overlayPadding ); - } - - // handle edge arrow size - ///////////////////////// - - if( styleEnabled && options.includeEdges && isEdge ){ - updateBoundsFromArrow( bounds, ele, 'mid-source', options ); - updateBoundsFromArrow( bounds, ele, 'mid-target', options ); - updateBoundsFromArrow( bounds, ele, 'source', options ); - updateBoundsFromArrow( bounds, ele, 'target', options ); + updateBounds(bounds, ex1 - overlayPadding, ey1 - overlayPadding, ex2 + overlayPadding, ey2 + overlayPadding); } // handle label dimensions ////////////////////////// - if( styleEnabled && options.includeLabels ){ - updateBoundsFromLabel( bounds, ele, null, options ); + if (styleEnabled && options.includeLabels) { + updateBoundsFromLabel(bounds, ele, null, options); - if( isEdge ){ - updateBoundsFromLabel( bounds, ele, 'source', options ); - updateBoundsFromLabel( bounds, ele, 'target', options ); + if (isEdge) { + updateBoundsFromLabel(bounds, ele, 'source', options); + updateBoundsFromLabel(bounds, ele, 'target', options); } } // style enabled for labels } // if displayed - bounds.x1 = noninf( bounds.x1 ); - bounds.y1 = noninf( bounds.y1 ); - bounds.x2 = noninf( bounds.x2 ); - bounds.y2 = noninf( bounds.y2 ); - bounds.w = noninf( bounds.x2 - bounds.x1 ); - bounds.h = noninf( bounds.y2 - bounds.y1 ); + bounds.x1 = noninf(bounds.x1); + bounds.y1 = noninf(bounds.y1); + bounds.x2 = noninf(bounds.x2); + bounds.y2 = noninf(bounds.y2); + bounds.w = noninf(bounds.x2 - bounds.x1); + bounds.h = noninf(bounds.y2 - bounds.y1); // expand bounds by 1 because antialiasing can increase the visual/effective size by 1 on all sides - if( bounds.w > 0 && bounds.h > 0 && displayed ){ - math.expandBoundingBox( bounds, 1 ); + if (bounds.w > 0 && bounds.h > 0 && displayed) { + math.expandBoundingBox(bounds, 1); } return bounds; }; -var tf = function( val ){ - if( val ){ +var tf = function tf(val) { + if (val) { return 't'; } else { return 'f'; } }; -var getKey = function( opts ){ +var getKey = function getKey(opts) { var key = ''; - key += tf( opts.incudeNodes ); - key += tf( opts.includeEdges ); - key += tf( opts.includeLabels ); - key += tf( opts.includeShadows ); - key += tf( opts.includeOverlays ); + key += tf(opts.incudeNodes); + key += tf(opts.includeEdges); + key += tf(opts.includeLabels); + key += tf(opts.includeOverlays); return key; }; -var cachedBoundingBoxImpl = function( ele, opts ){ +var cachedBoundingBoxImpl = function cachedBoundingBoxImpl(ele, opts) { var _p = ele._private; - var bb; + var bb = void 0; var headless = ele.cy().headless(); - var key = opts === defBbOpts ? defBbOptsKey : getKey( opts ); + var key = opts === defBbOpts ? defBbOptsKey : getKey(opts); - if( !opts.useCache || headless || !_p.bbCache || !_p.bbCache[key] ){ - bb = boundingBoxImpl( ele, opts ); + if (!opts.useCache || headless || !_p.bbCache || !_p.bbCache[key]) { + bb = boundingBoxImpl(ele, opts); - if( !headless ){ + if (!headless) { _p.bbCache = _p.bbCache || {}; _p.bbCache[key] = bb; } @@ -3365,23 +10911,34 @@ var defBbOpts = { includeNodes: true, includeEdges: true, includeLabels: true, - includeShadows: true, includeOverlays: true, useCache: true }; -var defBbOptsKey = getKey( defBbOpts ); +var defBbOptsKey = getKey(defBbOpts); -elesfn.boundingBox = function( options ){ +function filledBbOpts(options) { + return { + includeNodes: util.default(options.includeNodes, defBbOpts.includeNodes), + includeEdges: util.default(options.includeEdges, defBbOpts.includeEdges), + includeLabels: util.default(options.includeLabels, defBbOpts.includeLabels), + includeOverlays: util.default(options.includeOverlays, defBbOpts.includeOverlays), + useCache: util.default(options.useCache, defBbOpts.useCache) + }; +} + +elesfn.boundingBox = function (options) { // the main usecase is ele.boundingBox() for a single element with no/def options // specified s.t. the cache is used, so check for this case to make it faster by // avoiding the overhead of the rest of the function - if( this.length === 1 && this[0]._private.bbCache && (options === undefined || options.useCache === undefined || options.useCache === true) ){ - if( options === undefined ){ + if (this.length === 1 && this[0]._private.bbCache && (options === undefined || options.useCache === undefined || options.useCache === true)) { + if (options === undefined) { options = defBbOpts; + } else { + options = filledBbOpts(options); } - return cachedBoundingBoxImpl( this[0], options ); + return cachedBoundingBoxImpl(this[0], options); } var bounds = { @@ -3393,68 +10950,148 @@ elesfn.boundingBox = function( options ){ options = options || util.staticEmptyObject(); - var opts = { - includeNodes: util.default( options.includeNodes, defBbOpts.includeNodes ), - includeEdges: util.default( options.includeEdges, defBbOpts.includeEdges ), - includeLabels: util.default( options.includeLabels, defBbOpts.includeLabels ), - includeShadows: util.default( options.includeShadows, defBbOpts.includeShadows ), - includeOverlays: util.default( options.includeOverlays, defBbOpts.includeOverlays ), - useCache: util.default( options.useCache, defBbOpts.useCache ) - }; + var opts = filledBbOpts(options); var eles = this; var cy = eles.cy(); - var renderer = eles.cy().renderer(); var styleEnabled = cy.styleEnabled(); - if( styleEnabled ){ - renderer.recalculateRenderedStyle( eles, opts.useCache ); + if (styleEnabled) { + this.recalculateRenderedStyle(opts.useCache); } - for( var i = 0; i < eles.length; i++ ){ + this.updateCompoundBounds(); + + var updatedEdge = {}; // use to avoid duplicated edge updates + + for (var i = 0; i < eles.length; i++) { var ele = eles[i]; - if( styleEnabled && ele.isEdge() && ele.pstyle('curve-style').strValue === 'bezier' ){ - renderer.recalculateRenderedStyle( ele.parallelEdges(), opts.useCache ); // n.b. ele.parallelEdges() single is cached + if (styleEnabled && ele.isEdge() && ele.pstyle('curve-style').strValue === 'bezier' && !updatedEdge[ele.id()]) { + var edges = ele.parallelEdges(); + + for (var j = 0; j < edges.length; j++) { + // make all as updated + updatedEdge[edges[j].id()] = true; + } + + edges.recalculateRenderedStyle(opts.useCache); // n.b. ele.parallelEdges() single is cached } - updateBoundsFromBox( bounds, cachedBoundingBoxImpl( ele, opts ) ); + updateBoundsFromBox(bounds, cachedBoundingBoxImpl(ele, opts)); } - bounds.x1 = noninf( bounds.x1 ); - bounds.y1 = noninf( bounds.y1 ); - bounds.x2 = noninf( bounds.x2 ); - bounds.y2 = noninf( bounds.y2 ); - bounds.w = noninf( bounds.x2 - bounds.x1 ); - bounds.h = noninf( bounds.y2 - bounds.y1 ); + bounds.x1 = noninf(bounds.x1); + bounds.y1 = noninf(bounds.y1); + bounds.x2 = noninf(bounds.x2); + bounds.y2 = noninf(bounds.y2); + bounds.w = noninf(bounds.x2 - bounds.x1); + bounds.h = noninf(bounds.y2 - bounds.y1); return bounds; }; -var defineDimFns = function( opts ){ - opts.uppercaseName = util.capitalize( opts.name ); +// private helper to get bounding box for custom node positions +// - good for perf in certain cases but currently requires dirtying the rendered style +// - would be better to not modify the nodes but the nodes are read directly everywhere in the renderer... +// - try to use for only things like discrete layouts where the node position would change anyway +elesfn.boundingBoxAt = function (fn) { + var nodes = this.nodes(); + + if (is.plainObject(fn)) { + var obj = fn; + + fn = function fn() { + return obj; + }; + } + + // save the current position and set the new one, per node + for (var i = 0; i < nodes.length; i++) { + var n = nodes[i]; + var _p = n._private; + var pos = _p.position; + var newPos = fn.call(n, n, i); + + _p.bbAtOldPos = { x: pos.x, y: pos.y }; + + if (newPos) { + pos.x = newPos.x; + pos.y = newPos.y; + } + } + + this.emit('dirty'); // let the renderer know we've manually dirtied rendered dim calcs + + nodes.dirtyCompoundBoundsCache().updateCompoundBounds(); + + var bb = this.boundingBox({ useCache: false }); + + // restore the original position, per node + for (var _i = 0; _i < nodes.length; _i++) { + var _n = nodes[_i]; + var _p2 = _n._private; + var _pos = _n._private.position; + var old = _p2.bbAtOldPos; + + _pos.x = old.x; + _pos.y = old.y; + } + + nodes.dirtyCompoundBoundsCache(); + + this.emit('dirty'); // let the renderer know we've manually dirtied rendered dim calcs + + return bb; +}; + +fn.boundingbox = fn.boundingBox; +fn.renderedBoundingbox = fn.renderedBoundingBox; + +module.exports = elesfn; + +/***/ }), +/* 60 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var util = __webpack_require__(1); +var fn = void 0, + elesfn = void 0; + +fn = elesfn = {}; + +var defineDimFns = function defineDimFns(opts) { + opts.uppercaseName = util.capitalize(opts.name); opts.autoName = 'auto' + opts.uppercaseName; opts.labelName = 'label' + opts.uppercaseName; opts.outerName = 'outer' + opts.uppercaseName; - opts.uppercaseOuterName = util.capitalize( opts.outerName ); + opts.uppercaseOuterName = util.capitalize(opts.outerName); - fn[ opts.name ] = function dimImpl(){ + fn[opts.name] = function dimImpl() { var ele = this[0]; var _p = ele._private; var cy = _p.cy; var styleEnabled = cy._private.styleEnabled; - if( ele ){ - if( styleEnabled ){ - if( ele.isParent() ){ - return _p[ opts.autoName ] || 0; + if (ele) { + if (styleEnabled) { + if (ele.isParent()) { + ele.updateCompoundBounds(); + + return _p[opts.autoName] || 0; } - var d = ele.pstyle( opts.name ); + var d = ele.pstyle(opts.name); - switch( d.strValue ){ + switch (d.strValue) { case 'label': - return _p.rstyle[ opts.labelName ] || 0; + ele.recalculateRenderedStyle(); + + return _p.rstyle[opts.labelName] || 0; + default: return d.pfValue; } @@ -3464,17 +11101,17 @@ var defineDimFns = function( opts ){ } }; - fn[ 'outer' + opts.uppercaseName ] = function outerDimImpl(){ + fn['outer' + opts.uppercaseName] = function outerDimImpl() { var ele = this[0]; var _p = ele._private; var cy = _p.cy; var styleEnabled = cy._private.styleEnabled; - if( ele ){ - if( styleEnabled ){ - var dim = ele[ opts.name ](); - var border = ele.pstyle( 'border-width' ).pfValue; - var padding = ele.pstyle( opts.paddings[0] ).pfValue + ele.pstyle( opts.paddings[1] ).pfValue; + if (ele) { + if (styleEnabled) { + var dim = ele[opts.name](); + var border = ele.pstyle('border-width').pfValue; // n.b. 1/2 each side + var padding = 2 * ele.padding(); return dim + border + padding; } else { @@ -3483,314 +11120,394 @@ var defineDimFns = function( opts ){ } }; - fn[ 'rendered' + opts.uppercaseName ] = function renderedDimImpl(){ + fn['rendered' + opts.uppercaseName] = function renderedDimImpl() { var ele = this[0]; - if( ele ){ - var d = ele[ opts.name ](); + if (ele) { + var d = ele[opts.name](); return d * this.cy().zoom(); } }; - fn[ 'rendered' + opts.uppercaseOuterName ] = function renderedOuterDimImpl(){ + fn['rendered' + opts.uppercaseOuterName] = function renderedOuterDimImpl() { var ele = this[0]; - if( ele ){ - var od = ele[ opts.outerName ](); + if (ele) { + var od = ele[opts.outerName](); return od * this.cy().zoom(); } }; }; -defineDimFns( { - name: 'width', - paddings: [ 'padding-left', 'padding-right' ] -} ); - -defineDimFns( { - name: 'height', - paddings: [ 'padding-top', 'padding-bottom' ] -} ); - -// aliases -fn.modelPosition = fn.point = fn.position; -fn.modelPositions = fn.points = fn.positions; -fn.renderedPoint = fn.renderedPosition; -fn.relativePoint = fn.relativePosition; -fn.boundingbox = fn.boundingBox; -fn.renderedBoundingbox = fn.renderedBoundingBox; - -module.exports = elesfn; - -},{"../define":44,"../is":83,"../math":85,"../util":100}],22:[function(_dereq_,module,exports){ -'use strict'; - -var util = _dereq_( '../util' ); -var is = _dereq_( '../is' ); - -// represents a node or an edge -var Element = function( cy, params, restore ){ - var self = this; - restore = (restore === undefined || restore ? true : false); - - if( cy === undefined || params === undefined || !is.core( cy ) ){ - util.error( 'An element must have a core reference and parameters set' ); - return; - } - - var group = params.group; - - // try to automatically infer the group if unspecified - if( group == null ){ - if( params.data && params.data.source != null && params.data.target != null ){ - group = 'edges'; - } else { - group = 'nodes'; - } - } - - // validate group - if( group !== 'nodes' && group !== 'edges' ){ - util.error( 'An element must be of type `nodes` or `edges`; you specified `' + group + '`' ); - return; - } - - // make the element array-like, just like a collection - this.length = 1; - this[0] = this; - - // NOTE: when something is added here, add also to ele.json() - this._private = { - cy: cy, - single: true, // indicates this is an element - data: params.data || {}, // data object - position: params.position || {}, // (x, y) position pair - autoWidth: undefined, // width and height of nodes calculated by the renderer when set to special 'auto' value - autoHeight: undefined, - listeners: [], // array of bound listeners - group: group, // string; 'nodes' or 'edges' - style: {}, // properties as set by the style - rstyle: {}, // properties for style sent from the renderer to the core - styleCxts: [], // applied style contexts from the styler - removed: true, // whether it's inside the vis; true if removed (set true here since we call restore) - selected: params.selected ? true : false, // whether it's selected - selectable: params.selectable === undefined ? true : ( params.selectable ? true : false ), // whether it's selectable - locked: params.locked ? true : false, // whether the element is locked (cannot be moved) - grabbed: false, // whether the element is grabbed by the mouse; renderer sets this privately - grabbable: params.grabbable === undefined ? true : ( params.grabbable ? true : false ), // whether the element can be grabbed - active: false, // whether the element is active from user interaction - classes: {}, // map ( className => true ) - animation: { // object for currently-running animations - current: [], - queue: [] - }, - rscratch: {}, // object in which the renderer can store information - scratch: params.scratch || {}, // scratch objects - edges: [], // array of connected edges - children: [], // array of children - traversalCache: {} // cache of output of traversal functions - }; - - // renderedPosition overrides if specified - if( params.renderedPosition ){ - var rpos = params.renderedPosition; - var pan = cy.pan(); - var zoom = cy.zoom(); - - this._private.position = { - x: (rpos.x - pan.x) / zoom, - y: (rpos.y - pan.y) / zoom - }; - } - - if( is.string( params.classes ) ){ - var classes = params.classes.split( /\s+/ ); - for( var i = 0, l = classes.length; i < l; i++ ){ - var cls = classes[ i ]; - if( !cls || cls === '' ){ continue; } - - self._private.classes[ cls ] = true; - } - } - - if( params.style || params.css ){ - cy.style().applyBypass( this, params.style || params.css ); - } - - if( restore === undefined || restore ){ - this.restore(); - } - -}; - -module.exports = Element; - -},{"../is":83,"../util":100}],23:[function(_dereq_,module,exports){ -'use strict'; - -var define = _dereq_( '../define' ); - -var elesfn = ({ - on: define.on(), // .on( events [, selector] [, data], handler) - one: define.on( { unbindSelfOnTrigger: true } ), - once: define.on( { unbindAllBindersOnTrigger: true } ), - off: define.off(), // .off( events [, selector] [, handler] ) - trigger: define.trigger(), // .trigger( events [, extraParams] ) - - rtrigger: function( event, extraParams ){ // for internal use only - if( this.length === 0 ){ return; } // empty collections don't need to notify anything - - // notify renderer - this.cy().notify( { - type: event, - eles: this - } ); - - this.trigger( event, extraParams ); - return this; - } +defineDimFns({ + name: 'width' }); -// aliases: -define.eventAliasesOn( elesfn ); +defineDimFns({ + name: 'height' +}); + +elesfn.padding = function () { + var ele = this[0]; + var _p = ele._private; + if (ele.isParent()) { + ele.updateCompoundBounds(); + + if (_p.autoPadding !== undefined) { + return _p.autoPadding; + } else { + return ele.pstyle('padding').pfValue; + } + } else { + return ele.pstyle('padding').pfValue; + } +}; module.exports = elesfn; -},{"../define":44}],24:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 61 */ +/***/ (function(module, exports, __webpack_require__) { -var is = _dereq_( '../is' ); -var Selector = _dereq_( '../selector' ); +"use strict"; -var elesfn = ({ - nodes: function( selector ){ - return this.filter( function( i, element ){ - return element.isNode(); - } ).filter( selector ); + +var ifEdge = function ifEdge(self, then) { + if (self.isEdge()) { + return then(self.renderer()); + } +}; + +module.exports = { + controlPoints: function controlPoints() { + var _this = this; + + return ifEdge(this, function (renderer) { + return renderer.getControlPoints(_this); + }); + }, + segmentPoints: function segmentPoints() { + var _this2 = this; + + return ifEdge(this, function (renderer) { + return renderer.getSegmentPoints(_this2); + }); + }, + sourceEndpoint: function sourceEndpoint() { + var _this3 = this; + + return ifEdge(this, function (renderer) { + return renderer.getSourceEndpoint(_this3); + }); + }, + targetEndpoint: function targetEndpoint() { + var _this4 = this; + + return ifEdge(this, function (renderer) { + return renderer.getTargetEndpoint(_this4); + }); + }, + midpoint: function midpoint() { + var _this5 = this; + + return ifEdge(this, function (renderer) { + return renderer.getEdgeMidpoint(_this5); + }); + } +}; + +/***/ }), +/* 62 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var Emitter = __webpack_require__(11); +var define = __webpack_require__(4); +var is = __webpack_require__(0); +var util = __webpack_require__(1); +var Selector = __webpack_require__(6); + +var emitterOptions = { + qualifierCompare: function qualifierCompare(selector1, selector2) { + if (selector1 == null || selector2 == null) { + return selector1 == null && selector2 == null; + } else { + return selector1.sameText(selector2); + } + }, + eventMatches: function eventMatches(ele, listener, eventObj) { + var selector = listener.qualifier; + + if (selector != null) { + return ele !== eventObj.target && is.element(eventObj.target) && selector.matches(eventObj.target); + } + + return true; + }, + eventFields: function eventFields(ele) { + return { + cy: ele.cy(), + target: ele + }; + }, + callbackContext: function callbackContext(ele, listener, eventObj) { + return listener.qualifier != null ? eventObj.target : ele; + }, + beforeEmit: function beforeEmit(context, listener /*, eventObj*/) { + if (listener.conf && listener.conf.once) { + listener.conf.onceCollection.removeListener(listener.event, listener.qualifier, listener.callback); + } + }, + bubble: function bubble() { + return true; + }, + parent: function parent(ele) { + return ele.isChild() ? ele.parent() : ele.cy(); + } +}; + +var argSelector = function argSelector(arg) { + if (is.string(arg)) { + return new Selector(arg); + } else { + return arg; + } +}; + +var elesfn = { + createEmitter: function createEmitter() { + for (var i = 0; i < this.length; i++) { + var ele = this[i]; + var _p = ele._private; + + if (!_p.emitter) { + _p.emitter = new Emitter(util.assign({ + context: ele + }, emitterOptions)); + } + } + + return this; }, - edges: function( selector ){ - return this.filter( function( i, element ){ - return element.isEdge(); - } ).filter( selector ); + emitter: function emitter() { + return this._private.emitter; }, - filter: function( filter ){ - if( filter === undefined ){ // check this first b/c it's the most common/performant case + on: function on(events, selector, callback) { + for (var i = 0; i < this.length; i++) { + var ele = this[i]; + + ele.emitter().on(events, argSelector(selector), callback); + } + + return this; + }, + + removeListener: function removeListener(events, selector, callback) { + for (var i = 0; i < this.length; i++) { + var ele = this[i]; + + ele.emitter().removeListener(events, argSelector(selector), callback); + } + + return this; + }, + + one: function one(events, selector, callback) { + for (var i = 0; i < this.length; i++) { + var ele = this[i]; + + ele.emitter().one(events, argSelector(selector), callback); + } + + return this; + }, + + once: function once(events, selector, callback) { + for (var i = 0; i < this.length; i++) { + var ele = this[i]; + + ele.emitter().on(events, argSelector(selector), callback, { + once: true, + onceCollection: this + }); + } + }, + + emit: function emit(events, extraParams) { + for (var i = 0; i < this.length; i++) { + var ele = this[i]; + + ele.emitter().emit(events, extraParams); + } + + return this; + }, + + emitAndNotify: function emitAndNotify(event, extraParams) { + // for internal use only + if (this.length === 0) { + return; + } // empty collections don't need to notify anything + + // notify renderer + this.cy().notify({ + type: event, + eles: this + }); + + this.emit(event, extraParams); + + return this; + } +}; + +define.eventAliasesOn(elesfn); + +module.exports = elesfn; + +/***/ }), +/* 63 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var is = __webpack_require__(0); +var Selector = __webpack_require__(6); + +var elesfn = { + nodes: function nodes(selector) { + return this.filter(function (ele) { + return ele.isNode(); + }).filter(selector); + }, + + edges: function edges(selector) { + return this.filter(function (ele) { + return ele.isEdge(); + }).filter(selector); + }, + + filter: function filter(_filter, thisArg) { + if (_filter === undefined) { + // check this first b/c it's the most common/performant case return this; - } else if( is.string( filter ) || is.elementOrCollection( filter ) ){ - return Selector( filter ).filter( this ); - } else if( is.fn( filter ) ){ - var elements = []; + } else if (is.string(_filter) || is.elementOrCollection(_filter)) { + return new Selector(_filter).filter(this); + } else if (is.fn(_filter)) { + var filterEles = this.spawn(); + var eles = this; - for( var i = 0; i < this.length; i++ ){ - var ele = this[ i ]; + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; + var include = thisArg ? _filter.apply(thisArg, [ele, i, eles]) : _filter(ele, i, eles); - if( filter.apply( ele, [ i, ele ] ) ){ - elements.push( ele ); + if (include) { + filterEles.merge(ele); } } - return this.spawn( elements ); + return filterEles; } return this.spawn(); // if not handled by above, give 'em an empty collection }, - not: function( toRemove ){ - if( !toRemove ){ + not: function not(toRemove) { + if (!toRemove) { return this; } else { - if( is.string( toRemove ) ){ - toRemove = this.filter( toRemove ); + if (is.string(toRemove)) { + toRemove = this.filter(toRemove); } var elements = []; + var rMap = toRemove._private.map; - for( var i = 0; i < this.length; i++ ){ - var element = this[ i ]; + for (var i = 0; i < this.length; i++) { + var element = this[i]; - var remove = toRemove._private.ids[ element.id() ]; - if( !remove ){ - elements.push( element ); + var remove = rMap.has(element.id()); + if (!remove) { + elements.push(element); } } - return this.spawn( elements ); + return this.spawn(elements); } - }, - absoluteComplement: function(){ - var cy = this._private.cy; + absoluteComplement: function absoluteComplement() { + var cy = this.cy(); - return cy.mutableElements().not( this ); + return cy.mutableElements().not(this); }, - intersect: function( other ){ + intersect: function intersect(other) { // if a selector is specified, then filter by it instead - if( is.string( other ) ){ + if (is.string(other)) { var selector = other; - return this.filter( selector ); + return this.filter(selector); } var elements = []; var col1 = this; var col2 = other; var col1Smaller = this.length < other.length; - // var ids1 = col1Smaller ? col1._private.ids : col2._private.ids; - var ids2 = col1Smaller ? col2._private.ids : col1._private.ids; + var map2 = col1Smaller ? col2._private.map : col1._private.map; var col = col1Smaller ? col1 : col2; - for( var i = 0; i < col.length; i++ ){ - var id = col[ i ]._private.data.id; - var ele = ids2[ id ]; + for (var i = 0; i < col.length; i++) { + var id = col[i]._private.data.id; + var entry = map2.get(id); - if( ele ){ - elements.push( ele ); + if (entry) { + elements.push(entry.ele); } } - return this.spawn( elements ); + return this.spawn(elements); }, - xor: function( other ){ + xor: function xor(other) { var cy = this._private.cy; - if( is.string( other ) ){ - other = cy.$( other ); + if (is.string(other)) { + other = cy.$(other); } var elements = []; var col1 = this; var col2 = other; - var add = function( col, other ){ - - for( var i = 0; i < col.length; i++ ){ - var ele = col[ i ]; + var add = function add(col, other) { + for (var i = 0; i < col.length; i++) { + var ele = col[i]; var id = ele._private.data.id; - var inOther = other._private.ids[ id ]; + var inOther = other.hasElementWithId(id); - if( !inOther ){ - elements.push( ele ); + if (!inOther) { + elements.push(ele); } } - }; - add( col1, col2 ); - add( col2, col1 ); + add(col1, col2); + add(col2, col1); - return this.spawn( elements ); + return this.spawn(elements); }, - diff: function( other ){ + diff: function diff(other) { var cy = this._private.cy; - if( is.string( other ) ){ - other = cy.$( other ); + if (is.string(other)) { + other = cy.$(other); } var left = []; @@ -3799,91 +11516,95 @@ var elesfn = ({ var col1 = this; var col2 = other; - var add = function( col, other, retEles ){ + var add = function add(col, other, retEles) { - for( var i = 0; i < col.length; i++ ){ - var ele = col[ i ]; + for (var i = 0; i < col.length; i++) { + var ele = col[i]; var id = ele._private.data.id; - var inOther = other._private.ids[ id ]; + var inOther = other.hasElementWithId(id); - if( inOther ){ - both.push( ele ); + if (inOther) { + both.push(ele); } else { - retEles.push( ele ); + retEles.push(ele); } } - }; - add( col1, col2, left ); - add( col2, col1, right ); + add(col1, col2, left); + add(col2, col1, right); return { - left: this.spawn( left, { unique: true } ), - right: this.spawn( right, { unique: true } ), - both: this.spawn( both, { unique: true } ) + left: this.spawn(left, { unique: true }), + right: this.spawn(right, { unique: true }), + both: this.spawn(both, { unique: true }) }; }, - add: function( toAdd ){ + add: function add(toAdd) { var cy = this._private.cy; - if( !toAdd ){ + if (!toAdd) { return this; } - if( is.string( toAdd ) ){ + if (is.string(toAdd)) { var selector = toAdd; - toAdd = cy.mutableElements().filter( selector ); + toAdd = cy.mutableElements().filter(selector); } var elements = []; - for( var i = 0; i < this.length; i++ ){ - elements.push( this[ i ] ); + for (var i = 0; i < this.length; i++) { + elements.push(this[i]); } - for( var i = 0; i < toAdd.length; i++ ){ + var map = this._private.map; - var add = !this._private.ids[ toAdd[ i ].id() ]; - if( add ){ - elements.push( toAdd[ i ] ); + for (var _i = 0; _i < toAdd.length; _i++) { + + var add = !map.has(toAdd[_i].id()); + if (add) { + elements.push(toAdd[_i]); } } - return this.spawn( elements ); + return this.spawn(elements); }, // in place merge on calling collection - merge: function( toAdd ){ + merge: function merge(toAdd) { var _p = this._private; var cy = _p.cy; - if( !toAdd ){ + if (!toAdd) { return this; } - if( toAdd && is.string( toAdd ) ){ + if (toAdd && is.string(toAdd)) { var selector = toAdd; - toAdd = cy.mutableElements().filter( selector ); + toAdd = cy.mutableElements().filter(selector); } - for( var i = 0; i < toAdd.length; i++ ){ - var toAddEle = toAdd[ i ]; - var id = toAddEle._private.data.id; - var add = !_p.ids[ id ]; + var map = _p.map; - if( add ){ + for (var i = 0; i < toAdd.length; i++) { + var toAddEle = toAdd[i]; + var id = toAddEle._private.data.id; + var add = !map.has(id); + + if (add) { var index = this.length++; - this[ index ] = toAddEle; - _p.ids[ id ] = toAddEle; - _p.indexes[ id ] = index; - } else { // replace - var index = _p.indexes[ id ]; + this[index] = toAddEle; - this[ index ] = toAddEle; - _p.ids[ id ] = toAddEle; + map.set(id, { ele: toAddEle, index: index }); + } else { + // replace + var _index = map.get(id).index; + + this[_index] = toAddEle; + map.set(id, { ele: toAddEle, index: _index }); } } @@ -3891,33 +11612,35 @@ var elesfn = ({ }, // remove single ele in place in calling collection - unmergeOne: function( ele ){ + unmergeOne: function unmergeOne(ele) { ele = ele[0]; var _p = this._private; var id = ele._private.data.id; - var i = _p.indexes[ id ]; + var map = _p.map; + var entry = map.get(id); - if( i == null ){ + if (!entry) { return this; // no need to remove } + var i = entry.index; + // remove ele - this[ i ] = undefined; - _p.ids[ id ] = undefined; - _p.indexes[ id ] = undefined; + this[i] = undefined; + map.delete(id); var unmergedLastEle = i === this.length - 1; // replace empty spot with last ele in collection - if( this.length > 1 && !unmergedLastEle ){ + if (this.length > 1 && !unmergedLastEle) { var lastEleI = this.length - 1; - var lastEle = this[ lastEleI ]; + var lastEle = this[lastEleI]; var lastEleId = lastEle._private.data.id; - this[ lastEleI ] = undefined; - this[ i ] = lastEle; - _p.indexes[ lastEleId ] = i; + this[lastEleI] = undefined; + this[i] = lastEle; + map.set(lastEleId, { ele: lastEle, index: i }); } // the collection is now 1 ele smaller @@ -3927,65 +11650,60 @@ var elesfn = ({ }, // remove eles in place on calling collection - unmerge: function( toRemove ){ + unmerge: function unmerge(toRemove) { var cy = this._private.cy; - if( !toRemove ){ + if (!toRemove) { return this; } - if( toRemove && is.string( toRemove ) ){ + if (toRemove && is.string(toRemove)) { var selector = toRemove; - toRemove = cy.mutableElements().filter( selector ); + toRemove = cy.mutableElements().filter(selector); } - for( var i = 0; i < toRemove.length; i++ ){ - this.unmergeOne( toRemove[ i ] ); + for (var i = 0; i < toRemove.length; i++) { + this.unmergeOne(toRemove[i]); } return this; // chaining }, - map: function( mapFn, thisArg ){ + map: function map(mapFn, thisArg) { var arr = []; var eles = this; - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[ i ]; - var ret = thisArg ? mapFn.apply( thisArg, [ ele, i, eles ] ) : mapFn( ele, i, eles ); + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; + var ret = thisArg ? mapFn.apply(thisArg, [ele, i, eles]) : mapFn(ele, i, eles); - arr.push( ret ); + arr.push(ret); } return arr; }, - stdFilter: function( fn, thisArg ){ - var filterEles = []; + reduce: function reduce(fn, initialValue) { + var val = initialValue; var eles = this; - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[ i ]; - var include = thisArg ? fn.apply( thisArg, [ ele, i, eles ] ) : fn( ele, i, eles ); - - if( include ){ - filterEles.push( ele ); - } + for (var i = 0; i < eles.length; i++) { + val = fn(val, eles[i], i, eles); } - return this.spawn( filterEles ); + return val; }, - max: function( valFn, thisArg ){ + max: function max(valFn, thisArg) { var max = -Infinity; - var maxEle; + var maxEle = void 0; var eles = this; - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[ i ]; - var val = thisArg ? valFn.apply( thisArg, [ ele, i, eles ] ) : valFn( ele, i, eles ); + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; + var val = thisArg ? valFn.apply(thisArg, [ele, i, eles]) : valFn(ele, i, eles); - if( val > max ){ + if (val > max) { max = val; maxEle = ele; } @@ -3997,16 +11715,16 @@ var elesfn = ({ }; }, - min: function( valFn, thisArg ){ + min: function min(valFn, thisArg) { var min = Infinity; - var minEle; + var minEle = void 0; var eles = this; - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[ i ]; - var val = thisArg ? valFn.apply( thisArg, [ ele, i, eles ] ) : valFn( ele, i, eles ); + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; + var val = thisArg ? valFn.apply(thisArg, [ele, i, eles]) : valFn(ele, i, eles); - if( val < min ){ + if (val < min) { min = val; minEle = ele; } @@ -4017,906 +11735,172 @@ var elesfn = ({ ele: minEle }; } -}); +}; // aliases var fn = elesfn; -fn[ 'u' ] = fn[ '|' ] = fn[ '+' ] = fn.union = fn.or = fn.add; -fn[ '\\' ] = fn[ '!' ] = fn[ '-' ] = fn.difference = fn.relativeComplement = fn.subtract = fn.not; -fn[ 'n' ] = fn[ '&' ] = fn[ '.' ] = fn.and = fn.intersection = fn.intersect; -fn[ '^' ] = fn[ '(+)' ] = fn[ '(-)' ] = fn.symmetricDifference = fn.symdiff = fn.xor; -fn.fnFilter = fn.filterFn = fn.stdFilter; +fn['u'] = fn['|'] = fn['+'] = fn.union = fn.or = fn.add; +fn['\\'] = fn['!'] = fn['-'] = fn.difference = fn.relativeComplement = fn.subtract = fn.not; +fn['n'] = fn['&'] = fn['.'] = fn.and = fn.intersection = fn.intersect; +fn['^'] = fn['(+)'] = fn['(-)'] = fn.symmetricDifference = fn.symdiff = fn.xor; +fn.fnFilter = fn.filterFn = fn.stdFilter = fn.filter; fn.complement = fn.abscomp = fn.absoluteComplement; module.exports = elesfn; -},{"../is":83,"../selector":87}],25:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 64 */ +/***/ (function(module, exports, __webpack_require__) { -var elesfn = ({ - isNode: function(){ +"use strict"; + + +var elesfn = { + isNode: function isNode() { return this.group() === 'nodes'; }, - isEdge: function(){ + isEdge: function isEdge() { return this.group() === 'edges'; }, - isLoop: function(){ + isLoop: function isLoop() { return this.isEdge() && this.source().id() === this.target().id(); }, - isSimple: function(){ + isSimple: function isSimple() { return this.isEdge() && this.source().id() !== this.target().id(); }, - group: function(){ + group: function group() { var ele = this[0]; - if( ele ){ + if (ele) { return ele._private.group; } } -}); - +}; module.exports = elesfn; -},{}],26:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 65 */ +/***/ (function(module, exports, __webpack_require__) { -var util = _dereq_( '../util' ); -var is = _dereq_( '../is' ); +"use strict"; -var Element = _dereq_( './element' ); -// factory for generating edge ids when no id is specified for a new element -var idFactory = { - generate: function( cy, element, tryThisId ){ - var id = tryThisId != null ? tryThisId : util.uuid(); +var is = __webpack_require__(0); +var zIndexSort = __webpack_require__(17); +var util = __webpack_require__(1); - while( cy.hasElementWithId( id ) ){ - id = util.uuid(); - } +var elesfn = { + forEach: function forEach(fn, thisArg) { + if (is.fn(fn)) { - return id; - } -}; - -// represents a set of nodes, edges, or both together -var Collection = function( cy, elements, options ){ - if( cy === undefined || !is.core( cy ) ){ - util.error( 'A collection must have a reference to the core' ); - return; - } - - var ids = {}; - var indexes = {}; - var createdElements = false; - - if( !elements ){ - elements = []; - } else if( elements.length > 0 && is.plainObject( elements[0] ) && !is.element( elements[0] ) ){ - createdElements = true; - - // make elements from json and restore all at once later - var eles = []; - var elesIds = {}; - - for( var i = 0, l = elements.length; i < l; i++ ){ - var json = elements[ i ]; - - if( json.data == null ){ - json.data = {}; - } - - var data = json.data; - - // make sure newly created elements have valid ids - if( data.id == null ){ - data.id = idFactory.generate( cy, json ); - } else if( cy.hasElementWithId( data.id ) || elesIds[ data.id ] ){ - continue; // can't create element if prior id already exists - } - - var ele = new Element( cy, json, false ); - eles.push( ele ); - elesIds[ data.id ] = true; - } - - elements = eles; - } - - this.length = 0; - - for( var i = 0, l = elements.length; i < l; i++ ){ - var element = elements[ i ]; - if( !element ){ continue; } - - var id = element._private.data.id; - - if( !options || (options.unique && !ids[ id ] ) ){ - ids[ id ] = element; - indexes[ id ] = this.length; - - this[ this.length ] = element; - this.length++; - } - } - - this._private = { - cy: cy, - ids: ids, - indexes: indexes - }; - - // restore the elements if we created them from json - if( createdElements ){ - this.restore(); - } -}; - -// Functions -//////////////////////////////////////////////////////////////////////////////////////////////////// - -// keep the prototypes in sync (an element has the same functions as a collection) -// and use elefn and elesfn as shorthands to the prototypes -var elesfn = Element.prototype = Collection.prototype; - -elesfn.instanceString = function(){ - return 'collection'; -}; - -elesfn.spawn = function( cy, eles, opts ){ - if( !is.core( cy ) ){ // cy is optional - opts = eles; - eles = cy; - cy = this.cy(); - } - - return new Collection( cy, eles, opts ); -}; - -elesfn.spawnSelf = function(){ - return this.spawn( this ); -}; - -elesfn.cy = function(){ - return this._private.cy; -}; - -elesfn.element = function(){ - return this[0]; -}; - -elesfn.collection = function(){ - if( is.collection( this ) ){ - return this; - } else { // an element - return new Collection( this._private.cy, [ this ] ); - } -}; - -elesfn.unique = function(){ - return new Collection( this._private.cy, this, { unique: true } ); -}; - -elesfn.hasElementWithId = function( id ){ - return !!this._private.ids[ id ]; -}; - -elesfn.getElementById = function( id ){ - var cy = this._private.cy; - var ele = this._private.ids[ id ]; - - return ele ? ele : new Collection( cy ); // get ele or empty collection -}; - -elesfn.poolIndex = function(){ - var cy = this._private.cy; - var eles = cy._private.elements; - var id = this._private.data.id; - - return eles._private.indexes[ id ]; -}; - -elesfn.json = function( obj ){ - var ele = this.element(); - var cy = this.cy(); - - if( ele == null && obj ){ return this; } // can't set to no eles - - if( ele == null ){ return undefined; } // can't get from no eles - - var p = ele._private; - - if( is.plainObject( obj ) ){ // set - - cy.startBatch(); - - if( obj.data ){ - ele.data( obj.data ); - } - - if( obj.position ){ - ele.position( obj.position ); - } - - // ignore group -- immutable - - var checkSwitch = function( k, trueFnName, falseFnName ){ - var obj_k = obj[ k ]; - - if( obj_k != null && obj_k !== p[ k ] ){ - if( obj_k ){ - ele[ trueFnName ](); - } else { - ele[ falseFnName ](); - } - } - }; - - checkSwitch( 'removed', 'remove', 'restore' ); - - checkSwitch( 'selected', 'select', 'unselect' ); - - checkSwitch( 'selectable', 'selectify', 'unselectify' ); - - checkSwitch( 'locked', 'lock', 'unlock' ); - - checkSwitch( 'grabbable', 'grabify', 'ungrabify' ); - - if( obj.classes != null ){ - ele.classes( obj.classes ); - } - - cy.endBatch(); - - return this; - - } else if( obj === undefined ){ // get - - var json = { - data: util.copy( p.data ), - position: util.copy( p.position ), - group: p.group, - removed: p.removed, - selected: p.selected, - selectable: p.selectable, - locked: p.locked, - grabbable: p.grabbable, - classes: null - }; - - json.classes = Object.keys( p.classes ).filter(function( cls ){ - return p.classes[cls]; - }).join(' '); - - return json; - } -}; - -elesfn.jsons = function(){ - var jsons = []; - - for( var i = 0; i < this.length; i++ ){ - var ele = this[ i ]; - var json = ele.json(); - - jsons.push( json ); - } - - return jsons; -}; - -elesfn.clone = function(){ - var cy = this.cy(); - var elesArr = []; - - for( var i = 0; i < this.length; i++ ){ - var ele = this[ i ]; - var json = ele.json(); - var clone = new Element( cy, json, false ); // NB no restore - - elesArr.push( clone ); - } - - return new Collection( cy, elesArr ); -}; -elesfn.copy = elesfn.clone; - -elesfn.restore = function( notifyRenderer ){ - var self = this; - var cy = self.cy(); - var cy_p = cy._private; - - if( notifyRenderer === undefined ){ - notifyRenderer = true; - } - - // create arrays of nodes and edges, since we need to - // restore the nodes first - var nodes = []; - var edges = []; - var elements; - for( var i = 0, l = self.length; i < l; i++ ){ - var ele = self[ i ]; - - if( !ele.removed() ){ - // don't need to handle this ele - continue; - } - - // keep nodes first in the array and edges after - if( ele.isNode() ){ // put to front of array if node - nodes.push( ele ); - } else { // put to end of array if edge - edges.push( ele ); - } - } - - elements = nodes.concat( edges ); - - var i; - var removeFromElements = function(){ - elements.splice( i, 1 ); - i--; - }; - - // now, restore each element - for( i = 0; i < elements.length; i++ ){ - var ele = elements[ i ]; - - var _private = ele._private; - var data = _private.data; - - // the traversal cache should start fresh when ele is added - _private.traversalCache = null; - - // set id and validate - if( data.id === undefined ){ - data.id = idFactory.generate( cy, ele ); - - } else if( is.number( data.id ) ){ - data.id = '' + data.id; // now it's a string - - } else if( is.emptyString( data.id ) || !is.string( data.id ) ){ - util.error( 'Can not create element with invalid string ID `' + data.id + '`' ); - - // can't create element if it has empty string as id or non-string id - removeFromElements(); - continue; - } else if( cy.hasElementWithId( data.id ) ){ - util.error( 'Can not create second element with ID `' + data.id + '`' ); - - // can't create element if one already has that id - removeFromElements(); - continue; - } - - var id = data.id; // id is finalised, now let's keep a ref - - if( ele.isNode() ){ // extra checks for nodes - var node = ele; - var pos = _private.position; - - // make sure the nodes have a defined position - - if( pos.x == null ){ - pos.x = 0; - } - - if( pos.y == null ){ - pos.y = 0; - } - } - - if( ele.isEdge() ){ // extra checks for edges - - var edge = ele; - var fields = [ 'source', 'target' ]; - var fieldsLength = fields.length; - var badSourceOrTarget = false; - for( var j = 0; j < fieldsLength; j++ ){ - - var field = fields[ j ]; - var val = data[ field ]; - - if( is.number( val ) ){ - val = data[ field ] = '' + data[ field ]; // now string - } - - if( val == null || val === '' ){ - // can't create if source or target is not defined properly - util.error( 'Can not create edge `' + id + '` with unspecified ' + field ); - badSourceOrTarget = true; - } else if( !cy.hasElementWithId( val ) ){ - // can't create edge if one of its nodes doesn't exist - util.error( 'Can not create edge `' + id + '` with nonexistant ' + field + ' `' + val + '`' ); - badSourceOrTarget = true; - } - } - - if( badSourceOrTarget ){ removeFromElements(); continue; } // can't create this - - var src = cy.getElementById( data.source ); - var tgt = cy.getElementById( data.target ); - - src._private.edges.push( edge ); - tgt._private.edges.push( edge ); - - edge._private.source = src; - edge._private.target = tgt; - } // if is edge - - // create mock ids / indexes maps for element so it can be used like collections - _private.ids = {}; - _private.ids[ id ] = ele; - _private.indexes = {}; - _private.indexes[ id ] = ele; - - _private.removed = false; - cy.addToPool( ele ); - } // for each element - - // do compound node sanity checks - for( var i = 0; i < nodes.length; i++ ){ // each node - var node = nodes[ i ]; - var data = node._private.data; - - if( is.number( data.parent ) ){ // then automake string - data.parent = '' + data.parent; - } - - var parentId = data.parent; - - var specifiedParent = parentId != null; - - if( specifiedParent ){ - var parent = cy.getElementById( parentId ); - - if( parent.empty() ){ - // non-existant parent; just remove it - data.parent = undefined; - } else { - var selfAsParent = false; - var ancestor = parent; - while( !ancestor.empty() ){ - if( node.same( ancestor ) ){ - // mark self as parent and remove from data - selfAsParent = true; - data.parent = undefined; // remove parent reference - - // exit or we loop forever - break; - } - - ancestor = ancestor.parent(); - } - - if( !selfAsParent ){ - // connect with children - parent[0]._private.children.push( node ); - node._private.parent = parent[0]; - - // let the core know we have a compound graph - cy_p.hasCompoundNodes = true; - } - } // else - } // if specified parent - } // for each node - - if( elements.length > 0 ){ - var restored = new Collection( cy, elements ); - - for( var i = 0; i < restored.length; i++ ){ - var ele = restored[i]; - - if( ele.isNode() ){ continue; } - - // adding an edge invalidates the traversal caches for the parallel edges - var pedges = ele.parallelEdges(); - for( var j = 0; j < pedges.length; j++ ){ - pedges[j]._private.traversalCache = null; - } - - // adding an edge invalidates the traversal cache for the connected nodes - ele.source()[0]._private.traversalCache = null; - ele.target()[0]._private.traversalCache = null; - } - - var toUpdateStyle; - - if( cy_p.hasCompoundNodes ){ - toUpdateStyle = restored.add( restored.connectedNodes() ).add( restored.parent() ); - } else { - toUpdateStyle = restored; - } - - toUpdateStyle.updateStyle( notifyRenderer ); - - if( notifyRenderer ){ - restored.rtrigger( 'add' ); - } else { - restored.trigger( 'add' ); - } - } - - return self; // chainability -}; - -elesfn.removed = function(){ - var ele = this[0]; - return ele && ele._private.removed; -}; - -elesfn.inside = function(){ - var ele = this[0]; - return ele && !ele._private.removed; -}; - -elesfn.remove = function( notifyRenderer ){ - var self = this; - var removed = []; - var elesToRemove = []; - var elesToRemoveIds = {}; - var cy = self._private.cy; - - if( notifyRenderer === undefined ){ - notifyRenderer = true; - } - - // add connected edges - function addConnectedEdges( node ){ - var edges = node._private.edges; - for( var i = 0; i < edges.length; i++ ){ - add( edges[ i ] ); - } - } - - - // add descendant nodes - function addChildren( node ){ - var children = node._private.children; - - for( var i = 0; i < children.length; i++ ){ - add( children[ i ] ); - } - } - - function add( ele ){ - var alreadyAdded = elesToRemoveIds[ ele.id() ]; - if( alreadyAdded ){ - return; - } else { - elesToRemoveIds[ ele.id() ] = true; - } - - if( ele.isNode() ){ - elesToRemove.push( ele ); // nodes are removed last - - addConnectedEdges( ele ); - addChildren( ele ); - } else { - elesToRemove.unshift( ele ); // edges are removed first - } - } - - // make the list of elements to remove - // (may be removing more than specified due to connected edges etc) - - for( var i = 0, l = self.length; i < l; i++ ){ - var ele = self[ i ]; - - add( ele ); - } - - function removeEdgeRef( node, edge ){ - var connectedEdges = node._private.edges; - - util.removeFromArray( connectedEdges, edge ); - - // removing an edges invalidates the traversal cache for its nodes - node._private.traversalCache = null; - } - - function removeParallelRefs( edge ){ - // removing an edge invalidates the traversal caches for the parallel edges - var pedges = edge.parallelEdges(); - for( var j = 0; j < pedges.length; j++ ){ - pedges[j]._private.traversalCache = null; - } - } - - var alteredParents = []; - alteredParents.ids = {}; - - function removeChildRef( parent, ele ){ - ele = ele[0]; - parent = parent[0]; - - var children = parent._private.children; - var pid = parent.id(); - - util.removeFromArray( children, ele ); - - if( !alteredParents.ids[ pid ] ){ - alteredParents.ids[ pid ] = true; - alteredParents.push( parent ); - } - } - - // remove from core pool - cy.removeFromPool( elesToRemove ); - - for( var i = 0; i < elesToRemove.length; i++ ){ - var ele = elesToRemove[ i ]; - - // mark as removed - ele._private.removed = true; - - // add to list of removed elements - removed.push( ele ); - - if( ele.isEdge() ){ // remove references to this edge in its connected nodes - var src = ele.source()[0]; - var tgt = ele.target()[0]; - - removeEdgeRef( src, ele ); - removeEdgeRef( tgt, ele ); - removeParallelRefs( ele ); - - } else { // remove reference to parent - var parent = ele.parent(); - - if( parent.length !== 0 ){ - removeChildRef( parent, ele ); - } - } - } - - // check to see if we have a compound graph or not - var elesStillInside = cy._private.elements; - cy._private.hasCompoundNodes = false; - for( var i = 0; i < elesStillInside.length; i++ ){ - var ele = elesStillInside[ i ]; - - if( ele.isParent() ){ - cy._private.hasCompoundNodes = true; - break; - } - } - - var removedElements = new Collection( this.cy(), removed ); - if( removedElements.size() > 0 ){ - // must manually notify since trigger won't do this automatically once removed - - if( notifyRenderer ){ - this.cy().notify( { - type: 'remove', - eles: removedElements - } ); - } - - removedElements.trigger( 'remove' ); - } - - // the parents who were modified by the removal need their style updated - for( var i = 0; i < alteredParents.length; i++ ){ - var ele = alteredParents[ i ]; - - if( !ele.removed() ){ - ele.updateStyle(); - } - } - - return new Collection( cy, removed ); -}; - -elesfn.move = function( struct ){ - var cy = this._private.cy; - - if( struct.source !== undefined || struct.target !== undefined ){ - var srcId = struct.source; - var tgtId = struct.target; - var srcExists = cy.hasElementWithId( srcId ); - var tgtExists = cy.hasElementWithId( tgtId ); - - if( srcExists || tgtExists ){ - var jsons = this.jsons(); - - this.remove(); - - for( var i = 0; i < jsons.length; i++ ){ - var json = jsons[i]; + for (var i = 0; i < this.length; i++) { var ele = this[i]; + var ret = thisArg ? fn.apply(thisArg, [ele, i, this]) : fn(ele, i, this); - if( json.group === 'edges' ){ - if( srcExists ){ json.data.source = srcId; } - - if( tgtExists ){ json.data.target = tgtId; } - - json.scratch = ele._private.scratch; - } - } - - return cy.add( jsons ); - } - - } else if( struct.parent !== undefined ){ // move node to new parent - var parentId = struct.parent; - var parentExists = parentId === null || cy.hasElementWithId( parentId ); - - if( parentExists ){ - var jsons = this.jsons(); - var descs = this.descendants(); - var descsEtc = descs.union( descs.union( this ).connectedEdges() ); - - this.remove(); // NB: also removes descendants and their connected edges - - for( var i = 0; i < this.length; i++ ){ - var json = jsons[i]; - var ele = this[i]; - - if( json.group === 'nodes' ){ - json.data.parent = parentId === null ? undefined : parentId; - - json.scratch = ele._private.scratch; - } - } - - return cy.add( jsons ).union( descsEtc.restore() ); - } - } - - return this; // if nothing done -}; - -[ - _dereq_( './algorithms' ), - _dereq_( './animation' ), - _dereq_( './class' ), - _dereq_( './comparators' ), - _dereq_( './compounds' ), - _dereq_( './data' ), - _dereq_( './degree' ), - _dereq_( './dimensions' ), - _dereq_( './events' ), - _dereq_( './filter' ), - _dereq_( './group' ), - _dereq_( './index' ), - _dereq_( './iteration' ), - _dereq_( './layout' ), - _dereq_( './style' ), - _dereq_( './switch-functions' ), - _dereq_( './traversing' ) -].forEach( function( props ){ - util.extend( elesfn, props ); -} ); - -module.exports = Collection; - -},{"../is":83,"../util":100,"./algorithms":11,"./animation":15,"./class":16,"./comparators":17,"./compounds":18,"./data":19,"./degree":20,"./dimensions":21,"./element":22,"./events":23,"./filter":24,"./group":25,"./index":26,"./iteration":27,"./layout":28,"./style":29,"./switch-functions":30,"./traversing":31}],27:[function(_dereq_,module,exports){ -'use strict'; - -var is = _dereq_( '../is' ); -var zIndexSort = _dereq_( './zsort' ); - -var elesfn = ({ - each: function( fn ){ - if( is.fn( fn ) ){ - for( var i = 0; i < this.length; i++ ){ - var ele = this[ i ]; - var ret = fn.apply( ele, [ i, ele ] ); - - if( ret === false ){ break; } // exit each early on return false - } - } - return this; - }, - - forEach: function( fn, thisArg ){ - if( is.fn( fn ) ){ - - for( var i = 0; i < this.length; i++ ){ - var ele = this[ i ]; - var ret = thisArg ? fn.apply( thisArg, [ ele, i, this ] ) : fn( ele, i, this ); - - if( ret === false ){ break; } // exit each early on return false + if (ret === false) { + break; + } // exit each early on return false } } return this; }, - toArray: function(){ + toArray: function toArray() { var array = []; - for( var i = 0; i < this.length; i++ ){ - array.push( this[ i ] ); + for (var i = 0; i < this.length; i++) { + array.push(this[i]); } return array; }, - slice: function( start, end ){ + slice: function slice(start, end) { var array = []; var thisSize = this.length; - if( end == null ){ + if (end == null) { end = thisSize; } - if( start == null ){ + if (start == null) { start = 0; } - if( start < 0 ){ + if (start < 0) { start = thisSize + start; } - if( end < 0 ){ + if (end < 0) { end = thisSize + end; } - for( var i = start; i >= 0 && i < end && i < thisSize; i++ ){ - array.push( this[ i ] ); + for (var i = start; i >= 0 && i < end && i < thisSize; i++) { + array.push(this[i]); } - return this.spawn( array ); + return this.spawn(array); }, - size: function(){ + size: function size() { return this.length; }, - eq: function( i ){ - return this[ i ] || this.spawn(); + eq: function eq(i) { + return this[i] || this.spawn(); }, - first: function(){ + first: function first() { return this[0] || this.spawn(); }, - last: function(){ - return this[ this.length - 1 ] || this.spawn(); + last: function last() { + return this[this.length - 1] || this.spawn(); }, - empty: function(){ + empty: function empty() { return this.length === 0; }, - nonempty: function(){ + nonempty: function nonempty() { return !this.empty(); }, - sort: function( sortFn ){ - if( !is.fn( sortFn ) ){ + sort: function sort(sortFn) { + if (!is.fn(sortFn)) { return this; } - var sorted = this.toArray().sort( sortFn ); + var sorted = this.toArray().sort(sortFn); - return this.spawn( sorted ); + return this.spawn(sorted); }, - sortByZIndex: function(){ - return this.sort( zIndexSort ); + sortByZIndex: function sortByZIndex() { + return this.sort(zIndexSort); }, - zDepth: function(){ + zDepth: function zDepth() { var ele = this[0]; - if( !ele ){ return undefined; } + if (!ele) { + return undefined; + } - // var cy = ele.cy(); + // let cy = ele.cy(); var _p = ele._private; var group = _p.group; - if( group === 'nodes' ){ + if (group === 'nodes') { var depth = _p.data.parent ? ele.parents().size() : 0; - if( !ele.isParent() ){ - return Number.MAX_VALUE; // childless nodes always on top + if (!ele.isParent()) { + return util.MAX_INT - 1; // childless nodes always on top } return depth; @@ -4926,266 +11910,467 @@ var elesfn = ({ var srcDepth = src.zDepth(); var tgtDepth = tgt.zDepth(); - return Math.max( srcDepth, tgtDepth, 0 ); // depth of deepest parent + return Math.max(srcDepth, tgtDepth, 0); // depth of deepest parent } } -}); +}; + +elesfn.each = elesfn.forEach; module.exports = elesfn; -},{"../is":83,"./zsort":32}],28:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 66 */ +/***/ (function(module, exports, __webpack_require__) { -var is = _dereq_( '../is' ); -var util = _dereq_( '../util' ); -var Promise = _dereq_('../promise'); +"use strict"; -var elesfn = ({ + +var is = __webpack_require__(0); +var util = __webpack_require__(1); +var Promise = __webpack_require__(5); +var math = __webpack_require__(2); + +var elesfn = { + // Calculates and returns node dimensions { x, y } based on options given + layoutDimensions: function layoutDimensions(options) { + options = util.assign({ + nodeDimensionsIncludeLabels: true + }, options); + + if (options.nodeDimensionsIncludeLabels) { + var bbDim = this.boundingBox(); + return { + w: bbDim.w, + h: bbDim.h + }; + } else { + return { + w: this.outerWidth(), + h: this.outerHeight() + }; + } + }, // using standard layout options, apply position function (w/ or w/o animation) - layoutPositions: function( layout, options, fn ){ + layoutPositions: function layoutPositions(layout, options, fn) { var nodes = this.nodes(); var cy = this.cy(); + var layoutEles = options.eles; // nodes & edges + var getMemoizeKey = function getMemoizeKey(node, i) { + return node.id() + '$' + i; + }; + var fnMem = util.memoize(fn, getMemoizeKey); // memoized version of position function - layout.trigger( { type: 'layoutstart', layout: layout } ); + layout.emit({ type: 'layoutstart', layout: layout }); layout.animations = []; - if( options.animate ){ - for( var i = 0; i < nodes.length; i++ ){ - var node = nodes[ i ]; + var calculateSpacing = function calculateSpacing(spacing, nodesBb, pos) { + var center = { + x: nodesBb.x1 + nodesBb.w / 2, + y: nodesBb.y1 + nodesBb.h / 2 + }; - var newPos = fn.call( node, i, node ); - var pos = node.position(); + var spacingVector = { // scale from center of bounding box (not necessarily 0,0) + x: (pos.x - center.x) * spacing, + y: (pos.y - center.y) * spacing + }; - if( !is.number( pos.x ) || !is.number( pos.y ) ){ - node.silentPosition( { x: 0, y: 0 } ); + return { + x: center.x + spacingVector.x, + y: center.y + spacingVector.y + }; + }; + + var useSpacingFactor = options.spacingFactor && options.spacingFactor !== 1; + + var spacingBb = function spacingBb() { + if (!useSpacingFactor) { + return null; + } + + var bb = math.makeBoundingBox(); + + for (var i = 0; i < nodes.length; i++) { + var node = nodes[i]; + var pos = fnMem(node, i); + + math.expandBoundingBoxByPoint(bb, pos.x, pos.y); + } + + return bb; + }; + + var bb = spacingBb(); + + var getFinalPos = util.memoize(function (node, i) { + var newPos = fnMem(node, i); + var pos = node.position(); + + if (!is.number(pos.x) || !is.number(pos.y)) { + node.silentPosition({ x: 0, y: 0 }); + } + + if (useSpacingFactor) { + var spacing = Math.abs(options.spacingFactor); + + newPos = calculateSpacing(spacing, bb, newPos); + } + + if (options.transform != null) { + newPos = options.transform(node, newPos); + } + + return newPos; + }, getMemoizeKey); + + if (options.animate) { + for (var i = 0; i < nodes.length; i++) { + var node = nodes[i]; + var newPos = getFinalPos(node, i); + var animateNode = options.animateFilter == null || options.animateFilter(node, i); + + if (animateNode) { + var ani = node.animation({ + position: newPos, + duration: options.animationDuration, + easing: options.animationEasing + }); + + layout.animations.push(ani); + + ani.play(); + } else { + node.position(newPos); } + } - var ani = node.animation( { - position: newPos, + if (options.fit) { + var fitAni = cy.animation({ + fit: { + boundingBox: layoutEles.boundingBoxAt(getFinalPos), + padding: options.padding + }, duration: options.animationDuration, easing: options.animationEasing - } ); + }); - layout.animations.push( ani ); + layout.animations.push(fitAni); - ani.play(); + fitAni.play(); + } else if (options.zoom !== undefined && options.pan !== undefined) { + var zoomPanAni = cy.animation({ + zoom: options.zoom, + pan: options.pan, + duration: options.animationDuration, + easing: options.animationEasing + }); + + layout.animations.push(zoomPanAni); + + zoomPanAni.play(); } - var onStep; - cy.on( 'step.*', ( onStep = function(){ - if( options.fit ){ - cy.fit( options.eles, options.padding ); - } - }) ); + layout.one('layoutready', options.ready); + layout.emit({ type: 'layoutready', layout: layout }); - layout.one('layoutstop', function(){ - cy.off('step.*', onStep); - }); - - layout.one( 'layoutready', options.ready ); - layout.trigger( { type: 'layoutready', layout: layout } ); - - Promise.all( layout.animations.map(function( ani ){ + Promise.all(layout.animations.map(function (ani) { return ani.promise(); - }) ).then(function(){ - cy.off('step.*', onStep); - - if( options.zoom != null ){ - cy.zoom( options.zoom ); - } - - if( options.pan ){ - cy.pan( options.pan ); - } - - if( options.fit ){ - cy.fit( options.eles, options.padding ); - } - - layout.one( 'layoutstop', options.stop ); - layout.trigger( { type: 'layoutstop', layout: layout } ); + })).then(function () { + layout.one('layoutstop', options.stop); + layout.emit({ type: 'layoutstop', layout: layout }); }); } else { - nodes.positions( fn ); - if( options.fit ){ - cy.fit( options.eles, options.padding ); + nodes.positions(getFinalPos); + + if (options.fit) { + cy.fit(options.eles, options.padding); } - if( options.zoom != null ){ - cy.zoom( options.zoom ); + if (options.zoom != null) { + cy.zoom(options.zoom); } - if( options.pan ){ - cy.pan( options.pan ); + if (options.pan) { + cy.pan(options.pan); } - layout.one( 'layoutready', options.ready ); - layout.trigger( { type: 'layoutready', layout: layout } ); + layout.one('layoutready', options.ready); + layout.emit({ type: 'layoutready', layout: layout }); - layout.one( 'layoutstop', options.stop ); - layout.trigger( { type: 'layoutstop', layout: layout } ); + layout.one('layoutstop', options.stop); + layout.emit({ type: 'layoutstop', layout: layout }); } return this; // chaining }, - layout: function( options ){ + layout: function layout(options) { var cy = this.cy(); - cy.layout( util.extend( {}, options, { + return cy.makeLayout(util.extend({}, options, { eles: this - } ) ); + })); + } + +}; + +// aliases: +elesfn.createLayout = elesfn.makeLayout = elesfn.layout; + +module.exports = elesfn; + +/***/ }), +/* 67 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var is = __webpack_require__(0); + +function styleCache(key, fn, ele) { + var _p = ele._private; + var cache = _p.styleCache = _p.styleCache || {}; + var val; + + if ((val = cache[key]) != null) { + return val; + } else { + val = cache[key] = fn(ele); + + return val; + } +} + +function cacheStyleFunction(key, fn) { + return function cachedStyleFunction(ele) { + return styleCache(key, fn, ele); + }; +} + +function cachePrototypeStyleFunction(key, fn) { + var selfFn = function selfFn(ele) { + return fn.call(ele); + }; + + return function cachedPrototypeStyleFunction() { + var ele = this[0]; + + if (ele) { + return styleCache(key, selfFn, ele); + } + }; +} + +var elesfn = { + + recalculateRenderedStyle: function recalculateRenderedStyle(useCache) { + var cy = this.cy(); + var renderer = cy.renderer(); + var styleEnabled = cy.styleEnabled(); + + if (renderer && styleEnabled) { + renderer.recalculateRenderedStyle(this, useCache); + } return this; }, - makeLayout: function( options ){ + dirtyStyleCache: function dirtyStyleCache() { var cy = this.cy(); + var dirty = function dirty(ele) { + return ele._private.styleCache = {}; + }; - return cy.makeLayout( util.extend( {}, options, { - eles: this - } ) ); - } + if (cy.hasCompoundNodes()) { + var eles = void 0; -}); + eles = this.spawnSelf().merge(this.descendants()).merge(this.parents()); -// aliases: -elesfn.createLayout = elesfn.makeLayout; + eles.merge(eles.connectedEdges()); -module.exports = elesfn; + eles.forEach(dirty); + } else { + this.forEach(function (ele) { + dirty(ele); -},{"../is":83,"../promise":86,"../util":100}],29:[function(_dereq_,module,exports){ -'use strict'; + ele.connectedEdges().forEach(dirty); + }); + } -var is = _dereq_( '../is' ); - -var elesfn = ({ + return this; + }, // fully updates (recalculates) the style for the elements - updateStyle: function( notifyRenderer ){ + updateStyle: function updateStyle(notifyRenderer) { var cy = this._private.cy; - if( !cy.styleEnabled() ){ return this; } + if (!cy.styleEnabled()) { + return this; + } - if( cy._private.batchingStyle ){ + if (cy._private.batchingStyle) { var bEles = cy._private.batchStyleEles; - bEles.merge( this ); + bEles.merge(this); return this; // chaining and exit early when batching } + var hasCompounds = cy.hasCompoundNodes(); var style = cy.style(); + var updatedEles = this; + notifyRenderer = notifyRenderer || notifyRenderer === undefined ? true : false; - style.apply( this ); - - var updatedCompounds = this.updateCompoundBounds(); - var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this; - - if( notifyRenderer ){ - toNotify.rtrigger( 'style' ); // let renderer know we changed style - } else { - toNotify.trigger( 'style' ); // just fire the event + if (hasCompounds) { + // then add everything up and down for compound selector checks + updatedEles = this.spawnSelf().merge(this.descendants()).merge(this.parents()); } + + var changedEles = style.apply(updatedEles); + + changedEles.dirtyStyleCache(); + changedEles.dirtyCompoundBoundsCache(); + + if (notifyRenderer) { + changedEles.emitAndNotify('style'); // let renderer know we changed style + } else { + changedEles.emit('style'); // just fire the event + } + return this; // chaining }, // just update the mappers in the elements' styles; cheaper than eles.updateStyle() - updateMappers: function( notifyRenderer ){ + updateMappers: function updateMappers(notifyRenderer) { var cy = this._private.cy; var style = cy.style(); notifyRenderer = notifyRenderer || notifyRenderer === undefined ? true : false; - if( !cy.styleEnabled() ){ return this; } + if (!cy.styleEnabled()) { + return this; + } - style.updateMappers( this ); + var changedEles = style.updateMappers(this); - var updatedCompounds = this.updateCompoundBounds(); - var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this; + changedEles.dirtyStyleCache(); + changedEles.dirtyCompoundBoundsCache(); - if( notifyRenderer ){ - toNotify.rtrigger( 'style' ); // let renderer know we changed style + if (notifyRenderer) { + changedEles.emitAndNotify('style'); // let renderer know we changed style } else { - toNotify.trigger( 'style' ); // just fire the event + changedEles.emit('style'); // just fire the event } return this; // chaining }, // get the internal parsed style object for the specified property - parsedStyle: function( property ){ + parsedStyle: function parsedStyle(property) { var ele = this[0]; - if( !ele.cy().styleEnabled() ){ return; } + var cy = ele.cy(); - if( ele ){ - return ele._private.style[ property ] || ele.cy().style().getDefaultProperty( property ); + if (!cy.styleEnabled()) { + return; + } + + if (ele) { + return ele._private.style[property] || cy.style().getDefaultProperty(property); + } + }, + + numericStyle: function numericStyle(property) { + var ele = this[0]; + + if (!ele.cy().styleEnabled()) { + return; + } + + if (ele) { + var pstyle = ele.pstyle(property); + + return pstyle.pfValue !== undefined ? pstyle.pfValue : pstyle.value; + } + }, + + numericStyleUnits: function numericStyleUnits(property) { + var ele = this[0]; + + if (!ele.cy().styleEnabled()) { + return; + } + + if (ele) { + return ele.pstyle(property).units; } }, // get the specified css property as a rendered value (i.e. on-screen value) // or get the whole rendered style if no property specified (NB doesn't allow setting) - renderedStyle: function( property ){ + renderedStyle: function renderedStyle(property) { var cy = this.cy(); - if( !cy.styleEnabled() ){ return this; } + if (!cy.styleEnabled()) { + return this; + } var ele = this[0]; - if( ele ){ - var renstyle = ele.cy().style().getRenderedStyle( ele ); - - if( property === undefined ){ - return renstyle; - } else { - return renstyle[ property ]; - } + if (ele) { + return cy.style().getRenderedStyle(ele, property); } }, // read the calculated css style of the element or override the style (via a bypass) - style: function( name, value ){ + style: function style(name, value) { var cy = this.cy(); - if( !cy.styleEnabled() ){ return this; } + if (!cy.styleEnabled()) { + return this; + } var updateTransitions = false; var style = cy.style(); - if( is.plainObject( name ) ){ // then extend the bypass + if (is.plainObject(name)) { + // then extend the bypass var props = name; - style.applyBypass( this, props, updateTransitions ); + style.applyBypass(this, props, updateTransitions); - var updatedCompounds = this.updateCompoundBounds(); - var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this; - toNotify.rtrigger( 'style' ); // let the renderer know we've updated style + this.dirtyStyleCache(); + this.dirtyCompoundBoundsCache(); - } else if( is.string( name ) ){ + this.emitAndNotify('style'); // let the renderer know we've updated style + } else if (is.string(name)) { - if( value === undefined ){ // then get the property from the style + if (value === undefined) { + // then get the property from the style var ele = this[0]; - if( ele ){ - return style.getStylePropertyValue( ele, name ); - } else { // empty collection => can't get any value + if (ele) { + return style.getStylePropertyValue(ele, name); + } else { + // empty collection => can't get any value return; } + } else { + // then set the bypass with the property value + style.applyBypass(this, name, value, updateTransitions); - } else { // then set the bypass with the property value - style.applyBypass( this, name, value, updateTransitions ); + this.dirtyStyleCache(); + this.dirtyCompoundBoundsCache(); - var updatedCompounds = this.updateCompoundBounds(); - var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this; - toNotify.rtrigger( 'style' ); // let the renderer know we've updated style + this.emitAndNotify('style'); // let the renderer know we've updated style } + } else if (name === undefined) { + var _ele = this[0]; - } else if( name === undefined ){ - var ele = this[0]; - - if( ele ){ - return style.getRawStyle( ele ); - } else { // empty collection => can't get any value + if (_ele) { + return style.getRawStyle(_ele); + } else { + // empty collection => can't get any value return; } } @@ -5193,118 +12378,74 @@ var elesfn = ({ return this; // chaining }, - removeStyle: function( names ){ + removeStyle: function removeStyle(names) { var cy = this.cy(); - if( !cy.styleEnabled() ){ return this; } + if (!cy.styleEnabled()) { + return this; + } var updateTransitions = false; var style = cy.style(); var eles = this; - if( names === undefined ){ - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[ i ]; + if (names === undefined) { + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; - style.removeAllBypasses( ele, updateTransitions ); + style.removeAllBypasses(ele, updateTransitions); } } else { - names = names.split( /\s+/ ); + names = names.split(/\s+/); - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[ i ]; + for (var _i = 0; _i < eles.length; _i++) { + var _ele2 = eles[_i]; - style.removeBypasses( ele, names, updateTransitions ); + style.removeBypasses(_ele2, names, updateTransitions); } } - var updatedCompounds = this.updateCompoundBounds(); - var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this; - toNotify.rtrigger( 'style' ); // let the renderer know we've updated style + this.dirtyStyleCache(); + this.dirtyCompoundBoundsCache(); + + this.emitAndNotify('style'); // let the renderer know we've updated style return this; // chaining }, - show: function(){ - this.css( 'display', 'element' ); + show: function show() { + this.css('display', 'element'); return this; // chaining }, - hide: function(){ - this.css( 'display', 'none' ); + hide: function hide() { + this.css('display', 'none'); return this; // chaining }, - visible: function(){ + effectiveOpacity: function effectiveOpacity() { var cy = this.cy(); - if( !cy.styleEnabled() ){ return true; } - - var ele = this[0]; - var hasCompoundNodes = cy.hasCompoundNodes(); - - if( ele ){ - if( - ele.pstyle( 'visibility' ).value !== 'visible' - || ele.pstyle( 'display' ).value !== 'element' - ){ - return false; - } - - if( ele._private.group === 'nodes' ){ - if( !hasCompoundNodes ){ return true; } - - var parents = ele._private.data.parent ? ele.parents() : null; - - if( parents ){ - for( var i = 0; i < parents.length; i++ ){ - var parent = parents[ i ]; - var pVis = parent.pstyle( 'visibility' ).value; - var pDis = parent.pstyle( 'display' ).value; - - if( pVis !== 'visible' || pDis !== 'element' ){ - return false; - } - } - } - - return true; - } else { - var src = ele._private.source; - var tgt = ele._private.target; - - return src.visible() && tgt.visible(); - } - + if (!cy.styleEnabled()) { + return 1; } - }, - - hidden: function(){ - var ele = this[0]; - - if( ele ){ - return !ele.visible(); - } - }, - - effectiveOpacity: function(){ - var cy = this.cy(); - if( !cy.styleEnabled() ){ return 1; } var hasCompoundNodes = cy.hasCompoundNodes(); var ele = this[0]; - if( ele ){ + if (ele) { var _p = ele._private; - var parentOpacity = ele.pstyle( 'opacity' ).value; + var parentOpacity = ele.pstyle('opacity').value; - if( !hasCompoundNodes ){ return parentOpacity; } + if (!hasCompoundNodes) { + return parentOpacity; + } var parents = !_p.data.parent ? null : ele.parents(); - if( parents ){ - for( var i = 0; i < parents.length; i++ ){ - var parent = parents[ i ]; - var opacity = parent.pstyle( 'opacity' ).value; + if (parents) { + for (var i = 0; i < parents.length; i++) { + var parent = parents[i]; + var opacity = parent.pstyle('opacity').value; parentOpacity = opacity * parentOpacity; } @@ -5314,33 +12455,135 @@ var elesfn = ({ } }, - transparent: function(){ + transparent: function transparent() { var cy = this.cy(); - if( !cy.styleEnabled() ){ return false; } + if (!cy.styleEnabled()) { + return false; + } var ele = this[0]; var hasCompoundNodes = ele.cy().hasCompoundNodes(); - if( ele ){ - if( !hasCompoundNodes ){ - return ele.pstyle( 'opacity' ).value === 0; + if (ele) { + if (!hasCompoundNodes) { + return ele.pstyle('opacity').value === 0; } else { return ele.effectiveOpacity() === 0; } } }, - backgrounding: function(){ + backgrounding: function backgrounding() { var cy = this.cy(); - if( !cy.styleEnabled() ){ return false; } + if (!cy.styleEnabled()) { + return false; + } var ele = this[0]; return ele._private.backgrounding ? true : false; } +}; + +function checkCompound(ele, parentOk) { + var _p = ele._private; + var parents = _p.data.parent ? ele.parents() : null; + + if (parents) { + for (var i = 0; i < parents.length; i++) { + var parent = parents[i]; + + if (!parentOk(parent)) { + return false; + } + } + } + + return true; +} + +function defineDerivedStateFunction(specs) { + var ok = specs.ok; + var edgeOkViaNode = specs.edgeOkViaNode || specs.ok; + var parentOk = specs.parentOk || specs.ok; + + return function () { + var cy = this.cy(); + if (!cy.styleEnabled()) { + return true; + } + + var ele = this[0]; + var hasCompoundNodes = cy.hasCompoundNodes(); + + if (ele) { + var _p = ele._private; + + if (!ok(ele)) { + return false; + } + + if (ele.isNode()) { + return !hasCompoundNodes || checkCompound(ele, parentOk); + } else { + var src = _p.source; + var tgt = _p.target; + + return edgeOkViaNode(src) && (!hasCompoundNodes || checkCompound(src, edgeOkViaNode)) && (src === tgt || edgeOkViaNode(tgt) && (!hasCompoundNodes || checkCompound(tgt, edgeOkViaNode))); + } + } + }; +} + +var eleTakesUpSpace = cacheStyleFunction('eleTakesUpSpace', function (ele) { + return ele.pstyle('display').value === 'element' && ele.width() !== 0 && (ele.isNode() ? ele.height() !== 0 : true); }); +elesfn.takesUpSpace = cachePrototypeStyleFunction('takesUpSpace', defineDerivedStateFunction({ + ok: eleTakesUpSpace +})); + +var eleInteractive = cacheStyleFunction('eleInteractive', function (ele) { + return ele.pstyle('events').value === 'yes' && ele.pstyle('visibility').value === 'visible' && eleTakesUpSpace(ele); +}); + +var parentInteractive = cacheStyleFunction('parentInteractive', function (parent) { + return parent.pstyle('visibility').value === 'visible' && eleTakesUpSpace(parent); +}); + +elesfn.interactive = cachePrototypeStyleFunction('interactive', defineDerivedStateFunction({ + ok: eleInteractive, + parentOk: parentInteractive, + edgeOkViaNode: eleTakesUpSpace +})); + +elesfn.noninteractive = function () { + var ele = this[0]; + + if (ele) { + return !ele.interactive(); + } +}; + +var eleVisible = cacheStyleFunction('eleVisible', function (ele) { + return ele.pstyle('visibility').value === 'visible' && ele.pstyle('opacity').pfValue !== 0 && eleTakesUpSpace(ele); +}); + +var edgeVisibleViaNode = eleTakesUpSpace; + +elesfn.visible = cachePrototypeStyleFunction('visible', defineDerivedStateFunction({ + ok: eleVisible, + edgeOkViaNode: edgeVisibleViaNode +})); + +elesfn.hidden = function () { + var ele = this[0]; + + if (ele) { + return !ele.visible(); + } +}; elesfn.bypass = elesfn.css = elesfn.style; elesfn.renderedCss = elesfn.renderedStyle; @@ -5349,192 +12592,202 @@ elesfn.pstyle = elesfn.parsedStyle; module.exports = elesfn; -},{"../is":83}],30:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 68 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + var elesfn = {}; -function defineSwitchFunction( params ){ - return function(){ +function defineSwitchFunction(params) { + return function () { var args = arguments; var changedEles = []; // e.g. cy.nodes().select( data, handler ) - if( args.length === 2 ){ + if (args.length === 2) { var data = args[0]; var handler = args[1]; - this.on( params.event, data, handler ); + this.on(params.event, data, handler); } // e.g. cy.nodes().select( handler ) - else if( args.length === 1 ){ - var handler = args[0]; - this.on( params.event, handler ); - } - - // e.g. cy.nodes().select() - else if( args.length === 0 ){ - for( var i = 0; i < this.length; i++ ){ - var ele = this[ i ]; - var able = !params.ableField || ele._private[ params.ableField ]; - var changed = ele._private[ params.field ] != params.value; - - if( params.overrideAble ){ - var overrideAble = params.overrideAble( ele ); - - if( overrideAble !== undefined ){ - able = overrideAble; - - if( !overrideAble ){ return this; } // to save cycles assume not able for all on override - } - } - - if( able ){ - ele._private[ params.field ] = params.value; - - if( changed ){ - changedEles.push( ele ); - } - } + else if (args.length === 1) { + var _handler = args[0]; + this.on(params.event, _handler); } - var changedColl = this.spawn( changedEles ); - changedColl.updateStyle(); // change of state => possible change of style - changedColl.trigger( params.event ); - } + // e.g. cy.nodes().select() + else if (args.length === 0) { + for (var i = 0; i < this.length; i++) { + var ele = this[i]; + var able = !params.ableField || ele._private[params.ableField]; + var changed = ele._private[params.field] != params.value; + + if (params.overrideAble) { + var overrideAble = params.overrideAble(ele); + + if (overrideAble !== undefined) { + able = overrideAble; + + if (!overrideAble) { + return this; + } // to save cycles assume not able for all on override + } + } + + if (able) { + ele._private[params.field] = params.value; + + if (changed) { + changedEles.push(ele); + } + } + } + + var changedColl = this.spawn(changedEles); + changedColl.updateStyle(); // change of state => possible change of style + changedColl.emit(params.event); + } return this; }; } -function defineSwitchSet( params ){ - elesfn[ params.field ] = function(){ +function defineSwitchSet(params) { + elesfn[params.field] = function () { var ele = this[0]; - if( ele ){ - if( params.overrideField ){ - var val = params.overrideField( ele ); + if (ele) { + if (params.overrideField) { + var val = params.overrideField(ele); - if( val !== undefined ){ + if (val !== undefined) { return val; } } - return ele._private[ params.field ]; + return ele._private[params.field]; } }; - elesfn[ params.on ] = defineSwitchFunction( { + elesfn[params.on] = defineSwitchFunction({ event: params.on, field: params.field, ableField: params.ableField, overrideAble: params.overrideAble, value: true - } ); + }); - elesfn[ params.off ] = defineSwitchFunction( { + elesfn[params.off] = defineSwitchFunction({ event: params.off, field: params.field, ableField: params.ableField, overrideAble: params.overrideAble, value: false - } ); + }); } -defineSwitchSet( { +defineSwitchSet({ field: 'locked', - overrideField: function( ele ){ + overrideField: function overrideField(ele) { return ele.cy().autolock() ? true : undefined; }, on: 'lock', off: 'unlock' -} ); +}); -defineSwitchSet( { +defineSwitchSet({ field: 'grabbable', - overrideField: function( ele ){ + overrideField: function overrideField(ele) { return ele.cy().autoungrabify() ? false : undefined; }, on: 'grabify', off: 'ungrabify' -} ); +}); -defineSwitchSet( { +defineSwitchSet({ field: 'selected', ableField: 'selectable', - overrideAble: function( ele ){ + overrideAble: function overrideAble(ele) { return ele.cy().autounselectify() ? false : undefined; }, on: 'select', off: 'unselect' -} ); +}); -defineSwitchSet( { +defineSwitchSet({ field: 'selectable', - overrideField: function( ele ){ + overrideField: function overrideField(ele) { return ele.cy().autounselectify() ? false : undefined; }, on: 'selectify', off: 'unselectify' -} ); +}); elesfn.deselect = elesfn.unselect; -elesfn.grabbed = function(){ +elesfn.grabbed = function () { var ele = this[0]; - if( ele ){ + if (ele) { return ele._private.grabbed; } }; -defineSwitchSet( { +defineSwitchSet({ field: 'active', on: 'activate', off: 'unactivate' -} ); +}); -elesfn.inactive = function(){ +elesfn.inactive = function () { var ele = this[0]; - if( ele ){ + if (ele) { return !ele._private.active; } }; module.exports = elesfn; -},{}],31:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 69 */ +/***/ (function(module, exports, __webpack_require__) { -var util = _dereq_( '../util' ); -var is = _dereq_( '../is' ); +"use strict"; + + +var util = __webpack_require__(1); +var is = __webpack_require__(0); var elesfn = {}; -var cache = function( fn, name ){ - return function traversalCache( arg1, arg2, arg3, arg4 ){ +var cache = function cache(fn, name) { + return function traversalCache(arg1, arg2, arg3, arg4) { var selectorOrEles = arg1; var eles = this; - var key; + var key = void 0; - if( selectorOrEles == null ){ + if (selectorOrEles == null) { key = 'null'; - } else if( is.elementOrCollection( selectorOrEles ) && selectorOrEles.length === 1 ){ + } else if (is.elementOrCollection(selectorOrEles) && selectorOrEles.length === 1) { key = '#' + selectorOrEles.id(); } - if( eles.length === 1 && key ){ + if (eles.length === 1 && key) { var _p = eles[0]._private; var tch = _p.traversalCache = _p.traversalCache || {}; - var ch = tch[ name ] = tch[ name ] || {}; - var cacheHit = ch[ key ]; + var ch = tch[name] = tch[name] || {}; + var cacheHit = ch[key]; - if( cacheHit ){ + if (cacheHit) { return cacheHit; } else { - return ( ch[ key ] = fn.call( eles, arg1, arg2, arg3, arg4 ) ); + return ch[key] = fn.call(eles, arg1, arg2, arg3, arg4); } } else { - return fn.call( eles, arg1, arg2, arg3, arg4 ); + return fn.call(eles, arg1, arg2, arg3, arg4); } }; }; @@ -5542,106 +12795,115 @@ var cache = function( fn, name ){ // DAG functions //////////////// -var defineDagExtremity = function( params ){ - return function dagExtremityImpl( selector ){ +var defineDagExtremity = function defineDagExtremity(params) { + return function dagExtremityImpl(selector) { var eles = this; var ret = []; - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[ i ]; - if( !ele.isNode() ){ + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; + if (!ele.isNode()) { continue; } var disqualified = false; var edges = ele.connectedEdges(); - for( var j = 0; j < edges.length; j++ ){ + for (var j = 0; j < edges.length; j++) { var edge = edges[j]; var src = edge.source(); var tgt = edge.target(); - if( - ( params.noIncomingEdges && tgt === ele && src !== ele ) - || ( params.noOutgoingEdges && src === ele && tgt !== ele ) - ){ + if (params.noIncomingEdges && tgt === ele && src !== ele || params.noOutgoingEdges && src === ele && tgt !== ele) { disqualified = true; break; } } - if( !disqualified ){ - ret.push( ele ); + if (!disqualified) { + ret.push(ele); } } - return this.spawn( ret, { unique: true } ).filter( selector ); + return this.spawn(ret, { unique: true }).filter(selector); }; }; -var defineDagOneHop = function( params ){ - return function( selector ){ +var defineDagOneHop = function defineDagOneHop(params) { + return function (selector) { var eles = this; var oEles = []; - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[ i ]; + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; - if( !ele.isNode() ){ continue; } + if (!ele.isNode()) { + continue; + } var edges = ele.connectedEdges(); - for( var j = 0; j < edges.length; j++ ){ - var edge = edges[ j ]; + for (var j = 0; j < edges.length; j++) { + var edge = edges[j]; var src = edge.source(); var tgt = edge.target(); - if( params.outgoing && src === ele ){ - oEles.push( edge ); - oEles.push( tgt ); - } else if( params.incoming && tgt === ele ){ - oEles.push( edge ); - oEles.push( src ); + if (params.outgoing && src === ele) { + oEles.push(edge); + oEles.push(tgt); + } else if (params.incoming && tgt === ele) { + oEles.push(edge); + oEles.push(src); } } } - return this.spawn( oEles, { unique: true } ).filter( selector ); + return this.spawn(oEles, { unique: true }).filter(selector); }; }; -var defineDagAllHops = function( params ){ - return function( selector ){ +var defineDagAllHops = function defineDagAllHops(params) { + return function (selector) { var eles = this; var sEles = []; var sElesIds = {}; - for( ;; ){ + for (;;) { var next = params.outgoing ? eles.outgoers() : eles.incomers(); - if( next.length === 0 ){ break; } // done if none left + if (next.length === 0) { + break; + } // done if none left var newNext = false; - for( var i = 0; i < next.length; i++ ){ - var n = next[ i ]; + for (var i = 0; i < next.length; i++) { + var n = next[i]; var nid = n.id(); - if( !sElesIds[ nid ] ){ - sElesIds[ nid ] = true; - sEles.push( n ); + if (!sElesIds[nid]) { + sElesIds[nid] = true; + sEles.push(n); newNext = true; } } - if( !newNext ){ break; } // done if touched all outgoers already + if (!newNext) { + break; + } // done if touched all outgoers already eles = next; } - return this.spawn( sEles, { unique: true } ).filter( selector ); + return this.spawn(sEles, { unique: true }).filter(selector); }; }; -util.extend( elesfn, { +elesfn.clearTraversalCache = function () { + for (var i = 0; i < this.length; i++) { + this[i]._private.traversalCache = null; + } +}; + +util.extend(elesfn, { // get the root nodes in the DAG roots: defineDagExtremity({ noIncomingEdges: true }), @@ -5650,61 +12912,60 @@ util.extend( elesfn, { // normally called children in graph theory // these nodes =edges=> outgoing nodes - outgoers: cache( defineDagOneHop({ outgoing: true }) , 'outgoers' ), + outgoers: cache(defineDagOneHop({ outgoing: true }), 'outgoers'), // aka DAG descendants successors: defineDagAllHops({ outgoing: true }), // normally called parents in graph theory // these nodes <=edges= incoming nodes - incomers: cache( defineDagOneHop({ incoming: true }), 'incomers' ), + incomers: cache(defineDagOneHop({ incoming: true }), 'incomers'), // aka DAG ancestors predecessors: defineDagAllHops({ incoming: true }) -} ); - +}); // Neighbourhood functions ////////////////////////// -util.extend( elesfn, { - neighborhood: cache(function( selector ){ +util.extend(elesfn, { + neighborhood: cache(function (selector) { var elements = []; var nodes = this.nodes(); - for( var i = 0; i < nodes.length; i++ ){ // for all nodes - var node = nodes[ i ]; + for (var i = 0; i < nodes.length; i++) { + // for all nodes + var node = nodes[i]; var connectedEdges = node.connectedEdges(); // for each connected edge, add the edge and the other node - for( var j = 0; j < connectedEdges.length; j++ ){ - var edge = connectedEdges[ j ]; + for (var j = 0; j < connectedEdges.length; j++) { + var edge = connectedEdges[j]; var src = edge.source(); var tgt = edge.target(); var otherNode = node === src ? tgt : src; // need check in case of loop - if( otherNode.length > 0 ){ - elements.push( otherNode[0] ); // add node 1 hop away + if (otherNode.length > 0) { + elements.push(otherNode[0]); // add node 1 hop away } // add connected edge - elements.push( edge[0] ); + elements.push(edge[0]); } - } - return ( this.spawn( elements, { unique: true } ) ).filter( selector ); + return this.spawn(elements, { unique: true }).filter(selector); }, 'neighborhood'), - closedNeighborhood: function( selector ){ - return this.neighborhood().add( this ).filter( selector ); + closedNeighborhood: function closedNeighborhood(selector) { + return this.neighborhood().add(this).filter(selector); }, - openNeighborhood: function( selector ){ - return this.neighborhood( selector ); + openNeighborhood: function openNeighborhood(selector) { + return this.neighborhood(selector); } -} ); +}); // aliases elesfn.neighbourhood = elesfn.neighborhood; @@ -5714,160 +12975,168 @@ elesfn.openNeighbourhood = elesfn.openNeighborhood; // Edge functions ///////////////// -util.extend( elesfn, { - source: cache(function sourceImpl( selector ){ +util.extend(elesfn, { + source: cache(function sourceImpl(selector) { var ele = this[0]; - var src; + var src = void 0; - if( ele ){ + if (ele) { src = ele._private.source || ele.cy().collection(); } - return src && selector ? src.filter( selector ) : src; + return src && selector ? src.filter(selector) : src; }, 'source'), - target: cache(function targetImpl( selector ){ + target: cache(function targetImpl(selector) { var ele = this[0]; - var tgt; + var tgt = void 0; - if( ele ){ + if (ele) { tgt = ele._private.target || ele.cy().collection(); } - return tgt && selector ? tgt.filter( selector ) : tgt; + return tgt && selector ? tgt.filter(selector) : tgt; }, 'target'), - sources: defineSourceFunction( { + sources: defineSourceFunction({ attr: 'source' - } ), + }), - targets: defineSourceFunction( { + targets: defineSourceFunction({ attr: 'target' - } ) -} ); + }) +}); -function defineSourceFunction( params ){ - return function sourceImpl( selector ){ +function defineSourceFunction(params) { + return function sourceImpl(selector) { var sources = []; - for( var i = 0; i < this.length; i++ ){ - var ele = this[ i ]; - var src = ele._private[ params.attr ]; + for (var i = 0; i < this.length; i++) { + var ele = this[i]; + var src = ele._private[params.attr]; - if( src ){ - sources.push( src ); + if (src) { + sources.push(src); } } - return this.spawn( sources, { unique: true } ).filter( selector ); + return this.spawn(sources, { unique: true }).filter(selector); }; } -util.extend( elesfn, { - edgesWith: cache( defineEdgesWithFunction(), 'edgesWith', true ), +util.extend(elesfn, { + edgesWith: cache(defineEdgesWithFunction(), 'edgesWith'), - edgesTo: cache( defineEdgesWithFunction( { + edgesTo: cache(defineEdgesWithFunction({ thisIsSrc: true - } ), 'edgesTo', true ) -} ); + }), 'edgesTo') +}); -function defineEdgesWithFunction( params ){ +function defineEdgesWithFunction(params) { - return function edgesWithImpl( otherNodes ){ + return function edgesWithImpl(otherNodes) { var elements = []; var cy = this._private.cy; var p = params || {}; // get elements if a selector is specified - if( is.string( otherNodes ) ){ - otherNodes = cy.$( otherNodes ); + if (is.string(otherNodes)) { + otherNodes = cy.$(otherNodes); } - var thisIds = this._private.ids; - var otherIds = otherNodes._private.ids; + for (var h = 0; h < otherNodes.length; h++) { + var edges = otherNodes[h]._private.edges; - for( var h = 0; h < otherNodes.length; h++ ){ - var edges = otherNodes[ h ]._private.edges; - - for( var i = 0; i < edges.length; i++ ){ - var edge = edges[ i ]; + for (var i = 0; i < edges.length; i++) { + var edge = edges[i]; var edgeData = edge._private.data; - var thisToOther = thisIds[ edgeData.source ] && otherIds[ edgeData.target ]; - var otherToThis = otherIds[ edgeData.source ] && thisIds[ edgeData.target ]; + var thisToOther = this.hasElementWithId(edgeData.source) && otherNodes.hasElementWithId(edgeData.target); + var otherToThis = otherNodes.hasElementWithId(edgeData.source) && this.hasElementWithId(edgeData.target); var edgeConnectsThisAndOther = thisToOther || otherToThis; - if( !edgeConnectsThisAndOther ){ continue; } - - if( p.thisIsSrc || p.thisIsTgt ){ - if( p.thisIsSrc && !thisToOther ){ continue; } - - if( p.thisIsTgt && !otherToThis ){ continue; } + if (!edgeConnectsThisAndOther) { + continue; } - elements.push( edge ); + if (p.thisIsSrc || p.thisIsTgt) { + if (p.thisIsSrc && !thisToOther) { + continue; + } + + if (p.thisIsTgt && !otherToThis) { + continue; + } + } + + elements.push(edge); } } - return this.spawn( elements, { unique: true } ); + return this.spawn(elements, { unique: true }); }; } -util.extend( elesfn, { - connectedEdges: cache(function( selector ){ +util.extend(elesfn, { + connectedEdges: cache(function (selector) { var retEles = []; var eles = this; - for( var i = 0; i < eles.length; i++ ){ - var node = eles[ i ]; - if( !node.isNode() ){ continue; } + for (var i = 0; i < eles.length; i++) { + var node = eles[i]; + if (!node.isNode()) { + continue; + } var edges = node._private.edges; - for( var j = 0; j < edges.length; j++ ){ - var edge = edges[ j ]; - retEles.push( edge ); + for (var j = 0; j < edges.length; j++) { + var edge = edges[j]; + retEles.push(edge); } } - return this.spawn( retEles, { unique: true } ).filter( selector ); + return this.spawn(retEles, { unique: true }).filter(selector); }, 'connectedEdges'), - connectedNodes: cache(function( selector ){ + connectedNodes: cache(function (selector) { var retEles = []; var eles = this; - for( var i = 0; i < eles.length; i++ ){ - var edge = eles[ i ]; - if( !edge.isEdge() ){ continue; } + for (var i = 0; i < eles.length; i++) { + var edge = eles[i]; + if (!edge.isEdge()) { + continue; + } - retEles.push( edge.source()[0] ); - retEles.push( edge.target()[0] ); + retEles.push(edge.source()[0]); + retEles.push(edge.target()[0]); } - return this.spawn( retEles, { unique: true } ).filter( selector ); + return this.spawn(retEles, { unique: true }).filter(selector); }, 'connectedNodes'), - parallelEdges: cache( defineParallelEdgesFunction(), 'parallelEdges' ), + parallelEdges: cache(defineParallelEdgesFunction(), 'parallelEdges'), - codirectedEdges: cache( defineParallelEdgesFunction( { + codirectedEdges: cache(defineParallelEdgesFunction({ codirected: true - } ), 'codirectedEdges' ) -} ); + }), 'codirectedEdges') +}); -function defineParallelEdgesFunction( params ){ +function defineParallelEdgesFunction(params) { var defaults = { codirected: false }; - params = util.extend( {}, defaults, params ); + params = util.extend({}, defaults, params); - return function parallelEdgesImpl( selector ){ // micro-optimised for renderer + return function parallelEdgesImpl(selector) { + // micro-optimised for renderer var elements = []; var edges = this.edges(); var p = params; // look at all the edges in the collection - for( var i = 0; i < edges.length; i++ ){ - var edge1 = edges[ i ]; + for (var i = 0; i < edges.length; i++) { + var edge1 = edges[i]; var edge1_p = edge1._private; var src1 = edge1_p.source; var srcid1 = src1._private.data.id; @@ -5875,8 +13144,8 @@ function defineParallelEdgesFunction( params ){ var srcEdges1 = src1._private.edges; // look at edges connected to the src node of this edge - for( var j = 0; j < srcEdges1.length; j++ ){ - var edge2 = srcEdges1[ j ]; + for (var j = 0; j < srcEdges1.length; j++) { + var edge2 = srcEdges1[j]; var edge2data = edge2._private.data; var tgtid2 = edge2data.target; var srcid2 = edge2data.source; @@ -5884,248 +13153,172 @@ function defineParallelEdgesFunction( params ){ var codirected = tgtid2 === tgtid1 && srcid2 === srcid1; var oppdirected = srcid1 === tgtid2 && tgtid1 === srcid2; - if( (p.codirected && codirected) || (!p.codirected && (codirected || oppdirected)) ){ - elements.push( edge2 ); + if (p.codirected && codirected || !p.codirected && (codirected || oppdirected)) { + elements.push(edge2); } } } - return this.spawn( elements, { unique: true } ).filter( selector ); + return this.spawn(elements, { unique: true }).filter(selector); }; - } // Misc functions ///////////////// -util.extend( elesfn, { - components: function(){ +util.extend(elesfn, { + components: function components() { var self = this; var cy = self.cy(); var visited = self.spawn(); var unvisited = self.nodes().spawnSelf(); var components = []; - var visitInComponent = function( node, component ){ - visited.merge( node ); - unvisited.unmerge( node ); - component.merge( node ); + var visitInComponent = function visitInComponent(node, component) { + visited.merge(node); + unvisited.unmerge(node); + component.merge(node); }; - if( unvisited.empty() ){ return self.spawn(); } + if (unvisited.empty()) { + return self.spawn(); + } - do { + var _loop = function _loop() { var component = cy.collection(); - components.push( component ); + components.push(component); var root = unvisited[0]; - visitInComponent( root, component ); + visitInComponent(root, component); self.bfs({ directed: false, roots: root, - visit: function( i, depth, v, e, u ){ - visitInComponent( v, component ); + visit: function visit(v, e, u, i, depth) { + visitInComponent(v, component); } - } ); + }); + }; - } while( unvisited.length > 0 ); + do { + _loop(); + } while (unvisited.length > 0); - return components.map(function( component ){ - var connectedEdges = component.connectedEdges().stdFilter(function( edge ){ - return component.anySame( edge.source() ) && component.anySame( edge.target() ); + return components.map(function (component) { + var connectedEdges = component.connectedEdges().stdFilter(function (edge) { + return component.anySame(edge.source()) && component.anySame(edge.target()); }); - return component.union( connectedEdges ); + return component.union(connectedEdges); }); } -} ); +}); module.exports = elesfn; -},{"../is":83,"../util":100}],32:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 70 */ +/***/ (function(module, exports, __webpack_require__) { -var zIndexSort = function( a, b ){ - var cy = a.cy(); - var zDiff = a.pstyle( 'z-index' ).value - b.pstyle( 'z-index' ).value; - var depthA = 0; - var depthB = 0; - var hasCompoundNodes = cy.hasCompoundNodes(); - var aIsNode = a.isNode(); - var aIsEdge = !aIsNode; - var bIsNode = b.isNode(); - var bIsEdge = !bIsNode; +"use strict"; - // no need to calculate element depth if there is no compound node - if( hasCompoundNodes ){ - depthA = a.zDepth(); - depthB = b.zDepth(); - } - var depthDiff = depthA - depthB; - var sameDepth = depthDiff === 0; - - if( sameDepth ){ - - if( aIsNode && bIsEdge ){ - return 1; // 'a' is a node, it should be drawn later - - } else if( aIsEdge && bIsNode ){ - return -1; // 'a' is an edge, it should be drawn first - - } else { // both nodes or both edges - if( zDiff === 0 ){ // same z-index => compare indices in the core (order added to graph w/ last on top) - return a.poolIndex() - b.poolIndex(); - } else { - return zDiff; - } - } - - // elements on different level - } else { - return depthDiff; // deeper element should be drawn later - } - -}; - -module.exports = zIndexSort; - -},{}],33:[function(_dereq_,module,exports){ -'use strict'; - -var is = _dereq_( '../is' ); -var util = _dereq_( '../util' ); -var Collection = _dereq_( '../collection' ); -var Element = _dereq_( '../collection/element' ); +var is = __webpack_require__(0); +var util = __webpack_require__(1); +var Collection = __webpack_require__(7); +var Element = __webpack_require__(14); var corefn = { - add: function( opts ){ + add: function add(opts) { - var elements; + var elements = void 0; var cy = this; // add the elements - if( is.elementOrCollection( opts ) ){ + if (is.elementOrCollection(opts)) { var eles = opts; - if( eles._private.cy === cy ){ // same instance => just restore + if (eles._private.cy === cy) { + // same instance => just restore elements = eles.restore(); - - } else { // otherwise, copy from json + } else { + // otherwise, copy from json var jsons = []; - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[ i ]; - jsons.push( ele.json() ); + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; + jsons.push(ele.json()); } - elements = new Collection( cy, jsons ); + elements = new Collection(cy, jsons); } } // specify an array of options - else if( is.array( opts ) ){ - var jsons = opts; + else if (is.array(opts)) { + var _jsons = opts; - elements = new Collection( cy, jsons ); - } - - // specify via opts.nodes and opts.edges - else if( is.plainObject( opts ) && (is.array( opts.nodes ) || is.array( opts.edges )) ){ - var elesByGroup = opts; - var jsons = []; - - var grs = [ 'nodes', 'edges' ]; - for( var i = 0, il = grs.length; i < il; i++ ){ - var group = grs[ i ]; - var elesArray = elesByGroup[ group ]; - - if( is.array( elesArray ) ){ - - for( var j = 0, jl = elesArray.length; j < jl; j++ ){ - var json = util.extend( { group: group }, elesArray[ j ] ); - - jsons.push( json ); - } - } + elements = new Collection(cy, _jsons); } - elements = new Collection( cy, jsons ); - } + // specify via opts.nodes and opts.edges + else if (is.plainObject(opts) && (is.array(opts.nodes) || is.array(opts.edges))) { + var elesByGroup = opts; + var _jsons2 = []; - // specify options for one element - else { - var json = opts; - elements = (new Element( cy, json )).collection(); - } + var grs = ['nodes', 'edges']; + for (var _i = 0, il = grs.length; _i < il; _i++) { + var group = grs[_i]; + var elesArray = elesByGroup[group]; + + if (is.array(elesArray)) { + + for (var j = 0, jl = elesArray.length; j < jl; j++) { + var json = util.extend({ group: group }, elesArray[j]); + + _jsons2.push(json); + } + } + } + + elements = new Collection(cy, _jsons2); + } + + // specify options for one element + else { + var _json = opts; + elements = new Element(cy, _json).collection(); + } return elements; }, - remove: function( collection ){ - if( is.elementOrCollection( collection ) ){ + remove: function remove(collection) { + if (is.elementOrCollection(collection)) { // already have right ref - } else if( is.string( collection ) ){ + } else if (is.string(collection)) { var selector = collection; - collection = this.$( selector ); + collection = this.$(selector); } return collection.remove(); - }, - - load: function( elements, onload, ondone ){ - var cy = this; - - cy.notifications( false ); - - // remove old elements - var oldEles = cy.mutableElements(); - if( oldEles.length > 0 ){ - oldEles.remove(); - } - - if( elements != null ){ - if( is.plainObject( elements ) || is.array( elements ) ){ - cy.add( elements ); - } - } - - cy.one( 'layoutready', function( e ){ - cy.notifications( true ); - cy.trigger( e ); // we missed this event by turning notifications off, so pass it on - - cy.notify( { - type: 'load', - eles: cy.mutableElements() - } ); - - cy.one( 'load', onload ); - cy.trigger( 'load' ); - } ).one( 'layoutstop', function(){ - cy.one( 'done', ondone ); - cy.trigger( 'done' ); - } ); - - var layoutOpts = util.extend( {}, cy._private.options.layout ); - layoutOpts.eles = cy.elements(); - - cy.layout( layoutOpts ); - - return this; } }; module.exports = corefn; -},{"../collection":26,"../collection/element":22,"../is":83,"../util":100}],34:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 71 */ +/***/ (function(module, exports, __webpack_require__) { -var define = _dereq_( '../define' ); -var util = _dereq_( '../util' ); -var is = _dereq_( '../is' ); +"use strict"; -var corefn = ({ + +var define = __webpack_require__(4); +var util = __webpack_require__(1); +var stepAll = __webpack_require__(72); + +var corefn = { // pull in animation functions animate: define.animate(), @@ -6136,1140 +13329,1111 @@ var corefn = ({ delayAnimation: define.delayAnimation(), stop: define.stop(), - addToAnimationPool: function( eles ){ + addToAnimationPool: function addToAnimationPool(eles) { var cy = this; - if( !cy.styleEnabled() ){ return; } // save cycles when no style used + if (!cy.styleEnabled()) { + return; + } // save cycles when no style used - cy._private.aniEles.merge( eles ); + cy._private.aniEles.merge(eles); }, - stopAnimationLoop: function(){ + stopAnimationLoop: function stopAnimationLoop() { this._private.animationsRunning = false; }, - startAnimationLoop: function(){ + startAnimationLoop: function startAnimationLoop() { var cy = this; cy._private.animationsRunning = true; - if( !cy.styleEnabled() ){ return; } // save cycles when no style used + if (!cy.styleEnabled()) { + return; + } // save cycles when no style used // NB the animation loop will exec in headless environments if style enabled // and explicit cy.destroy() is necessary to stop the loop - function globalAnimationStep(){ - if( !cy._private.animationsRunning ){ return; } + function headlessStep() { + if (!cy._private.animationsRunning) { + return; + } - util.requestAnimationFrame( function animationStep( now ){ - handleElements( now ); - globalAnimationStep(); - } ); + util.requestAnimationFrame(function animationStep(now) { + stepAll(now, cy); + headlessStep(); + }); } var renderer = cy.renderer(); - if( renderer && renderer.beforeRender ){ // let the renderer schedule animations - renderer.beforeRender( function rendererAnimationStep( willDraw, now ){ - handleElements( now ); - }, renderer.beforeRenderPriorities.animations ); - } else { // manage the animation loop ourselves - globalAnimationStep(); // first call + if (renderer && renderer.beforeRender) { + // let the renderer schedule animations + renderer.beforeRender(function rendererAnimationStep(willDraw, now) { + stepAll(now, cy); + }, renderer.beforeRenderPriorities.animations); + } else { + // manage the animation loop ourselves + headlessStep(); // first call + } + } + +}; + +module.exports = corefn; + +/***/ }), +/* 72 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var step = __webpack_require__(73); +var startAnimation = __webpack_require__(78); + +function stepAll(now, cy) { + var eles = cy._private.aniEles; + var doneEles = []; + + function stepOne(ele, isCore) { + var _p = ele._private; + var current = _p.animation.current; + var queue = _p.animation.queue; + var ranAnis = false; + + // cancel all animations on display:none ele + if (!isCore && ele.pstyle('display').value === 'none') { + // put all current and queue animations in this tick's current list + // and empty the lists for the element + current = current.splice(0, current.length).concat(queue.splice(0, queue.length)); + + // stop all animations + for (var i = 0; i < current.length; i++) { + current[i].stop(); + } } - function handleElements( now ){ - var eles = cy._private.aniEles; - var doneEles = []; + // if nothing currently animating, get something from the queue + if (current.length === 0) { + var next = queue.shift(); - function handleElement( ele, isCore ){ - var _p = ele._private; - var current = _p.animation.current; - var queue = _p.animation.queue; - var ranAnis = false; - - // if nothing currently animating, get something from the queue - if( current.length === 0 ){ - var next = queue.shift(); - - if( next ){ - current.push( next ); - } - } - - var callbacks = function( callbacks ){ - for( var j = callbacks.length - 1; j >= 0; j-- ){ - var cb = callbacks[ j ]; - - cb(); - } - - callbacks.splice( 0, callbacks.length ); - }; - - // step and remove if done - for( var i = current.length - 1; i >= 0; i-- ){ - var ani = current[ i ]; - var ani_p = ani._private; - - if( ani_p.stopped ){ - current.splice( i, 1 ); - - ani_p.hooked = false; - ani_p.playing = false; - ani_p.started = false; - - callbacks( ani_p.frames ); - - continue; - } - - if( !ani_p.playing && !ani_p.applying ){ continue; } - - // an apply() while playing shouldn't do anything - if( ani_p.playing && ani_p.applying ){ - ani_p.applying = false; - } - - if( !ani_p.started ){ - startAnimation( ele, ani, now ); - } - - step( ele, ani, now, isCore ); - - if( is.fn( ani_p.step ) ){ - ani_p.step.call( ele, now ); - } - - if( ani_p.applying ){ - ani_p.applying = false; - } - - callbacks( ani_p.frames ); - - if( ani.completed() ){ - current.splice( i, 1 ); - - ani_p.hooked = false; - ani_p.playing = false; - ani_p.started = false; - - callbacks( ani_p.completes ); - } - - ranAnis = true; - } - - if( !isCore && current.length === 0 && queue.length === 0 ){ - doneEles.push( ele ); - } - - return ranAnis; - } // handleElement - - // handle all eles - var ranEleAni = false; - for( var e = 0; e < eles.length; e++ ){ - var ele = eles[ e ]; - var handledThisEle = handleElement( ele ); - - ranEleAni = ranEleAni || handledThisEle; - } // each element - - var ranCoreAni = handleElement( cy, true ); - - // notify renderer - if( ranEleAni || ranCoreAni ){ - if( eles.length > 0 ){ - var updatedEles = eles.updateCompoundBounds().spawnSelf().merge( eles ); - - cy.notify({ - type: 'draw', - eles: updatedEles - }); - } else { - cy.notify({ - type: 'draw' - }); - } + if (next) { + current.push(next); } - - // remove elements from list of currently animating if its queues are empty - eles.unmerge( doneEles ); - - cy.trigger('step'); - - } // handleElements - - function startAnimation( self, ani, now ){ - var isCore = is.core( self ); - var isEles = !isCore; - var ele = self; - var style = cy._private.style; - var ani_p = ani._private; - - if( isEles ){ - var pos = ele._private.position; - - ani_p.startPosition = ani_p.startPosition || { - x: pos.x, - y: pos.y - }; - - ani_p.startStyle = ani_p.startStyle || style.getAnimationStartStyle( ele, ani_p.style ); - } - - if( isCore ){ - var pan = cy._private.pan; - - ani_p.startPan = ani_p.startPan || { - x: pan.x, - y: pan.y - }; - - ani_p.startZoom = ani_p.startZoom != null ? ani_p.startZoom : cy._private.zoom; - } - - ani_p.started = true; - ani_p.startTime = now - ani_p.progress * ani_p.duration; } - function step( self, ani, now, isCore ){ - var style = cy._private.style; - var isEles = !isCore; - var _p = self._private; - var ani_p = ani._private; - var pEasing = ani_p.easing; - var startTime = ani_p.startTime; - - if( !ani_p.easingImpl ){ - - if( pEasing == null ){ // use default - ani_p.easingImpl = easings[ 'linear' ]; - - } else { // then define w/ name - var easingVals; - - if( is.string( pEasing ) ){ - var easingProp = style.parse( 'transition-timing-function', pEasing ); - - easingVals = easingProp.value; - - } else { // then assume preparsed array - easingVals = pEasing; - } - - var name, args; - - if( is.string( easingVals ) ){ - name = easingVals; - args = []; - } else { - name = easingVals[1]; - args = easingVals.slice( 2 ).map( function( n ){ return +n; } ); - } - - if( args.length > 0 ){ // create with args - if( name === 'spring' ){ - args.push( ani_p.duration ); // need duration to generate spring - } - - ani_p.easingImpl = easings[ name ].apply( null, args ); - } else { // static impl by name - ani_p.easingImpl = easings[ name ]; - } - } + var callbacks = function callbacks(_callbacks) { + for (var j = _callbacks.length - 1; j >= 0; j--) { + var cb = _callbacks[j]; + cb(); } - var easing = ani_p.easingImpl; - var percent; + _callbacks.splice(0, _callbacks.length); + }; - if( ani_p.duration === 0 ){ - percent = 1; + // step and remove if done + for (var _i = current.length - 1; _i >= 0; _i--) { + var ani = current[_i]; + var ani_p = ani._private; + + if (ani_p.stopped) { + current.splice(_i, 1); + + ani_p.hooked = false; + ani_p.playing = false; + ani_p.started = false; + + callbacks(ani_p.frames); + + continue; + } + + if (!ani_p.playing && !ani_p.applying) { + continue; + } + + // an apply() while playing shouldn't do anything + if (ani_p.playing && ani_p.applying) { + ani_p.applying = false; + } + + if (!ani_p.started) { + startAnimation(ele, ani, now, isCore); + } + + step(ele, ani, now, isCore); + + if (ani_p.applying) { + ani_p.applying = false; + } + + callbacks(ani_p.frames); + + if (ani.completed()) { + current.splice(_i, 1); + + ani_p.hooked = false; + ani_p.playing = false; + ani_p.started = false; + + callbacks(ani_p.completes); + } + + ranAnis = true; + } + + if (!isCore && current.length === 0 && queue.length === 0) { + doneEles.push(ele); + } + + return ranAnis; + } // stepElement + + // handle all eles + var ranEleAni = false; + for (var e = 0; e < eles.length; e++) { + var ele = eles[e]; + var handledThisEle = stepOne(ele); + + ranEleAni = ranEleAni || handledThisEle; + } // each element + + var ranCoreAni = stepOne(cy, true); + + // notify renderer + if (ranEleAni || ranCoreAni) { + if (eles.length > 0) { + eles.dirtyCompoundBoundsCache(); + + cy.notify({ + type: 'draw', + eles: eles + }); + } else { + cy.notify({ + type: 'draw' + }); + } + } + + // remove elements from list of currently animating if its queues are empty + eles.unmerge(doneEles); + + cy.emit('step'); +} // stepAll + +module.exports = stepAll; + +/***/ }), +/* 73 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var easings = __webpack_require__(74); +var ease = __webpack_require__(77); +var is = __webpack_require__(0); + +function step(self, ani, now, isCore) { + var isEles = !isCore; + var _p = self._private; + var ani_p = ani._private; + var pEasing = ani_p.easing; + var startTime = ani_p.startTime; + var cy = isCore ? self : self.cy(); + var style = cy.style(); + + if (!ani_p.easingImpl) { + + if (pEasing == null) { + // use default + ani_p.easingImpl = easings['linear']; + } else { + // then define w/ name + var easingVals = void 0; + + if (is.string(pEasing)) { + var easingProp = style.parse('transition-timing-function', pEasing); + + easingVals = easingProp.value; } else { - percent = (now - startTime) / ani_p.duration; + // then assume preparsed array + easingVals = pEasing; } - if( ani_p.applying ){ - percent = ani_p.progress; + var name = void 0, + args = void 0; + + if (is.string(easingVals)) { + name = easingVals; + args = []; + } else { + name = easingVals[1]; + args = easingVals.slice(2).map(function (n) { + return +n; + }); } - if( percent < 0 ){ - percent = 0; - } else if( percent > 1 ){ - percent = 1; + if (args.length > 0) { + // create with args + if (name === 'spring') { + args.push(ani_p.duration); // need duration to generate spring + } + + ani_p.easingImpl = easings[name].apply(null, args); + } else { + // static impl by name + ani_p.easingImpl = easings[name]; + } + } + } + + var easing = ani_p.easingImpl; + var percent = void 0; + + if (ani_p.duration === 0) { + percent = 1; + } else { + percent = (now - startTime) / ani_p.duration; + } + + if (ani_p.applying) { + percent = ani_p.progress; + } + + if (percent < 0) { + percent = 0; + } else if (percent > 1) { + percent = 1; + } + + if (ani_p.delay == null) { + // then update + + var startPos = ani_p.startPosition; + var endPos = ani_p.position; + + if (endPos && isEles && !self.locked()) { + var pos = self.position(); + + if (valid(startPos.x, endPos.x)) { + pos.x = ease(startPos.x, endPos.x, percent, easing); } - if( ani_p.delay == null ){ // then update - - var startPos = ani_p.startPosition; - var endPos = ani_p.position; - var pos = _p.position; - if( endPos && isEles ){ - if( valid( startPos.x, endPos.x ) ){ - pos.x = ease( startPos.x, endPos.x, percent, easing ); - } - - if( valid( startPos.y, endPos.y ) ){ - pos.y = ease( startPos.y, endPos.y, percent, easing ); - } - - self.trigger('position'); - } - - var startPan = ani_p.startPan; - var endPan = ani_p.pan; - var pan = _p.pan; - var animatingPan = endPan != null && isCore; - if( animatingPan ){ - if( valid( startPan.x, endPan.x ) ){ - pan.x = ease( startPan.x, endPan.x, percent, easing ); - } - - if( valid( startPan.y, endPan.y ) ){ - pan.y = ease( startPan.y, endPan.y, percent, easing ); - } - - self.trigger( 'pan' ); - } - - var startZoom = ani_p.startZoom; - var endZoom = ani_p.zoom; - var animatingZoom = endZoom != null && isCore; - if( animatingZoom ){ - if( valid( startZoom, endZoom ) ){ - _p.zoom = ease( startZoom, endZoom, percent, easing ); - } - - self.trigger( 'zoom' ); - } - - if( animatingPan || animatingZoom ){ - self.trigger( 'viewport' ); - } - - var props = ani_p.style; - if( props && props.length > 0 && isEles ){ - for( var i = 0; i < props.length; i++ ){ - var prop = props[ i ]; - var name = prop.name; - var end = prop; - - var start = ani_p.startStyle[ name ]; - var easedVal = ease( start, end, percent, easing ); - - style.overrideBypass( self, name, easedVal ); - } // for props - - self.trigger('style'); - - } // if - + if (valid(startPos.y, endPos.y)) { + pos.y = ease(startPos.y, endPos.y, percent, easing); } - ani_p.progress = percent; - - return percent; + self.emit('position'); } - function valid( start, end ){ - if( start == null || end == null ){ - return false; + var startPan = ani_p.startPan; + var endPan = ani_p.pan; + var pan = _p.pan; + var animatingPan = endPan != null && isCore; + if (animatingPan) { + if (valid(startPan.x, endPan.x)) { + pan.x = ease(startPan.x, endPan.x, percent, easing); } - if( is.number( start ) && is.number( end ) ){ - return true; - } else if( (start) && (end) ){ - return true; + if (valid(startPan.y, endPan.y)) { + pan.y = ease(startPan.y, endPan.y, percent, easing); } + self.emit('pan'); + } + + var startZoom = ani_p.startZoom; + var endZoom = ani_p.zoom; + var animatingZoom = endZoom != null && isCore; + if (animatingZoom) { + if (valid(startZoom, endZoom)) { + _p.zoom = ease(startZoom, endZoom, percent, easing); + } + + self.emit('zoom'); + } + + if (animatingPan || animatingZoom) { + self.emit('viewport'); + } + + var props = ani_p.style; + if (props && props.length > 0 && isEles) { + for (var i = 0; i < props.length; i++) { + var prop = props[i]; + var _name = prop.name; + var end = prop; + var start = ani_p.startStyle[_name]; + var propSpec = style.properties[start.name]; + var easedVal = ease(start, end, percent, easing, propSpec); + + style.overrideBypass(self, _name, easedVal); + } // for props + + self.emit('style'); + } // if + } + + ani_p.progress = percent; + + return percent; +} + +function valid(start, end) { + if (start == null || end == null) { + return false; + } + + if (is.number(start) && is.number(end)) { + return true; + } else if (start && end) { + return true; + } + + return false; +} + +module.exports = step; + +/***/ }), +/* 74 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var generateCubicBezier = __webpack_require__(75); +var generateSpringRK4 = __webpack_require__(76); + +var cubicBezier = function cubicBezier(t1, p1, t2, p2) { + var bezier = generateCubicBezier(t1, p1, t2, p2); + + return function (start, end, percent) { + return start + (end - start) * bezier(percent); + }; +}; + +var easings = { + 'linear': function linear(start, end, percent) { + return start + (end - start) * percent; + }, + + // default easings + 'ease': cubicBezier(0.25, 0.1, 0.25, 1), + 'ease-in': cubicBezier(0.42, 0, 1, 1), + 'ease-out': cubicBezier(0, 0, 0.58, 1), + 'ease-in-out': cubicBezier(0.42, 0, 0.58, 1), + + // sine + 'ease-in-sine': cubicBezier(0.47, 0, 0.745, 0.715), + 'ease-out-sine': cubicBezier(0.39, 0.575, 0.565, 1), + 'ease-in-out-sine': cubicBezier(0.445, 0.05, 0.55, 0.95), + + // quad + 'ease-in-quad': cubicBezier(0.55, 0.085, 0.68, 0.53), + 'ease-out-quad': cubicBezier(0.25, 0.46, 0.45, 0.94), + 'ease-in-out-quad': cubicBezier(0.455, 0.03, 0.515, 0.955), + + // cubic + 'ease-in-cubic': cubicBezier(0.55, 0.055, 0.675, 0.19), + 'ease-out-cubic': cubicBezier(0.215, 0.61, 0.355, 1), + 'ease-in-out-cubic': cubicBezier(0.645, 0.045, 0.355, 1), + + // quart + 'ease-in-quart': cubicBezier(0.895, 0.03, 0.685, 0.22), + 'ease-out-quart': cubicBezier(0.165, 0.84, 0.44, 1), + 'ease-in-out-quart': cubicBezier(0.77, 0, 0.175, 1), + + // quint + 'ease-in-quint': cubicBezier(0.755, 0.05, 0.855, 0.06), + 'ease-out-quint': cubicBezier(0.23, 1, 0.32, 1), + 'ease-in-out-quint': cubicBezier(0.86, 0, 0.07, 1), + + // expo + 'ease-in-expo': cubicBezier(0.95, 0.05, 0.795, 0.035), + 'ease-out-expo': cubicBezier(0.19, 1, 0.22, 1), + 'ease-in-out-expo': cubicBezier(1, 0, 0, 1), + + // circ + 'ease-in-circ': cubicBezier(0.6, 0.04, 0.98, 0.335), + 'ease-out-circ': cubicBezier(0.075, 0.82, 0.165, 1), + 'ease-in-out-circ': cubicBezier(0.785, 0.135, 0.15, 0.86), + + // user param easings... + + 'spring': function spring(tension, friction, duration) { + if (duration === 0) { + // can't get a spring w/ duration 0 + return easings.linear; // duration 0 => jump to end so impl doesn't matter + } + + var spring = generateSpringRK4(tension, friction, duration); + + return function (start, end, percent) { + return start + (end - start) * spring(percent); + }; + }, + + 'cubic-bezier': cubicBezier +}; + +module.exports = easings; + +/***/ }), +/* 75 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/* global Float32Array */ + +/*! Bezier curve function generator. Copyright Gaetan Renaudeau. MIT License: http://en.wikipedia.org/wiki/MIT_License */ +function generateCubicBezier(mX1, mY1, mX2, mY2) { + var NEWTON_ITERATIONS = 4, + NEWTON_MIN_SLOPE = 0.001, + SUBDIVISION_PRECISION = 0.0000001, + SUBDIVISION_MAX_ITERATIONS = 10, + kSplineTableSize = 11, + kSampleStepSize = 1.0 / (kSplineTableSize - 1.0), + float32ArraySupported = typeof Float32Array !== 'undefined'; + + /* Must contain four arguments. */ + if (arguments.length !== 4) { + return false; + } + + /* Arguments must be numbers. */ + for (var i = 0; i < 4; ++i) { + if (typeof arguments[i] !== "number" || isNaN(arguments[i]) || !isFinite(arguments[i])) { return false; } + } - // assumes p0 = 0, p3 = 1 - function evalCubicBezier( p1, p2, t ){ - var one_t = 1 - t; - var tsq = t * t; + /* X values must be in the [0, 1] range. */ + mX1 = Math.min(mX1, 1); + mX2 = Math.min(mX2, 1); + mX1 = Math.max(mX1, 0); + mX2 = Math.max(mX2, 0); - return ( 3 * one_t * one_t * t * p1 ) + ( 3 * one_t * tsq * p2 ) + tsq * t; - } + var mSampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize); - function cubicBezier( p1, p2 ){ - return function( start, end, percent ){ - return start + (end - start) * evalCubicBezier( p1, p2, percent ); - }; - } + function A(aA1, aA2) { + return 1.0 - 3.0 * aA2 + 3.0 * aA1; + } - /*! Runge-Kutta spring physics function generator. Adapted from Framer.js, copyright Koen Bok. MIT License: http://en.wikipedia.org/wiki/MIT_License */ - /* Given a tension, friction, and duration, a simulation at 60FPS will first run without a defined duration in order to calculate the full path. A second pass - then adjusts the time delta -- using the relation between actual time and duration -- to calculate the path for the duration-constrained animation. */ - var generateSpringRK4 = (function(){ - function springAccelerationForState( state ){ - return (-state.tension * state.x) - (state.friction * state.v); + function B(aA1, aA2) { + return 3.0 * aA2 - 6.0 * aA1; + } + + function C(aA1) { + return 3.0 * aA1; + } + + function calcBezier(aT, aA1, aA2) { + return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT; + } + + function getSlope(aT, aA1, aA2) { + return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1); + } + + function newtonRaphsonIterate(aX, aGuessT) { + for (var _i = 0; _i < NEWTON_ITERATIONS; ++_i) { + var currentSlope = getSlope(aGuessT, mX1, mX2); + + if (currentSlope === 0.0) { + return aGuessT; } - function springEvaluateStateWithDerivative( initialState, dt, derivative ){ - var state = { - x: initialState.x + derivative.dx * dt, - v: initialState.v + derivative.dv * dt, - tension: initialState.tension, - friction: initialState.friction - }; + var currentX = calcBezier(aGuessT, mX1, mX2) - aX; + aGuessT -= currentX / currentSlope; + } - return { dx: state.v, dv: springAccelerationForState( state ) }; + return aGuessT; + } + + function calcSampleValues() { + for (var _i2 = 0; _i2 < kSplineTableSize; ++_i2) { + mSampleValues[_i2] = calcBezier(_i2 * kSampleStepSize, mX1, mX2); + } + } + + function binarySubdivide(aX, aA, aB) { + var currentX = void 0, + currentT = void 0, + i = 0; + + do { + currentT = aA + (aB - aA) / 2.0; + currentX = calcBezier(currentT, mX1, mX2) - aX; + if (currentX > 0.0) { + aB = currentT; + } else { + aA = currentT; } + } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS); - function springIntegrateState( state, dt ){ - var a = { - dx: state.v, - dv: springAccelerationForState( state ) - }, - b = springEvaluateStateWithDerivative( state, dt * 0.5, a ), - c = springEvaluateStateWithDerivative( state, dt * 0.5, b ), - d = springEvaluateStateWithDerivative( state, dt, c ), + return currentT; + } + + function getTForX(aX) { + var intervalStart = 0.0, + currentSample = 1, + lastSample = kSplineTableSize - 1; + + for (; currentSample !== lastSample && mSampleValues[currentSample] <= aX; ++currentSample) { + intervalStart += kSampleStepSize; + } + + --currentSample; + + var dist = (aX - mSampleValues[currentSample]) / (mSampleValues[currentSample + 1] - mSampleValues[currentSample]), + guessForT = intervalStart + dist * kSampleStepSize, + initialSlope = getSlope(guessForT, mX1, mX2); + + if (initialSlope >= NEWTON_MIN_SLOPE) { + return newtonRaphsonIterate(aX, guessForT); + } else if (initialSlope === 0.0) { + return guessForT; + } else { + return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize); + } + } + + var _precomputed = false; + + function precompute() { + _precomputed = true; + if (mX1 !== mY1 || mX2 !== mY2) { + calcSampleValues(); + } + } + + var f = function f(aX) { + if (!_precomputed) { + precompute(); + } + if (mX1 === mY1 && mX2 === mY2) { + return aX; + } + if (aX === 0) { + return 0; + } + if (aX === 1) { + return 1; + } + + return calcBezier(getTForX(aX), mY1, mY2); + }; + + f.getControlPoints = function () { + return [{ + x: mX1, + y: mY1 + }, { + x: mX2, + y: mY2 + }]; + }; + + var str = "generateBezier(" + [mX1, mY1, mX2, mY2] + ")"; + f.toString = function () { + return str; + }; + + return f; +} + +module.exports = generateCubicBezier; + +/***/ }), +/* 76 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/*! Runge-Kutta spring physics function generator. Adapted from Framer.js, copyright Koen Bok. MIT License: http://en.wikipedia.org/wiki/MIT_License */ +/* Given a tension, friction, and duration, a simulation at 60FPS will first run without a defined duration in order to calculate the full path. A second pass + then adjusts the time delta -- using the relation between actual time and duration -- to calculate the path for the duration-constrained animation. */ +var generateSpringRK4 = function () { + function springAccelerationForState(state) { + return -state.tension * state.x - state.friction * state.v; + } + + function springEvaluateStateWithDerivative(initialState, dt, derivative) { + var state = { + x: initialState.x + derivative.dx * dt, + v: initialState.v + derivative.dv * dt, + tension: initialState.tension, + friction: initialState.friction + }; + + return { dx: state.v, dv: springAccelerationForState(state) }; + } + + function springIntegrateState(state, dt) { + var a = { + dx: state.v, + dv: springAccelerationForState(state) + }, + b = springEvaluateStateWithDerivative(state, dt * 0.5, a), + c = springEvaluateStateWithDerivative(state, dt * 0.5, b), + d = springEvaluateStateWithDerivative(state, dt, c), dxdt = 1.0 / 6.0 * (a.dx + 2.0 * (b.dx + c.dx) + d.dx), dvdt = 1.0 / 6.0 * (a.dv + 2.0 * (b.dv + c.dv) + d.dv); - state.x = state.x + dxdt * dt; - state.v = state.v + dvdt * dt; + state.x = state.x + dxdt * dt; + state.v = state.v + dvdt * dt; - return state; - } + return state; + } - return function springRK4Factory( tension, friction, duration ){ + return function springRK4Factory(tension, friction, duration) { - var initState = { - x: -1, - v: 0, - tension: null, - friction: null - }, + var initState = { + x: -1, + v: 0, + tension: null, + friction: null + }, path = [0], time_lapsed = 0, tolerance = 1 / 10000, DT = 16 / 1000, - have_duration, dt, last_state; + have_duration = void 0, + dt = void 0, + last_state = void 0; - tension = parseFloat( tension ) || 500; - friction = parseFloat( friction ) || 20; - duration = duration || null; + tension = parseFloat(tension) || 500; + friction = parseFloat(friction) || 20; + duration = duration || null; - initState.tension = tension; - initState.friction = friction; + initState.tension = tension; + initState.friction = friction; - have_duration = duration !== null; + have_duration = duration !== null; - /* Calculate the actual time it takes for this animation to complete with the provided conditions. */ - if( have_duration ){ - /* Run the simulation without a duration. */ - time_lapsed = springRK4Factory( tension, friction ); - /* Compute the adjusted time delta. */ - dt = time_lapsed / duration * DT; - } else { - dt = DT; - } - - while( true ){ - /* Next/step function .*/ - last_state = springIntegrateState( last_state || initState, dt ); - /* Store the position. */ - path.push( 1 + last_state.x ); - time_lapsed += 16; - /* If the change threshold is reached, break. */ - if( !(Math.abs( last_state.x ) > tolerance && Math.abs( last_state.v ) > tolerance) ){ - break; - } - } - - /* If duration is not defined, return the actual time required for completing this animation. Otherwise, return a closure that holds the - computed path and returns a snapshot of the position according to a given percentComplete. */ - return !have_duration ? time_lapsed : function( percentComplete ){ return path[ (percentComplete * (path.length - 1)) | 0 ]; }; - }; - }()); - - var easings = { - 'linear': function( start, end, percent ){ - return start + (end - start) * percent; - }, - - // default easings - 'ease': cubicBezier( 0.25, 0.1, 0.25, 1 ), - 'ease-in': cubicBezier( 0.42, 0, 1, 1 ), - 'ease-out': cubicBezier( 0, 0, 0.58, 1 ), - 'ease-in-out': cubicBezier( 0.42, 0, 0.58, 1 ), - - // sine - 'ease-in-sine': cubicBezier( 0.47, 0, 0.745, 0.715 ), - 'ease-out-sine': cubicBezier( 0.39, 0.575, 0.565, 1 ), - 'ease-in-out-sine': cubicBezier( 0.445, 0.05, 0.55, 0.95 ), - - // quad - 'ease-in-quad': cubicBezier( 0.55, 0.085, 0.68, 0.53 ), - 'ease-out-quad': cubicBezier( 0.25, 0.46, 0.45, 0.94 ), - 'ease-in-out-quad': cubicBezier( 0.455, 0.03, 0.515, 0.955 ), - - // cubic - 'ease-in-cubic': cubicBezier( 0.55, 0.055, 0.675, 0.19 ), - 'ease-out-cubic': cubicBezier( 0.215, 0.61, 0.355, 1 ), - 'ease-in-out-cubic': cubicBezier( 0.645, 0.045, 0.355, 1 ), - - // quart - 'ease-in-quart': cubicBezier( 0.895, 0.03, 0.685, 0.22 ), - 'ease-out-quart': cubicBezier( 0.165, 0.84, 0.44, 1 ), - 'ease-in-out-quart': cubicBezier( 0.77, 0, 0.175, 1 ), - - // quint - 'ease-in-quint': cubicBezier( 0.755, 0.05, 0.855, 0.06 ), - 'ease-out-quint': cubicBezier( 0.23, 1, 0.32, 1 ), - 'ease-in-out-quint': cubicBezier( 0.86, 0, 0.07, 1 ), - - // expo - 'ease-in-expo': cubicBezier( 0.95, 0.05, 0.795, 0.035 ), - 'ease-out-expo': cubicBezier( 0.19, 1, 0.22, 1 ), - 'ease-in-out-expo': cubicBezier( 1, 0, 0, 1 ), - - // circ - 'ease-in-circ': cubicBezier( 0.6, 0.04, 0.98, 0.335 ), - 'ease-out-circ': cubicBezier( 0.075, 0.82, 0.165, 1 ), - 'ease-in-out-circ': cubicBezier( 0.785, 0.135, 0.15, 0.86 ), - - - // user param easings... - - 'spring': function( tension, friction, duration ){ - if( duration === 0 ){ // can't get a spring w/ duration 0 - return easings.linear; // duration 0 => jump to end so impl doesn't matter - } - - var spring = generateSpringRK4( tension, friction, duration ); - - return function( start, end, percent ){ - return start + (end - start) * spring( percent ); - }; - }, - - 'cubic-bezier': function( x1, y1, x2, y2 ){ - return cubicBezier( x1, y1, x2, y2 ); - } - }; - - function ease( startProp, endProp, percent, easingFn ){ - if( percent < 0 ){ - percent = 0; - } else if( percent > 1 ){ - percent = 1; - } - - var start, end; - - if( startProp.pfValue != null || startProp.value != null ){ - start = startProp.pfValue != null ? startProp.pfValue : startProp.value; - } else { - start = startProp; - } - - if( endProp.pfValue != null || endProp.value != null ){ - end = endProp.pfValue != null ? endProp.pfValue : endProp.value; - } else { - end = endProp; - } - - if( is.number( start ) && is.number( end ) ){ - return easingFn( start, end, percent ); - - } else if( is.array( start ) && is.array( end ) ){ - var easedArr = []; - - for( var i = 0; i < end.length; i++ ){ - var si = start[ i ]; - var ei = end[ i ]; - - if( si != null && ei != null ){ - var val = easingFn( si, ei, percent ); - - if( startProp.roundValue ){ val = Math.round( val ); } - - easedArr.push( val ); - } else { - easedArr.push( ei ); - } - } - - return easedArr; - } - - return undefined; + /* Calculate the actual time it takes for this animation to complete with the provided conditions. */ + if (have_duration) { + /* Run the simulation without a duration. */ + time_lapsed = springRK4Factory(tension, friction); + /* Compute the adjusted time delta. */ + dt = time_lapsed / duration * DT; + } else { + dt = DT; } + for (;;) { + /* Next/step function .*/ + last_state = springIntegrateState(last_state || initState, dt); + /* Store the position. */ + path.push(1 + last_state.x); + time_lapsed += 16; + /* If the change threshold is reached, break. */ + if (!(Math.abs(last_state.x) > tolerance && Math.abs(last_state.v) > tolerance)) { + break; + } + } + + /* If duration is not defined, return the actual time required for completing this animation. Otherwise, return a closure that holds the + computed path and returns a snapshot of the position according to a given percentComplete. */ + return !have_duration ? time_lapsed : function (percentComplete) { + return path[percentComplete * (path.length - 1) | 0]; + }; + }; +}(); + +module.exports = generateSpringRK4; + +/***/ }), +/* 77 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var is = __webpack_require__(0); + +function getEasedValue(type, start, end, percent, easingFn) { + if (percent === 1) { + return end; } -}); + var val = easingFn(start, end, percent); -module.exports = corefn; + if (type == null) { + return val; + } -},{"../define":44,"../is":83,"../util":100}],35:[function(_dereq_,module,exports){ -'use strict'; + if (type.roundValue || type.color) { + val = Math.round(val); + } -var define = _dereq_( '../define' ); + if (type.min !== undefined) { + val = Math.max(val, type.min); + } -var corefn = ({ - on: define.on(), // .on( events [, selector] [, data], handler) - one: define.on( { unbindSelfOnTrigger: true } ), - once: define.on( { unbindAllBindersOnTrigger: true } ), - off: define.off(), // .off( events [, selector] [, handler] ) - trigger: define.trigger() // .trigger( events [, extraParams] ) -}); + if (type.max !== undefined) { + val = Math.min(val, type.max); + } -define.eventAliasesOn( corefn ); + return val; +} -module.exports = corefn; +function getValue(prop, spec) { + if (prop.pfValue != null || prop.value != null) { + if (prop.pfValue != null && (spec == null || spec.type.units !== '%')) { + return prop.pfValue; + } else { + return prop.value; + } + } else { + return prop; + } +} -},{"../define":44}],36:[function(_dereq_,module,exports){ -'use strict'; +function ease(startProp, endProp, percent, easingFn, propSpec) { + var type = propSpec != null ? propSpec.type : null; -var corefn = ({ + if (percent < 0) { + percent = 0; + } else if (percent > 1) { + percent = 1; + } - png: function( options ){ + var start = getValue(startProp, propSpec); + var end = getValue(endProp, propSpec); + + if (is.number(start) && is.number(end)) { + return getEasedValue(type, start, end, percent, easingFn); + } else if (is.array(start) && is.array(end)) { + var easedArr = []; + + for (var i = 0; i < end.length; i++) { + var si = start[i]; + var ei = end[i]; + + if (si != null && ei != null) { + var val = getEasedValue(type, si, ei, percent, easingFn); + + easedArr.push(val); + } else { + easedArr.push(ei); + } + } + + return easedArr; + } + + return undefined; +} + +module.exports = ease; + +/***/ }), +/* 78 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +function startAnimation(self, ani, now, isCore) { + var isEles = !isCore; + var ele = self; + var ani_p = ani._private; + var cy = isCore ? self : self.cy(); + var style = cy.style(); + + if (isEles) { + var pos = ele.position(); + + ani_p.startPosition = ani_p.startPosition || { + x: pos.x, + y: pos.y + }; + + ani_p.startStyle = ani_p.startStyle || style.getAnimationStartStyle(ele, ani_p.style); + } + + if (isCore) { + var pan = cy._private.pan; + + ani_p.startPan = ani_p.startPan || { + x: pan.x, + y: pan.y + }; + + ani_p.startZoom = ani_p.startZoom != null ? ani_p.startZoom : cy._private.zoom; + } + + ani_p.started = true; + ani_p.startTime = now - ani_p.progress * ani_p.duration; +} + +module.exports = startAnimation; + +/***/ }), +/* 79 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var Emitter = __webpack_require__(11); +var define = __webpack_require__(4); +var is = __webpack_require__(0); +var util = __webpack_require__(1); +var Selector = __webpack_require__(6); + +var emitterOptions = { + qualifierCompare: function qualifierCompare(selector1, selector2) { + if (selector1 == null || selector2 == null) { + return selector1 == null && selector2 == null; + } else { + return selector1.sameText(selector2); + } + }, + eventMatches: function eventMatches(cy, listener, eventObj) { + var selector = listener.qualifier; + + if (selector != null) { + return cy !== eventObj.target && is.element(eventObj.target) && selector.matches(eventObj.target); + } + + return true; + }, + eventFields: function eventFields(cy) { + return { + cy: cy, + target: cy + }; + }, + callbackContext: function callbackContext(cy, listener, eventObj) { + return listener.qualifier != null ? eventObj.target : cy; + } +}; + +var argSelector = function argSelector(arg) { + if (is.string(arg)) { + return new Selector(arg); + } else { + return arg; + } +}; + +var elesfn = { + createEmitter: function createEmitter() { + var _p = this._private; + + if (!_p.emitter) { + _p.emitter = new Emitter(util.assign({ + context: this + }, emitterOptions)); + } + + return this; + }, + + emitter: function emitter() { + return this._private.emitter; + }, + + on: function on(events, selector, callback) { + this.emitter().on(events, argSelector(selector), callback); + + return this; + }, + + removeListener: function removeListener(events, selector, callback) { + this.emitter().removeListener(events, argSelector(selector), callback); + + return this; + }, + + one: function one(events, selector, callback) { + this.emitter().one(events, argSelector(selector), callback); + + return this; + }, + + once: function once(events, selector, callback) { + this.emitter().one(events, argSelector(selector), callback); + + return this; + }, + + emit: function emit(events, extraParams) { + this.emitter().emit(events, extraParams); + + return this; + } +}; + +define.eventAliasesOn(elesfn); + +module.exports = elesfn; + +/***/ }), +/* 80 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var corefn = { + + png: function png(options) { var renderer = this._private.renderer; options = options || {}; - return renderer.png( options ); + return renderer.png(options); }, - jpg: function( options ){ + jpg: function jpg(options) { var renderer = this._private.renderer; options = options || {}; options.bg = options.bg || '#fff'; - return renderer.jpg( options ); + return renderer.jpg(options); } -}); +}; corefn.jpeg = corefn.jpg; module.exports = corefn; -},{}],37:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 81 */ +/***/ (function(module, exports, __webpack_require__) { -var window = _dereq_( '../window' ); -var util = _dereq_( '../util' ); -var Collection = _dereq_( '../collection' ); -var is = _dereq_( '../is' ); -var Promise = _dereq_( '../promise' ); -var define = _dereq_( '../define' ); +"use strict"; -var Core = function( opts ){ - var cy = this; - opts = util.extend( {}, opts ); +var util = __webpack_require__(1); +var is = __webpack_require__(0); - var container = opts.container; +var corefn = { - // allow for passing a wrapped jquery object - // e.g. cytoscape({ container: $('#cy') }) - if( container && !is.htmlElement( container ) && is.htmlElement( container[0] ) ){ - container = container[0]; - } - - var reg = container ? container._cyreg : null; // e.g. already registered some info (e.g. readies) via jquery - reg = reg || {}; - - if( reg && reg.cy ){ - reg.cy.destroy(); - - reg = {}; // old instance => replace reg completely - } - - var readies = reg.readies = reg.readies || []; - - if( container ){ container._cyreg = reg; } // make sure container assoc'd reg points to this cy - reg.cy = cy; - - var head = window !== undefined && container !== undefined && !opts.headless; - var options = opts; - options.layout = util.extend( { name: head ? 'grid' : 'null' }, options.layout ); - options.renderer = util.extend( { name: head ? 'canvas' : 'null' }, options.renderer ); - - var defVal = function( def, val, altVal ){ - if( val !== undefined ){ - return val; - } else if( altVal !== undefined ){ - return altVal; - } else { - return def; - } - }; - - var _p = this._private = { - container: container, // html dom ele container - ready: false, // whether ready has been triggered - initrender: false, // has initrender has been triggered - options: options, // cached options - elements: new Collection( this ), // elements in the graph - listeners: [], // list of listeners - aniEles: new Collection( this ), // elements being animated - scratch: {}, // scratch object for core - layout: null, - renderer: null, - notificationsEnabled: true, // whether notifications are sent to the renderer - minZoom: 1e-50, - maxZoom: 1e50, - zoomingEnabled: defVal( true, options.zoomingEnabled ), - userZoomingEnabled: defVal( true, options.userZoomingEnabled ), - panningEnabled: defVal( true, options.panningEnabled ), - userPanningEnabled: defVal( true, options.userPanningEnabled ), - boxSelectionEnabled: defVal( true, options.boxSelectionEnabled ), - autolock: defVal( false, options.autolock, options.autolockNodes ), - autoungrabify: defVal( false, options.autoungrabify, options.autoungrabifyNodes ), - autounselectify: defVal( false, options.autounselectify ), - styleEnabled: options.styleEnabled === undefined ? head : options.styleEnabled, - zoom: is.number( options.zoom ) ? options.zoom : 1, - pan: { - x: is.plainObject( options.pan ) && is.number( options.pan.x ) ? options.pan.x : 0, - y: is.plainObject( options.pan ) && is.number( options.pan.y ) ? options.pan.y : 0 - }, - animation: { // object for currently-running animations - current: [], - queue: [] - }, - hasCompoundNodes: false - }; - - // set selection type - var selType = options.selectionType; - if( selType === undefined || (selType !== 'additive' && selType !== 'single') ){ - // then set default - - _p.selectionType = 'single'; - } else { - _p.selectionType = selType; - } - - // init zoom bounds - if( is.number( options.minZoom ) && is.number( options.maxZoom ) && options.minZoom < options.maxZoom ){ - _p.minZoom = options.minZoom; - _p.maxZoom = options.maxZoom; - } else if( is.number( options.minZoom ) && options.maxZoom === undefined ){ - _p.minZoom = options.minZoom; - } else if( is.number( options.maxZoom ) && options.minZoom === undefined ){ - _p.maxZoom = options.maxZoom; - } - - var loadExtData = function( extData, next ){ - var anyIsPromise = extData.some( is.promise ); - - if( anyIsPromise ){ - return Promise.all( extData ).then( next ); // load all data asynchronously, then exec rest of init - } else { - next( extData ); // exec synchronously for convenience - } - }; - - // create the renderer - cy.initRenderer( util.extend( { - hideEdgesOnViewport: options.hideEdgesOnViewport, - textureOnViewport: options.textureOnViewport, - wheelSensitivity: is.number( options.wheelSensitivity ) && options.wheelSensitivity > 0 ? options.wheelSensitivity : 1, - motionBlur: options.motionBlur === undefined ? false : options.motionBlur, // off by default - motionBlurOpacity: options.motionBlurOpacity === undefined ? 0.05 : options.motionBlurOpacity, - pixelRatio: is.number( options.pixelRatio ) && options.pixelRatio > 0 ? options.pixelRatio : undefined, - desktopTapThreshold: options.desktopTapThreshold === undefined ? 4 : options.desktopTapThreshold, - touchTapThreshold: options.touchTapThreshold === undefined ? 8 : options.touchTapThreshold - }, options.renderer ) ); - - loadExtData([ options.style, options.elements ], function( thens ){ - var initStyle = thens[0]; - var initEles = thens[1]; - - // init style - if( _p.styleEnabled ){ - cy.setStyle( initStyle ); - } - - // trigger the passed function for the `initrender` event - if( options.initrender ){ - cy.on( 'initrender', options.initrender ); - cy.on( 'initrender', function(){ - _p.initrender = true; - } ); - } - - // initial load - cy.load( initEles, function(){ // onready - cy.startAnimationLoop(); - _p.ready = true; - - // if a ready callback is specified as an option, the bind it - if( is.fn( options.ready ) ){ - cy.on( 'ready', options.ready ); - } - - // bind all the ready handlers registered before creating this instance - for( var i = 0; i < readies.length; i++ ){ - var fn = readies[ i ]; - cy.on( 'ready', fn ); - } - if( reg ){ reg.readies = []; } // clear b/c we've bound them all and don't want to keep it around in case a new core uses the same div etc - - cy.trigger( 'ready' ); - }, options.done ); - - } ); -}; - -var corefn = Core.prototype; // short alias - -util.extend( corefn, { - instanceString: function(){ - return 'core'; - }, - - isReady: function(){ - return this._private.ready; - }, - - ready: function( fn ){ - if( this.isReady() ){ - this.trigger( 'ready', [], fn ); // just calls fn as though triggered via ready event - } else { - this.on( 'ready', fn ); - } - - return this; - }, - - initrender: function(){ - return this._private.initrender; - }, - - destroy: function(){ + layout: function layout(options) { var cy = this; - cy.stopAnimationLoop(); - - cy.destroyRenderer(); - - return cy; - }, - - hasElementWithId: function( id ){ - return this._private.elements.hasElementWithId( id ); - }, - - getElementById: function( id ){ - return this._private.elements.getElementById( id ); - }, - - selectionType: function(){ - return this._private.selectionType; - }, - - hasCompoundNodes: function(){ - return this._private.hasCompoundNodes; - }, - - headless: function(){ - return this._private.options.renderer.name === 'null'; - }, - - styleEnabled: function(){ - return this._private.styleEnabled; - }, - - addToPool: function( eles ){ - this._private.elements.merge( eles ); - - return this; // chaining - }, - - removeFromPool: function( eles ){ - this._private.elements.unmerge( eles ); - - return this; - }, - - container: function(){ - return this._private.container; - }, - - options: function(){ - return util.copy( this._private.options ); - }, - - json: function( obj ){ - var cy = this; - var _p = cy._private; - var eles = cy.mutableElements(); - - if( is.plainObject( obj ) ){ // set - - cy.startBatch(); - - if( obj.elements ){ - var idInJson = {}; - - var updateEles = function( jsons, gr ){ - for( var i = 0; i < jsons.length; i++ ){ - var json = jsons[ i ]; - var id = json.data.id; - var ele = cy.getElementById( id ); - - idInJson[ id ] = true; - - if( ele.length !== 0 ){ // existing element should be updated - ele.json( json ); - } else { // otherwise should be added - if( gr ){ - cy.add( util.extend( { group: gr }, json ) ); - } else { - cy.add( json ); - } - } - } - }; - - if( is.array( obj.elements ) ){ // elements: [] - updateEles( obj.elements ); - - } else { // elements: { nodes: [], edges: [] } - var grs = [ 'nodes', 'edges' ]; - for( var i = 0; i < grs.length; i++ ){ - var gr = grs[ i ]; - var elements = obj.elements[ gr ]; - - if( is.array( elements ) ){ - updateEles( elements, gr ); - } - } - } - - // elements not specified in json should be removed - eles.stdFilter( function( ele ){ - return !idInJson[ ele.id() ]; - } ).remove(); - } - - if( obj.style ){ - cy.style( obj.style ); - } - - if( obj.zoom != null && obj.zoom !== _p.zoom ){ - cy.zoom( obj.zoom ); - } - - if( obj.pan ){ - if( obj.pan.x !== _p.pan.x || obj.pan.y !== _p.pan.y ){ - cy.pan( obj.pan ); - } - } - - var fields = [ - 'minZoom', 'maxZoom', 'zoomingEnabled', 'userZoomingEnabled', - 'panningEnabled', 'userPanningEnabled', - 'boxSelectionEnabled', - 'autolock', 'autoungrabify', 'autounselectify' - ]; - - for( var i = 0; i < fields.length; i++ ){ - var f = fields[ i ]; - - if( obj[ f ] != null ){ - cy[ f ]( obj[ f ] ); - } - } - - cy.endBatch(); - - return this; // chaining - } else if( obj === undefined ){ // get - var json = {}; - - json.elements = {}; - eles.forEach( function( ele ){ - var group = ele.group(); - - if( !json.elements[ group ] ){ - json.elements[ group ] = []; - } - - json.elements[ group ].push( ele.json() ); - } ); - - if( this._private.styleEnabled ){ - json.style = cy.style().json(); - } - - json.zoomingEnabled = cy._private.zoomingEnabled; - json.userZoomingEnabled = cy._private.userZoomingEnabled; - json.zoom = cy._private.zoom; - json.minZoom = cy._private.minZoom; - json.maxZoom = cy._private.maxZoom; - json.panningEnabled = cy._private.panningEnabled; - json.userPanningEnabled = cy._private.userPanningEnabled; - json.pan = util.copy( cy._private.pan ); - json.boxSelectionEnabled = cy._private.boxSelectionEnabled; - json.renderer = util.copy( cy._private.options.renderer ); - json.hideEdgesOnViewport = cy._private.options.hideEdgesOnViewport; - json.textureOnViewport = cy._private.options.textureOnViewport; - json.wheelSensitivity = cy._private.options.wheelSensitivity; - json.motionBlur = cy._private.options.motionBlur; - - return json; - } - }, - - scratch: define.data( { - field: 'scratch', - bindingEvent: 'scratch', - allowBinding: true, - allowSetting: true, - settingEvent: 'scratch', - settingTriggersEvent: true, - triggerFnName: 'trigger', - allowGetting: true - } ), - - removeScratch: define.removeData( { - field: 'scratch', - event: 'scratch', - triggerFnName: 'trigger', - triggerEvent: true - } ) - -} ); - -[ - _dereq_( './add-remove' ), - _dereq_( './animation' ), - _dereq_( './events' ), - _dereq_( './export' ), - _dereq_( './layout' ), - _dereq_( './notification' ), - _dereq_( './renderer' ), - _dereq_( './search' ), - _dereq_( './style' ), - _dereq_( './viewport' ) -].forEach( function( props ){ - util.extend( corefn, props ); -} ); - -module.exports = Core; - -},{"../collection":26,"../define":44,"../is":83,"../promise":86,"../util":100,"../window":107,"./add-remove":33,"./animation":34,"./events":35,"./export":36,"./layout":38,"./notification":39,"./renderer":40,"./search":41,"./style":42,"./viewport":43}],38:[function(_dereq_,module,exports){ -'use strict'; - -var util = _dereq_( '../util' ); -var is = _dereq_( '../is' ); - -var corefn = ({ - - layout: function( params ){ - var layout = this._private.prevLayout = ( params == null ? this._private.prevLayout : this.makeLayout( params ) ); - - layout.run(); - - return this; // chaining - }, - - makeLayout: function( options ){ - var cy = this; - - if( options == null ){ - util.error( 'Layout options must be specified to make a layout' ); + if (options == null) { + util.error('Layout options must be specified to make a layout'); return; } - if( options.name == null ){ - util.error( 'A `name` must be specified to make a layout' ); + if (options.name == null) { + util.error('A `name` must be specified to make a layout'); return; } var name = options.name; - var Layout = cy.extension( 'layout', name ); + var Layout = cy.extension('layout', name); - if( Layout == null ){ - util.error( 'Can not apply layout: No such layout `' + name + '` found; did you include its JS file?' ); + if (Layout == null) { + util.error('Can not apply layout: No such layout `' + name + '` found; did you include its JS file?'); return; } - var eles; - if( is.string( options.eles ) ){ - eles = cy.$( options.eles ); + var eles = void 0; + if (is.string(options.eles)) { + eles = cy.$(options.eles); } else { eles = options.eles != null ? options.eles : cy.$(); } - var layout = new Layout( util.extend( {}, options, { + var layout = new Layout(util.extend({}, options, { cy: cy, eles: eles - } ) ); + })); return layout; } -}); +}; -corefn.createLayout = corefn.makeLayout; +corefn.createLayout = corefn.makeLayout = corefn.layout; module.exports = corefn; -},{"../is":83,"../util":100}],39:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 82 */ +/***/ (function(module, exports, __webpack_require__) { -var corefn = ({ - notify: function( params ){ +"use strict"; + + +var corefn = { + notify: function notify(params) { var _p = this._private; - if( _p.batchingNotify ){ + if (_p.batchingNotify) { var bEles = _p.batchNotifyEles; var bTypes = _p.batchNotifyTypes; - if( params.eles ){ - bEles.merge( params.eles ); + if (params.eles) { + bEles.merge(params.eles); } - if( !bTypes.ids[ params.type ] ){ - bTypes.push( params.type ); - bTypes.ids[ params.type ] = true; + if (!bTypes.ids[params.type]) { + bTypes.push(params.type); + bTypes.ids[params.type] = true; } return; // notifications are disabled during batching } - if( !_p.notificationsEnabled ){ return; } // exit on disabled + if (!_p.notificationsEnabled) { + return; + } // exit on disabled var renderer = this.renderer(); - renderer.notify( params ); + // exit if destroy() called on core or renderer in between frames #1499 #1528 + if (this.isDestroyed() || !renderer) { + return; + } + + renderer.notify(params); }, - notifications: function( bool ){ + notifications: function notifications(bool) { var p = this._private; - if( bool === undefined ){ + if (bool === undefined) { return p.notificationsEnabled; } else { p.notificationsEnabled = bool ? true : false; } }, - noNotifications: function( callback ){ - this.notifications( false ); + noNotifications: function noNotifications(callback) { + this.notifications(false); callback(); - this.notifications( true ); + this.notifications(true); }, - startBatch: function(){ + batching: function batching() { + return this._private.batchCount > 0; + }, + + startBatch: function startBatch() { var _p = this._private; - if( _p.batchCount == null ){ + if (_p.batchCount == null) { _p.batchCount = 0; } - if( _p.batchCount === 0 ){ + if (_p.batchCount === 0) { _p.batchingStyle = _p.batchingNotify = true; _p.batchStyleEles = this.collection(); _p.batchNotifyEles = this.collection(); @@ -7282,28 +14446,28 @@ var corefn = ({ return this; }, - endBatch: function(){ + endBatch: function endBatch() { var _p = this._private; _p.batchCount--; - if( _p.batchCount === 0 ){ + if (_p.batchCount === 0) { // update style for dirty eles _p.batchingStyle = false; _p.batchStyleEles.updateStyle(); // notify the renderer of queued eles and event types _p.batchingNotify = false; - this.notify( { + this.notify({ type: _p.batchNotifyTypes, eles: _p.batchNotifyEles - } ); + }); } return this; }, - batch: function( callback ){ + batch: function batch(callback) { this.startBatch(); callback(); this.endBatch(); @@ -7312,194 +14476,202 @@ var corefn = ({ }, // for backwards compatibility - batchData: function( map ){ + batchData: function batchData(map) { var cy = this; - return this.batch( function(){ - var ids = Object.keys( map ); + return this.batch(function () { + var ids = Object.keys(map); - for( var i = 0; i < ids.length; i++ ){ + for (var i = 0; i < ids.length; i++) { var id = ids[i]; - var data = map[ id ]; - var ele = cy.getElementById( id ); + var data = map[id]; + var ele = cy.getElementById(id); - ele.data( data ); + ele.data(data); } - } ); + }); } -}); +}; module.exports = corefn; -},{}],40:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 83 */ +/***/ (function(module, exports, __webpack_require__) { -var util = _dereq_( '../util' ); +"use strict"; -var corefn = ({ - renderTo: function( context, zoom, pan, pxRatio ){ +var util = __webpack_require__(1); + +var corefn = { + + renderTo: function renderTo(context, zoom, pan, pxRatio) { var r = this._private.renderer; - r.renderTo( context, zoom, pan, pxRatio ); + r.renderTo(context, zoom, pan, pxRatio); return this; }, - renderer: function(){ + renderer: function renderer() { return this._private.renderer; }, - forceRender: function(){ - this.notify( { + forceRender: function forceRender() { + this.notify({ type: 'draw' - } ); + }); return this; }, - resize: function(){ + resize: function resize() { this.invalidateSize(); - this.notify( { + this.notify({ type: 'resize' - } ); + }); - this.trigger( 'resize' ); + this.emit('resize'); return this; }, - initRenderer: function( options ){ + initRenderer: function initRenderer(options) { var cy = this; - var RendererProto = cy.extension( 'renderer', options.name ); - if( RendererProto == null ){ - util.error( 'Can not initialise: No such renderer `%s` found; did you include its JS file?', options.name ); + var RendererProto = cy.extension('renderer', options.name); + if (RendererProto == null) { + util.error('Can not initialise: No such renderer `%s` found; did you include its JS file?', options.name); return; } - var rOpts = util.extend( {}, options, { - cy: cy - } ); + cy._private.renderer = new RendererProto(util.extend({}, options, { cy: cy })); - cy._private.renderer = new RendererProto( rOpts ); + this.notify({ type: 'init' }); }, - destroyRenderer: function(){ + destroyRenderer: function destroyRenderer() { var cy = this; - cy.notify( { type: 'destroy' } ); // destroy the renderer + cy.notify({ type: 'destroy' }); // destroy the renderer var domEle = cy.container(); - if( domEle ){ + if (domEle) { domEle._cyreg = null; - while( domEle.childNodes.length > 0 ){ - domEle.removeChild( domEle.childNodes[0] ); + while (domEle.childNodes.length > 0) { + domEle.removeChild(domEle.childNodes[0]); } } cy._private.renderer = null; // to be extra safe, remove the ref }, - onRender: function( fn ){ + onRender: function onRender(fn) { return this.on('render', fn); }, - offRender: function( fn ){ + offRender: function offRender(fn) { return this.off('render', fn); } -}); +}; corefn.invalidateDimensions = corefn.resize; module.exports = corefn; -},{"../util":100}],41:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 84 */ +/***/ (function(module, exports, __webpack_require__) { -var is = _dereq_( '../is' ); -var Collection = _dereq_( '../collection' ); +"use strict"; -var corefn = ({ + +var is = __webpack_require__(0); +var Collection = __webpack_require__(7); + +var corefn = { // get a collection // - empty collection on no args // - collection of elements in the graph on selector arg // - guarantee a returned collection when elements or collection specified - collection: function( eles, opts ){ + collection: function collection(eles, opts) { - if( is.string( eles ) ){ - return this.$( eles ); - - } else if( is.elementOrCollection( eles ) ){ + if (is.string(eles)) { + return this.$(eles); + } else if (is.elementOrCollection(eles)) { return eles.collection(); - - } else if( is.array( eles ) ){ - return new Collection( this, eles, opts ); + } else if (is.array(eles)) { + return new Collection(this, eles, opts); } - return new Collection( this ); + return new Collection(this); }, - nodes: function( selector ){ - var nodes = this.$( function(){ - return this.isNode(); - } ); + nodes: function nodes(selector) { + var nodes = this.$(function (ele) { + return ele.isNode(); + }); - if( selector ){ - return nodes.filter( selector ); + if (selector) { + return nodes.filter(selector); } return nodes; }, - edges: function( selector ){ - var edges = this.$( function(){ - return this.isEdge(); - } ); + edges: function edges(selector) { + var edges = this.$(function (ele) { + return ele.isEdge(); + }); - if( selector ){ - return edges.filter( selector ); + if (selector) { + return edges.filter(selector); } return edges; }, // search the graph like jQuery - $: function( selector ){ + $: function $(selector) { var eles = this._private.elements; - if( selector ){ - return eles.filter( selector ); + if (selector) { + return eles.filter(selector); } else { return eles.spawnSelf(); } }, - mutableElements: function(){ + mutableElements: function mutableElements() { return this._private.elements; } -}); +}; // aliases corefn.elements = corefn.filter = corefn.$; module.exports = corefn; -},{"../collection":26,"../is":83}],42:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 85 */ +/***/ (function(module, exports, __webpack_require__) { -var is = _dereq_( '../is' ); -var Style = _dereq_( '../style' ); +"use strict"; -var corefn = ({ - style: function( newStyle ){ - if( newStyle ){ - var s = this.setStyle( newStyle ); +var is = __webpack_require__(0); +var Style = __webpack_require__(18); + +var corefn = { + + style: function style(newStyle) { + if (newStyle) { + var s = this.setStyle(newStyle); s.update(); } @@ -7507,37 +14679,2205 @@ var corefn = ({ return this._private.style; }, - setStyle: function( style ){ + setStyle: function setStyle(style) { var _p = this._private; - if( is.stylesheet( style ) ){ - _p.style = style.generateStyle( this ); - - } else if( is.array( style ) ){ - _p.style = Style.fromJson( this, style ); - - } else if( is.string( style ) ){ - _p.style = Style.fromString( this, style ); - + if (is.stylesheet(style)) { + _p.style = style.generateStyle(this); + } else if (is.array(style)) { + _p.style = Style.fromJson(this, style); + } else if (is.string(style)) { + _p.style = Style.fromString(this, style); } else { - _p.style = Style( this ); + _p.style = Style(this); } return _p.style; } -}); +}; module.exports = corefn; -},{"../is":83,"../style":92}],43:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 86 */ +/***/ (function(module, exports, __webpack_require__) { -var is = _dereq_( '../is' ); +"use strict"; -var corefn = ({ - autolock: function( bool ){ - if( bool !== undefined ){ +var util = __webpack_require__(1); +var is = __webpack_require__(0); +var Promise = __webpack_require__(5); + +var styfn = {}; + +// (potentially expensive calculation) +// apply the style to the element based on +// - its bypass +// - what selectors match it +styfn.apply = function (eles) { + var self = this; + var _p = self._private; + var cy = _p.cy; + var updatedEles = cy.collection(); + + if (_p.newStyle) { + // clear style caches + _p.contextStyles = {}; + _p.propDiffs = {}; + + self.cleanElements(eles, true); + } + + for (var ie = 0; ie < eles.length; ie++) { + var ele = eles[ie]; + + var cxtMeta = self.getContextMeta(ele); + + if (cxtMeta.empty) { + continue; + } else { + updatedEles.merge(ele); + } + + var cxtStyle = self.getContextStyle(cxtMeta); + var app = self.applyContextStyle(cxtMeta, cxtStyle, ele); + + if (!_p.newStyle) { + self.updateTransitions(ele, app.diffProps); + } + + self.updateStyleHints(ele); + } // for elements + + _p.newStyle = false; + + return updatedEles; +}; + +styfn.getPropertiesDiff = function (oldCxtKey, newCxtKey) { + var self = this; + var cache = self._private.propDiffs = self._private.propDiffs || {}; + var dualCxtKey = oldCxtKey + '-' + newCxtKey; + var cachedVal = cache[dualCxtKey]; + + if (cachedVal) { + return cachedVal; + } + + var diffProps = []; + var addedProp = {}; + + for (var i = 0; i < self.length; i++) { + var cxt = self[i]; + var oldHasCxt = oldCxtKey[i] === 't'; + var newHasCxt = newCxtKey[i] === 't'; + var cxtHasDiffed = oldHasCxt !== newHasCxt; + var cxtHasMappedProps = cxt.mappedProperties.length > 0; + + if (cxtHasDiffed || cxtHasMappedProps) { + var props = void 0; + + if (cxtHasDiffed && cxtHasMappedProps) { + props = cxt.properties; // suffices b/c mappedProperties is a subset of properties + } else if (cxtHasDiffed) { + props = cxt.properties; // need to check them all + } else if (cxtHasMappedProps) { + props = cxt.mappedProperties; // only need to check mapped + } + + for (var j = 0; j < props.length; j++) { + var prop = props[j]; + var name = prop.name; + + // if a later context overrides this property, then the fact that this context has switched/diffed doesn't matter + // (semi expensive check since it makes this function O(n^2) on context length, but worth it since overall result + // is cached) + var laterCxtOverrides = false; + for (var k = i + 1; k < self.length; k++) { + var laterCxt = self[k]; + var hasLaterCxt = newCxtKey[k] === 't'; + + if (!hasLaterCxt) { + continue; + } // can't override unless the context is active + + laterCxtOverrides = laterCxt.properties[prop.name] != null; + + if (laterCxtOverrides) { + break; + } // exit early as long as one later context overrides + } + + if (!addedProp[name] && !laterCxtOverrides) { + addedProp[name] = true; + diffProps.push(name); + } + } // for props + } // if + } // for contexts + + cache[dualCxtKey] = diffProps; + return diffProps; +}; + +styfn.getContextMeta = function (ele) { + var self = this; + var cxtKey = ''; + var diffProps = void 0; + var prevKey = ele._private.styleCxtKey || ''; + + if (self._private.newStyle) { + prevKey = ''; // since we need to apply all style if a fresh stylesheet + } + + // get the cxt key + for (var i = 0; i < self.length; i++) { + var context = self[i]; + var contextSelectorMatches = context.selector && context.selector.matches(ele); // NB: context.selector may be null for 'core' + + if (contextSelectorMatches) { + cxtKey += 't'; + } else { + cxtKey += 'f'; + } + } // for context + + diffProps = self.getPropertiesDiff(prevKey, cxtKey); + + ele._private.styleCxtKey = cxtKey; + + return { + key: cxtKey, + diffPropNames: diffProps, + empty: diffProps.length === 0 + }; +}; + +// gets a computed ele style object based on matched contexts +styfn.getContextStyle = function (cxtMeta) { + var cxtKey = cxtMeta.key; + var self = this; + var cxtStyles = this._private.contextStyles = this._private.contextStyles || {}; + + // if already computed style, returned cached copy + if (cxtStyles[cxtKey]) { + return cxtStyles[cxtKey]; + } + + var style = { + _private: { + key: cxtKey + } + }; + + for (var i = 0; i < self.length; i++) { + var cxt = self[i]; + var hasCxt = cxtKey[i] === 't'; + + if (!hasCxt) { + continue; + } + + for (var j = 0; j < cxt.properties.length; j++) { + var prop = cxt.properties[j]; + + style[prop.name] = prop; + } + } + + cxtStyles[cxtKey] = style; + return style; +}; + +styfn.applyContextStyle = function (cxtMeta, cxtStyle, ele) { + var self = this; + var diffProps = cxtMeta.diffPropNames; + var retDiffProps = {}; + + for (var i = 0; i < diffProps.length; i++) { + var diffPropName = diffProps[i]; + var cxtProp = cxtStyle[diffPropName]; + var eleProp = ele.pstyle(diffPropName); + + if (!cxtProp) { + // no context prop means delete + if (!eleProp) { + continue; // no existing prop means nothing needs to be removed + // nb affects initial application on mapped values like control-point-distances + } else if (eleProp.bypass) { + cxtProp = { name: diffPropName, deleteBypassed: true }; + } else { + cxtProp = { name: diffPropName, delete: true }; + } + } + + // save cycles when the context prop doesn't need to be applied + if (eleProp === cxtProp) { + continue; + } + + var retDiffProp = retDiffProps[diffPropName] = { + prev: eleProp + }; + + self.applyParsedProperty(ele, cxtProp); + + retDiffProp.next = ele.pstyle(diffPropName); + + if (retDiffProp.next && retDiffProp.next.bypass) { + retDiffProp.next = retDiffProp.next.bypassed; + } + } + + return { + diffProps: retDiffProps + }; +}; + +styfn.updateStyleHints = function (ele) { + var _p = ele._private; + var self = this; + + if (ele.removed()) { + return; + } + + // set whether has pie or not; for greater efficiency + var hasPie = false; + if (_p.group === 'nodes') { + for (var i = 1; i <= self.pieBackgroundN; i++) { + // 1..N + var _size = ele.pstyle('pie-' + i + '-background-size').value; + + if (_size > 0) { + hasPie = true; + break; + } + } + } + + _p.hasPie = hasPie; + + var transform = ele.pstyle('text-transform').strValue; + var content = ele.pstyle('label').strValue; + var srcContent = ele.pstyle('source-label').strValue; + var tgtContent = ele.pstyle('target-label').strValue; + var fStyle = ele.pstyle('font-style').strValue; + var size = ele.pstyle('font-size').pfValue + 'px'; + var family = ele.pstyle('font-family').strValue; + // let letiant = style['font-letiant'].strValue; + var weight = ele.pstyle('font-weight').strValue; + var valign = ele.pstyle('text-valign').strValue; + var halign = ele.pstyle('text-valign').strValue; + var oWidth = ele.pstyle('text-outline-width').pfValue; + var wrap = ele.pstyle('text-wrap').strValue; + var wrapW = ele.pstyle('text-max-width').pfValue; + var labelStyleKey = fStyle + '$' + size + '$' + family + '$' + weight + '$' + transform + '$' + valign + '$' + halign + '$' + oWidth + '$' + wrap + '$' + wrapW; + _p.labelStyleKey = labelStyleKey; + _p.sourceLabelKey = labelStyleKey + '$' + srcContent; + _p.targetLabelKey = labelStyleKey + '$' + tgtContent; + _p.labelKey = labelStyleKey + '$' + content; + _p.fontKey = fStyle + '$' + weight + '$' + size + '$' + family; + + _p.styleKey = Date.now(); +}; + +// apply a property to the style (for internal use) +// returns whether application was successful +// +// now, this function flattens the property, and here's how: +// +// for parsedProp:{ bypass: true, deleteBypass: true } +// no property is generated, instead the bypass property in the +// element's style is replaced by what's pointed to by the `bypassed` +// field in the bypass property (i.e. restoring the property the +// bypass was overriding) +// +// for parsedProp:{ mapped: truthy } +// the generated flattenedProp:{ mapping: prop } +// +// for parsedProp:{ bypass: true } +// the generated flattenedProp:{ bypassed: parsedProp } +styfn.applyParsedProperty = function (ele, parsedProp) { + var self = this; + var prop = parsedProp; + var style = ele._private.style; + var fieldVal = void 0, + flatProp = void 0; + var types = self.types; + var type = self.properties[prop.name].type; + var propIsBypass = prop.bypass; + var origProp = style[prop.name]; + var origPropIsBypass = origProp && origProp.bypass; + var _p = ele._private; + var flatPropMapping = 'mapping'; + + var checkZOrder = function checkZOrder() { + self.checkZOrderTrigger(ele, prop.name, origProp ? origProp.value : null, prop.value); + }; + + // edges connected to compound nodes can not be haystacks + if (parsedProp.name === 'curve-style' && parsedProp.value === 'haystack' && ele.isEdge() && (ele.isLoop() || ele.source().isParent() || ele.target().isParent())) { + prop = parsedProp = this.parse(parsedProp.name, 'bezier', propIsBypass); + } + + if (prop.delete) { + // delete the property and use the default value on falsey value + style[prop.name] = undefined; + + checkZOrder(); + + return true; + } + + if (prop.deleteBypassed) { + // delete the property that the + if (!origProp) { + checkZOrder(); + + return true; // can't delete if no prop + } else if (origProp.bypass) { + // delete bypassed + origProp.bypassed = undefined; + + checkZOrder(); + + return true; + } else { + return false; // we're unsuccessful deleting the bypassed + } + } + + // check if we need to delete the current bypass + if (prop.deleteBypass) { + // then this property is just here to indicate we need to delete + if (!origProp) { + checkZOrder(); + + return true; // property is already not defined + } else if (origProp.bypass) { + // then replace the bypass property with the original + // because the bypassed property was already applied (and therefore parsed), we can just replace it (no reapplying necessary) + style[prop.name] = origProp.bypassed; + + checkZOrder(); + + return true; + } else { + return false; // we're unsuccessful deleting the bypass + } + } + + var printMappingErr = function printMappingErr() { + util.error('Do not assign mappings to elements without corresponding data (e.g. ele `' + ele.id() + '` for property `' + prop.name + '` with data field `' + prop.field + '`); try a `[' + prop.field + ']` selector to limit scope to elements with `' + prop.field + '` defined'); + }; + + // put the property in the style objects + switch (prop.mapped) {// flatten the property if mapped + case types.mapData: + { + // flatten the field (e.g. data.foo.bar) + var fields = prop.field.split('.'); + var _fieldVal = _p.data; + + for (var i = 0; i < fields.length && _fieldVal; i++) { + var field = fields[i]; + _fieldVal = _fieldVal[field]; + } + + var percent = void 0; + if (!is.number(_fieldVal)) { + // then keep the mapping but assume 0% for now + percent = 0; + } else { + percent = (_fieldVal - prop.fieldMin) / (prop.fieldMax - prop.fieldMin); + } + + // make sure to bound percent value + if (percent < 0) { + percent = 0; + } else if (percent > 1) { + percent = 1; + } + + if (type.color) { + var r1 = prop.valueMin[0]; + var r2 = prop.valueMax[0]; + var g1 = prop.valueMin[1]; + var g2 = prop.valueMax[1]; + var b1 = prop.valueMin[2]; + var b2 = prop.valueMax[2]; + var a1 = prop.valueMin[3] == null ? 1 : prop.valueMin[3]; + var a2 = prop.valueMax[3] == null ? 1 : prop.valueMax[3]; + + var clr = [Math.round(r1 + (r2 - r1) * percent), Math.round(g1 + (g2 - g1) * percent), Math.round(b1 + (b2 - b1) * percent), Math.round(a1 + (a2 - a1) * percent)]; + + flatProp = { // colours are simple, so just create the flat property instead of expensive string parsing + bypass: prop.bypass, // we're a bypass if the mapping property is a bypass + name: prop.name, + value: clr, + strValue: 'rgb(' + clr[0] + ', ' + clr[1] + ', ' + clr[2] + ')' + }; + } else if (type.number) { + var calcValue = prop.valueMin + (prop.valueMax - prop.valueMin) * percent; + flatProp = this.parse(prop.name, calcValue, prop.bypass, flatPropMapping); + } else { + return false; // can only map to colours and numbers + } + + if (!flatProp) { + // if we can't flatten the property, then use the origProp so we still keep the mapping itself + flatProp = this.parse(prop.name, origProp.strValue, prop.bypass, flatPropMapping); + } + + if (!flatProp) { + printMappingErr(); + } + flatProp.mapping = prop; // keep a reference to the mapping + prop = flatProp; // the flattened (mapped) property is the one we want + + break; + } + + // direct mapping + case types.data: + { + // flatten the field (e.g. data.foo.bar) + var _fields = prop.field.split('.'); + var _fieldVal2 = _p.data; + + if (_fieldVal2) { + for (var _i = 0; _i < _fields.length; _i++) { + var _field = _fields[_i]; + _fieldVal2 = _fieldVal2[_field]; + } + } + + flatProp = this.parse(prop.name, _fieldVal2, prop.bypass, flatPropMapping); + + if (!flatProp) { + // if we can't flatten the property, then use the origProp so we still keep the mapping itself + var flatPropVal = origProp ? origProp.strValue : ''; + + flatProp = this.parse(prop.name, flatPropVal, prop.bypass, flatPropMapping); + } + + if (!flatProp) { + printMappingErr(); + } + flatProp.mapping = prop; // keep a reference to the mapping + prop = flatProp; // the flattened (mapped) property is the one we want + + break; + } + + case types.fn: + { + var fn = prop.value; + var fnRetVal = fn(ele); + + flatProp = this.parse(prop.name, fnRetVal, prop.bypass, flatPropMapping); + flatProp.mapping = prop; // keep a reference to the mapping + prop = flatProp; // the flattened (mapped) property is the one we want + + break; + } + + case undefined: + break; // just set the property + + default: + return false; // not a valid mapping + } + + // if the property is a bypass property, then link the resultant property to the original one + if (propIsBypass) { + if (origPropIsBypass) { + // then this bypass overrides the existing one + prop.bypassed = origProp.bypassed; // steal bypassed prop from old bypass + } else { + // then link the orig prop to the new bypass + prop.bypassed = origProp; + } + + style[prop.name] = prop; // and set + } else { + // prop is not bypass + if (origPropIsBypass) { + // then keep the orig prop (since it's a bypass) and link to the new prop + origProp.bypassed = prop; + } else { + // then just replace the old prop with the new one + style[prop.name] = prop; + } + } + + checkZOrder(); + + return true; +}; + +styfn.cleanElements = function (eles, keepBypasses) { + var self = this; + var props = self.properties; + + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; + + if (!keepBypasses) { + ele._private.style = {}; + } else { + var style = ele._private.style; + + for (var j = 0; j < props.length; j++) { + var prop = props[j]; + var eleProp = style[prop.name]; + + if (eleProp) { + if (eleProp.bypass) { + eleProp.bypassed = null; + } else { + style[prop.name] = null; + } + } + } + } + } +}; + +// updates the visual style for all elements (useful for manual style modification after init) +styfn.update = function () { + var cy = this._private.cy; + var eles = cy.mutableElements(); + + eles.updateStyle(); +}; + +// just update the functional properties (i.e. mappings) in the elements' +// styles (less expensive than recalculation) +styfn.updateMappers = function (eles) { + var self = this; + var cy = this._private.cy; + var updatedEles = cy.collection(); + + for (var i = 0; i < eles.length; i++) { + // for each ele + var ele = eles[i]; + var style = ele._private.style; + var updatedEle = false; + + for (var j = 0; j < self.properties.length; j++) { + // for each prop + var prop = self.properties[j]; + var propInStyle = style[prop.name]; + + if (propInStyle && propInStyle.mapping) { + var mapping = propInStyle.mapping; + + this.applyParsedProperty(ele, mapping); // reapply the mapping property + + updatedEle = true; + } + } + + if (updatedEle) { + this.updateStyleHints(ele); + + updatedEles.merge(ele); + } + } + + return updatedEles; +}; + +// diffProps : { name => { prev, next } } +styfn.updateTransitions = function (ele, diffProps, isBypass) { + var self = this; + var _p = ele._private; + var props = ele.pstyle('transition-property').value; + var duration = ele.pstyle('transition-duration').pfValue; + var delay = ele.pstyle('transition-delay').pfValue; + + if (props.length > 0 && duration > 0) { + + var style = {}; + + // build up the style to animate towards + var anyPrev = false; + for (var i = 0; i < props.length; i++) { + var prop = props[i]; + var styProp = ele.pstyle(prop); + var diffProp = diffProps[prop]; + + if (!diffProp) { + continue; + } + + var prevProp = diffProp.prev; + var fromProp = prevProp; + var toProp = diffProp.next != null ? diffProp.next : styProp; + var diff = false; + var initVal = void 0; + var initDt = 0.000001; // delta time % value for initVal (allows animating out of init zero opacity) + + if (!fromProp) { + continue; + } + + // consider px values + if (is.number(fromProp.pfValue) && is.number(toProp.pfValue)) { + diff = toProp.pfValue - fromProp.pfValue; // nonzero is truthy + initVal = fromProp.pfValue + initDt * diff; + + // consider numerical values + } else if (is.number(fromProp.value) && is.number(toProp.value)) { + diff = toProp.value - fromProp.value; // nonzero is truthy + initVal = fromProp.value + initDt * diff; + + // consider colour values + } else if (is.array(fromProp.value) && is.array(toProp.value)) { + diff = fromProp.value[0] !== toProp.value[0] || fromProp.value[1] !== toProp.value[1] || fromProp.value[2] !== toProp.value[2]; + + initVal = fromProp.strValue; + } + + // the previous value is good for an animation only if it's different + if (diff) { + style[prop] = toProp.strValue; // to val + this.applyBypass(ele, prop, initVal); // from val + anyPrev = true; + } + } // end if props allow ani + + // can't transition if there's nothing previous to transition from + if (!anyPrev) { + return; + } + + _p.transitioning = true; + + new Promise(function (resolve) { + if (delay > 0) { + ele.delayAnimation(delay).play().promise().then(resolve); + } else { + resolve(); + } + }).then(function () { + return ele.animation({ + style: style, + duration: duration, + easing: ele.pstyle('transition-timing-function').value, + queue: false + }).play().promise(); + }).then(function () { + // if( !isBypass ){ + self.removeBypasses(ele, props); + ele.emitAndNotify('style'); + // } + + _p.transitioning = false; + }); + } else if (_p.transitioning) { + this.removeBypasses(ele, props); + ele.emitAndNotify('style'); + + _p.transitioning = false; + } +}; + +styfn.checkZOrderTrigger = function (ele, name, fromValue, toValue) { + var prop = this.properties[name]; + + if (prop.triggersZOrder != null && (fromValue == null || prop.triggersZOrder(fromValue, toValue))) { + this._private.cy.notify({ + type: 'zorder', + eles: ele + }); + } +}; + +module.exports = styfn; + +/***/ }), +/* 87 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var is = __webpack_require__(0); +var util = __webpack_require__(1); + +var styfn = {}; + +// bypasses are applied to an existing style on an element, and just tacked on temporarily +// returns true iff application was successful for at least 1 specified property +styfn.applyBypass = function (eles, name, value, updateTransitions) { + var self = this; + var props = []; + var isBypass = true; + + // put all the properties (can specify one or many) in an array after parsing them + if (name === '*' || name === '**') { + // apply to all property names + + if (value !== undefined) { + for (var i = 0; i < self.properties.length; i++) { + var prop = self.properties[i]; + var _name = prop.name; + + var parsedProp = this.parse(_name, value, true); + + if (parsedProp) { + props.push(parsedProp); + } + } + } + } else if (is.string(name)) { + // then parse the single property + var _parsedProp = this.parse(name, value, true); + + if (_parsedProp) { + props.push(_parsedProp); + } + } else if (is.plainObject(name)) { + // then parse each property + var specifiedProps = name; + updateTransitions = value; + + var names = Object.keys(specifiedProps); + + for (var _i = 0; _i < names.length; _i++) { + var _name2 = names[_i]; + var _prop = self.properties[_name2]; + var _value = specifiedProps[_name2]; + + if (_value === undefined) { + // try camel case name too + _value = specifiedProps[util.dash2camel(_name2)]; + } + + if (_value !== undefined) { + var _parsedProp2 = this.parse(_name2, _value, true); + + if (_parsedProp2) { + props.push(_parsedProp2); + } + } + } + } else { + // can't do anything without well defined properties + return false; + } + + // we've failed if there are no valid properties + if (props.length === 0) { + return false; + } + + // now, apply the bypass properties on the elements + var ret = false; // return true if at least one succesful bypass applied + for (var _i2 = 0; _i2 < eles.length; _i2++) { + // for each ele + var ele = eles[_i2]; + var diffProps = {}; + var diffProp = void 0; + + for (var j = 0; j < props.length; j++) { + // for each prop + var _prop2 = props[j]; + + if (updateTransitions) { + var prevProp = ele.pstyle(_prop2.name); + diffProp = diffProps[_prop2.name] = { prev: prevProp }; + } + + ret = this.applyParsedProperty(ele, _prop2) || ret; + + if (updateTransitions) { + diffProp.next = ele.pstyle(_prop2.name); + } + } // for props + + if (ret) { + this.updateStyleHints(ele); + } + + if (updateTransitions) { + this.updateTransitions(ele, diffProps, isBypass); + } + } // for eles + + return ret; +}; + +// only useful in specific cases like animation +styfn.overrideBypass = function (eles, name, value) { + name = util.camel2dash(name); + + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; + var prop = ele._private.style[name]; + var type = this.properties[name].type; + var isColor = type.color; + var isMulti = type.mutiple; + + if (!prop || !prop.bypass) { + // need a bypass if one doesn't exist + this.applyBypass(ele, name, value); + continue; + } + + var oldValue = prop.pfValue != null ? prop.pfValue : prop.value; + + prop.value = value; + + if (prop.pfValue != null) { + prop.pfValue = value; + } + + if (isColor) { + prop.strValue = 'rgb(' + value.join(',') + ')'; + } else if (isMulti) { + prop.strValue = value.join(' '); + } else { + prop.strValue = '' + value; + } + + this.checkZOrderTrigger(ele, name, oldValue, value); + } +}; + +styfn.removeAllBypasses = function (eles, updateTransitions) { + return this.removeBypasses(eles, this.propertyNames, updateTransitions); +}; + +styfn.removeBypasses = function (eles, props, updateTransitions) { + var isBypass = true; + + for (var j = 0; j < eles.length; j++) { + var ele = eles[j]; + var diffProps = {}; + + for (var i = 0; i < props.length; i++) { + var name = props[i]; + var prop = this.properties[name]; + var prevProp = ele.pstyle(prop.name); + + if (!prevProp || !prevProp.bypass) { + // if a bypass doesn't exist for the prop, nothing needs to be removed + continue; + } + + var value = ''; // empty => remove bypass + var parsedProp = this.parse(name, value, true); + var diffProp = diffProps[prop.name] = { prev: prevProp }; + + this.applyParsedProperty(ele, parsedProp); + + diffProp.next = ele.pstyle(prop.name); + } // for props + + this.updateStyleHints(ele); + + if (updateTransitions) { + this.updateTransitions(ele, diffProps, isBypass); + } + } // for eles +}; + +module.exports = styfn; + +/***/ }), +/* 88 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var window = __webpack_require__(3); + +var styfn = {}; + +// gets what an em size corresponds to in pixels relative to a dom element +styfn.getEmSizeInPixels = function () { + var px = this.containerCss('font-size'); + + if (px != null) { + return parseFloat(px); + } else { + return 1; // for headless + } +}; + +// gets css property from the core container +styfn.containerCss = function (propName) { + var cy = this._private.cy; + var domElement = cy.container(); + + if (window && domElement && window.getComputedStyle) { + return window.getComputedStyle(domElement).getPropertyValue(propName); + } +}; + +module.exports = styfn; + +/***/ }), +/* 89 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var util = __webpack_require__(1); +var is = __webpack_require__(0); + +var styfn = {}; + +// gets the rendered style for an element +styfn.getRenderedStyle = function (ele, prop) { + if (prop) { + return this.getStylePropertyValue(ele, prop, true); + } else { + return this.getRawStyle(ele, true); + } +}; + +// gets the raw style for an element +styfn.getRawStyle = function (ele, isRenderedVal) { + var self = this; + + ele = ele[0]; // insure it's an element + + if (ele) { + var rstyle = {}; + + for (var i = 0; i < self.properties.length; i++) { + var prop = self.properties[i]; + var val = self.getStylePropertyValue(ele, prop.name, isRenderedVal); + + if (val != null) { + rstyle[prop.name] = val; + rstyle[util.dash2camel(prop.name)] = val; + } + } + + return rstyle; + } +}; + +styfn.getIndexedStyle = function (ele, property, subproperty, index) { + var pstyle = ele.pstyle(property)[subproperty][index]; + return pstyle != null ? pstyle : ele.cy().style().getDefaultProperty(property)[subproperty][0]; +}; + +styfn.getStylePropertyValue = function (ele, propName, isRenderedVal) { + var self = this; + + ele = ele[0]; // insure it's an element + + if (ele) { + var prop = self.properties[propName]; + + if (prop.alias) { + prop = prop.pointsTo; + } + + var type = prop.type; + var styleProp = ele.pstyle(prop.name); + var zoom = ele.cy().zoom(); + + if (styleProp) { + var units = styleProp.units ? type.implicitUnits || 'px' : null; + var val = units ? [].concat(styleProp.pfValue).map(function (pfValue) { + return pfValue * (isRenderedVal ? zoom : 1) + units; + }).join(' ') : styleProp.strValue; + + return val; + } + } +}; + +styfn.getAnimationStartStyle = function (ele, aniProps) { + var rstyle = {}; + + for (var i = 0; i < aniProps.length; i++) { + var aniProp = aniProps[i]; + var name = aniProp.name; + + var styleProp = ele.pstyle(name); + + if (styleProp !== undefined) { + // then make a prop of it + if (is.plainObject(styleProp)) { + styleProp = this.parse(name, styleProp.strValue); + } else { + styleProp = this.parse(name, styleProp); + } + } + + if (styleProp) { + rstyle[name] = styleProp; + } + } + + return rstyle; +}; + +styfn.getPropsList = function (propsObj) { + var self = this; + var rstyle = []; + var style = propsObj; + var props = self.properties; + + if (style) { + var names = Object.keys(style); + + for (var i = 0; i < names.length; i++) { + var name = names[i]; + var val = style[name]; + var prop = props[name] || props[util.camel2dash(name)]; + var styleProp = this.parse(prop.name, val); + + if (styleProp) { + rstyle.push(styleProp); + } + } + } + + return rstyle; +}; + +module.exports = styfn; + +/***/ }), +/* 90 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var styfn = {}; + +styfn.appendFromJson = function (json) { + var style = this; + + for (var i = 0; i < json.length; i++) { + var context = json[i]; + var selector = context.selector; + var props = context.style || context.css; + var names = Object.keys(props); + + style.selector(selector); // apply selector + + for (var j = 0; j < names.length; j++) { + var name = names[j]; + var value = props[name]; + + style.css(name, value); // apply property + } + } + + return style; +}; + +// accessible cy.style() function +styfn.fromJson = function (json) { + var style = this; + + style.resetToDefault(); + style.appendFromJson(json); + + return style; +}; + +// get json from cy.style() api +styfn.json = function () { + var json = []; + + for (var i = this.defaultLength; i < this.length; i++) { + var cxt = this[i]; + var selector = cxt.selector; + var props = cxt.properties; + var css = {}; + + for (var j = 0; j < props.length; j++) { + var prop = props[j]; + css[prop.name] = prop.strValue; + } + + json.push({ + selector: !selector ? 'core' : selector.toString(), + style: css + }); + } + + return json; +}; + +module.exports = styfn; + +/***/ }), +/* 91 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var util = __webpack_require__(1); +var Selector = __webpack_require__(6); + +var styfn = {}; + +styfn.appendFromString = function (string) { + var self = this; + var style = this; + var remaining = '' + string; + var selAndBlockStr = void 0; + var blockRem = void 0; + var propAndValStr = void 0; + + // remove comments from the style string + remaining = remaining.replace(/[/][*](\s|.)+?[*][/]/g, ''); + + function removeSelAndBlockFromRemaining() { + // remove the parsed selector and block from the remaining text to parse + if (remaining.length > selAndBlockStr.length) { + remaining = remaining.substr(selAndBlockStr.length); + } else { + remaining = ''; + } + } + + function removePropAndValFromRem() { + // remove the parsed property and value from the remaining block text to parse + if (blockRem.length > propAndValStr.length) { + blockRem = blockRem.substr(propAndValStr.length); + } else { + blockRem = ''; + } + } + + while (true) { + var nothingLeftToParse = remaining.match(/^\s*$/); + if (nothingLeftToParse) { + break; + } + + var selAndBlock = remaining.match(/^\s*((?:.|\s)+?)\s*\{((?:.|\s)+?)\}/); + + if (!selAndBlock) { + util.error('Halting stylesheet parsing: String stylesheet contains more to parse but no selector and block found in: ' + remaining); + break; + } + + selAndBlockStr = selAndBlock[0]; + + // parse the selector + var selectorStr = selAndBlock[1]; + if (selectorStr !== 'core') { + var selector = new Selector(selectorStr); + if (selector._private.invalid) { + util.error('Skipping parsing of block: Invalid selector found in string stylesheet: ' + selectorStr); + + // skip this selector and block + removeSelAndBlockFromRemaining(); + continue; + } + } + + // parse the block of properties and values + var blockStr = selAndBlock[2]; + var invalidBlock = false; + blockRem = blockStr; + var props = []; + + while (true) { + var _nothingLeftToParse = blockRem.match(/^\s*$/); + if (_nothingLeftToParse) { + break; + } + + var propAndVal = blockRem.match(/^\s*(.+?)\s*:\s*(.+?)\s*;/); + + if (!propAndVal) { + util.error('Skipping parsing of block: Invalid formatting of style property and value definitions found in:' + blockStr); + invalidBlock = true; + break; + } + + propAndValStr = propAndVal[0]; + var propStr = propAndVal[1]; + var valStr = propAndVal[2]; + + var prop = self.properties[propStr]; + if (!prop) { + util.error('Skipping property: Invalid property name in: ' + propAndValStr); + + // skip this property in the block + removePropAndValFromRem(); + continue; + } + + var parsedProp = style.parse(propStr, valStr); + + if (!parsedProp) { + util.error('Skipping property: Invalid property definition in: ' + propAndValStr); + + // skip this property in the block + removePropAndValFromRem(); + continue; + } + + props.push({ + name: propStr, + val: valStr + }); + removePropAndValFromRem(); + } + + if (invalidBlock) { + removeSelAndBlockFromRemaining(); + break; + } + + // put the parsed block in the style + style.selector(selectorStr); + for (var i = 0; i < props.length; i++) { + var _prop = props[i]; + style.css(_prop.name, _prop.val); + } + + removeSelAndBlockFromRemaining(); + } + + return style; +}; + +styfn.fromString = function (string) { + var style = this; + + style.resetToDefault(); + style.appendFromString(string); + + return style; +}; + +module.exports = styfn; + +/***/ }), +/* 92 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var util = __webpack_require__(1); +var is = __webpack_require__(0); + +var styfn = {}; + +(function () { + var number = util.regex.number; + var rgba = util.regex.rgbaNoBackRefs; + var hsla = util.regex.hslaNoBackRefs; + var hex3 = util.regex.hex3; + var hex6 = util.regex.hex6; + var data = function data(prefix) { + return '^' + prefix + '\\s*\\(\\s*([\\w\\.]+)\\s*\\)$'; + }; + var mapData = function mapData(prefix) { + var mapArg = number + '|\\w+|' + rgba + '|' + hsla + '|' + hex3 + '|' + hex6; + return '^' + prefix + '\\s*\\(([\\w\\.]+)\\s*\\,\\s*(' + number + ')\\s*\\,\\s*(' + number + ')\\s*,\\s*(' + mapArg + ')\\s*\\,\\s*(' + mapArg + ')\\)$'; + }; + var urlRegexes = ['^url\\s*\\(\\s*[\'"]?(.+?)[\'"]?\\s*\\)$', '^(none)$', '^(.+)$']; + + // each visual style property has a type and needs to be validated according to it + styfn.types = { + time: { number: true, min: 0, units: 's|ms', implicitUnits: 'ms' }, + percent: { number: true, min: 0, max: 100, units: '%', implicitUnits: '%' }, + zeroOneNumber: { number: true, min: 0, max: 1, unitless: true }, + zeroOneNumbers: { number: true, min: 0, max: 1, unitless: true, multiple: true }, + nOneOneNumber: { number: true, min: -1, max: 1, unitless: true }, + nonNegativeInt: { number: true, min: 0, integer: true, unitless: true }, + position: { enums: ['parent', 'origin'] }, + nodeSize: { number: true, min: 0, enums: ['label'] }, + number: { number: true, unitless: true }, + numbers: { number: true, unitless: true, multiple: true }, + positiveNumber: { number: true, unitless: true, min: 0, strictMin: true }, + size: { number: true, min: 0 }, + bidirectionalSize: { number: true }, // allows negative + bidirectionalSizes: { number: true, multiple: true }, // allows negative + sizeMaybePercent: { number: true, min: 0, allowPercent: true }, + paddingRelativeTo: { enums: ['width', 'height', 'average', 'min', 'max'] }, + bgWH: { number: true, min: 0, allowPercent: true, enums: ['auto'], multiple: true }, + bgPos: { number: true, allowPercent: true, multiple: true }, + bgRelativeTo: { enums: ['inner', 'include-padding'], multiple: true }, + bgRepeat: { enums: ['repeat', 'repeat-x', 'repeat-y', 'no-repeat'], multiple: true }, + bgFit: { enums: ['none', 'contain', 'cover'], multiple: true }, + bgCrossOrigin: { enums: ['anonymous', 'use-credentials'], multiple: true }, + bgClip: { enums: ['none', 'node'] }, + color: { color: true }, + bool: { enums: ['yes', 'no'] }, + lineStyle: { enums: ['solid', 'dotted', 'dashed'] }, + borderStyle: { enums: ['solid', 'dotted', 'dashed', 'double'] }, + curveStyle: { enums: ['bezier', 'unbundled-bezier', 'haystack', 'segments'] }, + fontFamily: { regex: '^([\\w- \\"]+(?:\\s*,\\s*[\\w- \\"]+)*)$' }, + fontletiant: { enums: ['small-caps', 'normal'] }, + fontStyle: { enums: ['italic', 'normal', 'oblique'] }, + fontWeight: { enums: ['normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '800', '900', 100, 200, 300, 400, 500, 600, 700, 800, 900] }, + textDecoration: { enums: ['none', 'underline', 'overline', 'line-through'] }, + textTransform: { enums: ['none', 'uppercase', 'lowercase'] }, + textWrap: { enums: ['none', 'wrap', 'ellipsis'] }, + textBackgroundShape: { enums: ['rectangle', 'roundrectangle'] }, + nodeShape: { enums: ['rectangle', 'roundrectangle', 'cutrectangle', 'bottomroundrectangle', 'barrel', 'ellipse', 'triangle', 'square', 'pentagon', 'hexagon', 'concavehexagon', 'heptagon', 'octagon', 'tag', 'star', 'diamond', 'vee', 'rhomboid', 'polygon'] }, + compoundIncludeLabels: { enums: ['include', 'exclude'] }, + arrowShape: { enums: ['tee', 'triangle', 'triangle-tee', 'triangle-cross', 'triangle-backcurve', 'half-triangle-overshot', 'vee', 'square', 'circle', 'diamond', 'none'] }, + arrowFill: { enums: ['filled', 'hollow'] }, + display: { enums: ['element', 'none'] }, + visibility: { enums: ['hidden', 'visible'] }, + zCompoundDepth: { enums: ['bottom', 'orphan', 'auto', 'top'] }, + zIndexCompare: { enums: ['auto', 'manual'] }, + valign: { enums: ['top', 'center', 'bottom'] }, + halign: { enums: ['left', 'center', 'right'] }, + text: { string: true }, + data: { mapping: true, regex: data('data') }, + layoutData: { mapping: true, regex: data('layoutData') }, + scratch: { mapping: true, regex: data('scratch') }, + mapData: { mapping: true, regex: mapData('mapData') }, + mapLayoutData: { mapping: true, regex: mapData('mapLayoutData') }, + mapScratch: { mapping: true, regex: mapData('mapScratch') }, + fn: { mapping: true, fn: true }, + url: { regexes: urlRegexes, singleRegexMatchValue: true }, + urls: { regexes: urlRegexes, singleRegexMatchValue: true, multiple: true }, + propList: { propList: true }, + angle: { number: true, units: 'deg|rad', implicitUnits: 'rad' }, + textRotation: { number: true, units: 'deg|rad', implicitUnits: 'rad', enums: ['none', 'autorotate'] }, + polygonPointList: { number: true, multiple: true, evenMultiple: true, min: -1, max: 1, unitless: true }, + edgeDistances: { enums: ['intersection', 'node-position'] }, + edgeEndpoint: { + number: true, multiple: true, units: '%|px|em|deg|rad', implicitUnits: 'px', + enums: ['inside-to-node', 'outside-to-node', 'outside-to-line'], singleEnum: true, + validate: function validate(valArr, unitsArr) { + switch (valArr.length) { + case 2: + // can be % or px only + return unitsArr[0] !== 'deg' && unitsArr[0] !== 'rad' && unitsArr[1] !== 'deg' && unitsArr[1] !== 'rad'; + case 1: + // can be enum, deg, or rad only + return is.string(valArr[0]) || unitsArr[0] === 'deg' || unitsArr[0] === 'rad'; + default: + return false; + } + } + }, + easing: { + regexes: ['^(spring)\\s*\\(\\s*(' + number + ')\\s*,\\s*(' + number + ')\\s*\\)$', '^(cubic-bezier)\\s*\\(\\s*(' + number + ')\\s*,\\s*(' + number + ')\\s*,\\s*(' + number + ')\\s*,\\s*(' + number + ')\\s*\\)$'], + enums: ['linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out', 'ease-in-sine', 'ease-out-sine', 'ease-in-out-sine', 'ease-in-quad', 'ease-out-quad', 'ease-in-out-quad', 'ease-in-cubic', 'ease-out-cubic', 'ease-in-out-cubic', 'ease-in-quart', 'ease-out-quart', 'ease-in-out-quart', 'ease-in-quint', 'ease-out-quint', 'ease-in-out-quint', 'ease-in-expo', 'ease-out-expo', 'ease-in-out-expo', 'ease-in-circ', 'ease-out-circ', 'ease-in-out-circ'] + } + }; + + var zOrderDiff = { + zeroNonZero: function zeroNonZero(val1, val2) { + if (val1 === 0 && val2 !== 0) { + return true; + } else if (val1 !== 0 && val2 === 0) { + return true; + } else { + return false; + } + }, + anyDiff: function anyDiff(val1, val2) { + return val1 !== val2; + } + }; + + var zd = zOrderDiff; + + // define visual style properties + var t = styfn.types; + var props = styfn.properties = [ + // main label + { name: 'label', type: t.text }, { name: 'text-rotation', type: t.textRotation }, { name: 'text-margin-x', type: t.bidirectionalSize }, { name: 'text-margin-y', type: t.bidirectionalSize }, + + // source label + { name: 'source-label', type: t.text }, { name: 'source-text-rotation', type: t.textRotation }, { name: 'source-text-margin-x', type: t.bidirectionalSize }, { name: 'source-text-margin-y', type: t.bidirectionalSize }, { name: 'source-text-offset', type: t.size }, + + // target label + { name: 'target-label', type: t.text }, { name: 'target-text-rotation', type: t.textRotation }, { name: 'target-text-margin-x', type: t.bidirectionalSize }, { name: 'target-text-margin-y', type: t.bidirectionalSize }, { name: 'target-text-offset', type: t.size }, + + // common label style + { name: 'text-valign', type: t.valign }, { name: 'text-halign', type: t.halign }, { name: 'color', type: t.color }, { name: 'text-outline-color', type: t.color }, { name: 'text-outline-width', type: t.size }, { name: 'text-outline-opacity', type: t.zeroOneNumber }, { name: 'text-opacity', type: t.zeroOneNumber }, { name: 'text-background-color', type: t.color }, { name: 'text-background-opacity', type: t.zeroOneNumber }, { name: 'text-background-padding', type: t.size }, { name: 'text-border-opacity', type: t.zeroOneNumber }, { name: 'text-border-color', type: t.color }, { name: 'text-border-width', type: t.size }, { name: 'text-border-style', type: t.borderStyle }, { name: 'text-background-shape', type: t.textBackgroundShape }, + // { name: 'text-decoration', type: t.textDecoration }, // not supported in canvas + { name: 'text-transform', type: t.textTransform }, { name: 'text-wrap', type: t.textWrap }, { name: 'text-max-width', type: t.size }, { name: 'text-events', type: t.bool }, { name: 'font-family', type: t.fontFamily }, { name: 'font-style', type: t.fontStyle }, + // { name: 'font-letiant', type: t.fontletiant }, // not useful + { name: 'font-weight', type: t.fontWeight }, { name: 'font-size', type: t.size }, { name: 'min-zoomed-font-size', type: t.size }, + + // behaviour + { name: 'events', type: t.bool }, + + // visibility + { name: 'display', type: t.display, triggersZOrder: zd.anyDiff }, { name: 'visibility', type: t.visibility, triggersZOrder: zd.anyDiff }, { name: 'opacity', type: t.zeroOneNumber, triggersZOrder: zd.zeroNonZero }, { name: 'z-compound-depth', type: t.zCompoundDepth, triggersZOrder: zd.anyDiff }, { name: 'z-index-compare', type: t.zIndexCompare, triggersZOrder: zd.anyDiff }, { name: 'z-index', type: t.nonNegativeInt, triggersZOrder: zd.anyDiff }, + + // overlays + { name: 'overlay-padding', type: t.size }, { name: 'overlay-color', type: t.color }, { name: 'overlay-opacity', type: t.zeroOneNumber }, + + // transition anis + { name: 'transition-property', type: t.propList }, { name: 'transition-duration', type: t.time }, { name: 'transition-delay', type: t.time }, { name: 'transition-timing-function', type: t.easing }, + + // node body + { name: 'height', type: t.nodeSize }, { name: 'width', type: t.nodeSize }, { name: 'shape', type: t.nodeShape }, { name: 'shape-polygon-points', type: t.polygonPointList }, { name: 'background-color', type: t.color }, { name: 'background-opacity', type: t.zeroOneNumber }, { name: 'background-blacken', type: t.nOneOneNumber }, { name: 'padding', type: t.sizeMaybePercent }, { name: 'padding-relative-to', type: t.paddingRelativeTo }, + + // node border + { name: 'border-color', type: t.color }, { name: 'border-opacity', type: t.zeroOneNumber }, { name: 'border-width', type: t.size }, { name: 'border-style', type: t.borderStyle }, + + // node background images + { name: 'background-image', type: t.urls }, { name: 'background-image-crossorigin', type: t.bgCrossOrigin }, { name: 'background-image-opacity', type: t.zeroOneNumbers }, { name: 'background-position-x', type: t.bgPos }, { name: 'background-position-y', type: t.bgPos }, { name: 'background-width-relative-to', type: t.bgRelativeTo }, { name: 'background-height-relative-to', type: t.bgRelativeTo }, { name: 'background-repeat', type: t.bgRepeat }, { name: 'background-fit', type: t.bgFit }, { name: 'background-clip', type: t.bgClip }, { name: 'background-width', type: t.bgWH }, { name: 'background-height', type: t.bgWH }, + + // compound props + { name: 'position', type: t.position }, { name: 'compound-sizing-wrt-labels', type: t.compoundIncludeLabels }, { name: 'min-width', type: t.size }, { name: 'min-width-bias-left', type: t.sizeMaybePercent }, { name: 'min-width-bias-right', type: t.sizeMaybePercent }, { name: 'min-height', type: t.size }, { name: 'min-height-bias-top', type: t.sizeMaybePercent }, { name: 'min-height-bias-bottom', type: t.sizeMaybePercent }, + + // edge line + { name: 'line-style', type: t.lineStyle }, { name: 'line-color', type: t.color }, { name: 'curve-style', type: t.curveStyle }, { name: 'haystack-radius', type: t.zeroOneNumber }, { name: 'source-endpoint', type: t.edgeEndpoint }, { name: 'target-endpoint', type: t.edgeEndpoint }, { name: 'control-point-step-size', type: t.size }, { name: 'control-point-distances', type: t.bidirectionalSizes }, { name: 'control-point-weights', type: t.numbers }, { name: 'segment-distances', type: t.bidirectionalSizes }, { name: 'segment-weights', type: t.numbers }, { name: 'edge-distances', type: t.edgeDistances }, { name: 'arrow-scale', type: t.positiveNumber }, { name: 'loop-direction', type: t.angle }, { name: 'loop-sweep', type: t.angle }, { name: 'source-distance-from-node', type: t.size }, { name: 'target-distance-from-node', type: t.size }, + + // ghost properties + { name: 'ghost', type: t.bool }, { name: 'ghost-offset-x', type: t.bidirectionalSize }, { name: 'ghost-offset-y', type: t.bidirectionalSize }, { name: 'ghost-opacity', type: t.zeroOneNumber }, + + // these are just for the core + { name: 'selection-box-color', type: t.color }, { name: 'selection-box-opacity', type: t.zeroOneNumber }, { name: 'selection-box-border-color', type: t.color }, { name: 'selection-box-border-width', type: t.size }, { name: 'active-bg-color', type: t.color }, { name: 'active-bg-opacity', type: t.zeroOneNumber }, { name: 'active-bg-size', type: t.size }, { name: 'outside-texture-bg-color', type: t.color }, { name: 'outside-texture-bg-opacity', type: t.zeroOneNumber }]; + + // define aliases + var aliases = styfn.aliases = [{ name: 'content', pointsTo: 'label' }, { name: 'control-point-distance', pointsTo: 'control-point-distances' }, { name: 'control-point-weight', pointsTo: 'control-point-weights' }, { name: 'edge-text-rotation', pointsTo: 'text-rotation' }, { name: 'padding-left', pointsTo: 'padding' }, { name: 'padding-right', pointsTo: 'padding' }, { name: 'padding-top', pointsTo: 'padding' }, { name: 'padding-bottom', pointsTo: 'padding' }]; + + // pie backgrounds for nodes + styfn.pieBackgroundN = 16; // because the pie properties are numbered, give access to a constant N (for renderer use) + props.push({ name: 'pie-size', type: t.sizeMaybePercent }); + for (var i = 1; i <= styfn.pieBackgroundN; i++) { + props.push({ name: 'pie-' + i + '-background-color', type: t.color }); + props.push({ name: 'pie-' + i + '-background-size', type: t.percent }); + props.push({ name: 'pie-' + i + '-background-opacity', type: t.zeroOneNumber }); + } + + // edge arrows + var arrowPrefixes = styfn.arrowPrefixes = ['source', 'mid-source', 'target', 'mid-target']; + [{ name: 'arrow-shape', type: t.arrowShape }, { name: 'arrow-color', type: t.color }, { name: 'arrow-fill', type: t.arrowFill }].forEach(function (prop) { + arrowPrefixes.forEach(function (prefix) { + var name = prefix + '-' + prop.name; + var type = prop.type; + + props.push({ name: name, type: type }); + }); + }, {}); + + // list of property names + styfn.propertyNames = props.map(function (p) { + return p.name; + }); + + // allow access of properties by name ( e.g. style.properties.height ) + for (var _i = 0; _i < props.length; _i++) { + var prop = props[_i]; + + props[prop.name] = prop; // allow lookup by name + } + + // map aliases + for (var _i2 = 0; _i2 < aliases.length; _i2++) { + var alias = aliases[_i2]; + var pointsToProp = props[alias.pointsTo]; + var aliasProp = { + name: alias.name, + alias: true, + pointsTo: pointsToProp + }; + + // add alias prop for parsing + props.push(aliasProp); + + props[alias.name] = aliasProp; // allow lookup by name + } +})(); + +styfn.getDefaultProperty = function (name) { + return this.getDefaultProperties()[name]; +}; + +styfn.getDefaultProperties = util.memoize(function () { + var rawProps = util.extend({ + // common node/edge props + 'events': 'yes', + 'text-events': 'no', + 'text-valign': 'top', + 'text-halign': 'center', + 'color': '#000', + 'text-outline-color': '#000', + 'text-outline-width': 0, + 'text-outline-opacity': 1, + 'text-opacity': 1, + 'text-decoration': 'none', + 'text-transform': 'none', + 'text-wrap': 'none', + 'text-max-width': 9999, + 'text-background-color': '#000', + 'text-background-opacity': 0, + 'text-background-shape': 'rectangle', + 'text-background-padding': 0, + 'text-border-opacity': 0, + 'text-border-width': 0, + 'text-border-style': 'solid', + 'text-border-color': '#000', + 'font-family': 'Helvetica Neue, Helvetica, sans-serif', + 'font-style': 'normal', + // 'font-letiant': fontletiant, + 'font-weight': 'normal', + 'font-size': 16, + 'min-zoomed-font-size': 0, + 'text-rotation': 'none', + 'source-text-rotation': 'none', + 'target-text-rotation': 'none', + 'visibility': 'visible', + 'display': 'element', + 'opacity': 1, + 'z-compound-depth': 'auto', + 'z-index-compare': 'auto', + 'z-index': 0, + 'label': '', + 'text-margin-x': 0, + 'text-margin-y': 0, + 'source-label': '', + 'source-text-offset': 0, + 'source-text-margin-x': 0, + 'source-text-margin-y': 0, + 'target-label': '', + 'target-text-offset': 0, + 'target-text-margin-x': 0, + 'target-text-margin-y': 0, + 'overlay-opacity': 0, + 'overlay-color': '#000', + 'overlay-padding': 10, + 'transition-property': 'none', + 'transition-duration': 0, + 'transition-delay': 0, + 'transition-timing-function': 'linear', + + // node props + 'background-blacken': 0, + 'background-color': '#999', + 'background-opacity': 1, + 'background-image': 'none', + 'background-image-crossorigin': 'anonymous', + 'background-image-opacity': 1, + 'background-position-x': '50%', + 'background-position-y': '50%', + 'background-width-relative-to': 'include-padding', + 'background-height-relative-to': 'include-padding', + 'background-repeat': 'no-repeat', + 'background-fit': 'none', + 'background-clip': 'node', + 'background-width': 'auto', + 'background-height': 'auto', + 'border-color': '#000', + 'border-opacity': 1, + 'border-width': 0, + 'border-style': 'solid', + 'height': 30, + 'width': 30, + 'shape': 'ellipse', + 'shape-polygon-points': '-1, -1, 1, -1, 1, 1, -1, 1', + + // ghost props + 'ghost': 'no', + 'ghost-offset-y': 0, + 'ghost-offset-x': 0, + 'ghost-opacity': 0, + + // compound props + 'padding': 0, + 'padding-relative-to': 'width', + 'position': 'origin', + 'compound-sizing-wrt-labels': 'include', + 'min-width': 0, + 'min-width-bias-left': 0, + 'min-width-bias-right': 0, + 'min-height': 0, + 'min-height-bias-top': 0, + 'min-height-bias-bottom': 0 + }, { + // node pie bg + 'pie-size': '100%' + }, [{ name: 'pie-{{i}}-background-color', value: 'black' }, { name: 'pie-{{i}}-background-size', value: '0%' }, { name: 'pie-{{i}}-background-opacity', value: 1 }].reduce(function (css, prop) { + for (var i = 1; i <= styfn.pieBackgroundN; i++) { + var name = prop.name.replace('{{i}}', i); + var val = prop.value; + + css[name] = val; + } + + return css; + }, {}), { + // edge props + 'line-style': 'solid', + 'line-color': '#999', + 'control-point-step-size': 40, + 'control-point-weights': 0.5, + 'segment-weights': 0.5, + 'segment-distances': 20, + 'edge-distances': 'intersection', + 'curve-style': 'bezier', + 'haystack-radius': 0, + 'arrow-scale': 1, + 'loop-direction': '-45deg', + 'loop-sweep': '-90deg', + 'source-distance-from-node': 0, + 'target-distance-from-node': 0, + 'source-endpoint': 'outside-to-node', + 'target-endpoint': 'outside-to-node' + }, [{ name: 'arrow-shape', value: 'none' }, { name: 'arrow-color', value: '#999' }, { name: 'arrow-fill', value: 'filled' }].reduce(function (css, prop) { + styfn.arrowPrefixes.forEach(function (prefix) { + var name = prefix + '-' + prop.name; + var val = prop.value; + + css[name] = val; + }); + + return css; + }, {})); + + var parsedProps = {}; + + for (var i = 0; i < this.properties.length; i++) { + var prop = this.properties[i]; + + if (prop.pointsTo) { + continue; + } + + var name = prop.name; + var val = rawProps[name]; + var parsedProp = this.parse(name, val); + + parsedProps[name] = parsedProp; + } + + return parsedProps; +}); + +styfn.addDefaultStylesheet = function () { + this.selector('$node > node') // compound (parent) node properties + .css({ + 'shape': 'rectangle', + 'padding': 10, + 'background-color': '#eee', + 'border-color': '#ccc', + 'border-width': 1 + }).selector('edge') // just edge properties + .css({ + 'width': 3, + 'curve-style': 'haystack' + }).selector(':parent <-> node').css({ + 'curve-style': 'bezier', + 'source-endpoint': 'outside-to-line', + 'target-endpoint': 'outside-to-line' + }).selector(':selected').css({ + 'background-color': '#0169D9', + 'line-color': '#0169D9', + 'source-arrow-color': '#0169D9', + 'target-arrow-color': '#0169D9', + 'mid-source-arrow-color': '#0169D9', + 'mid-target-arrow-color': '#0169D9' + }).selector('node:parent:selected').css({ + 'background-color': '#CCE1F9', + 'border-color': '#aec8e5' + }).selector(':active').css({ + 'overlay-color': 'black', + 'overlay-padding': 10, + 'overlay-opacity': 0.25 + }).selector('core') // just core properties + .css({ + 'selection-box-color': '#ddd', + 'selection-box-opacity': 0.65, + 'selection-box-border-color': '#aaa', + 'selection-box-border-width': 1, + 'active-bg-color': 'black', + 'active-bg-opacity': 0.15, + 'active-bg-size': 30, + 'outside-texture-bg-color': '#000', + 'outside-texture-bg-opacity': 0.125 + }); + + this.defaultLength = this.length; +}; + +module.exports = styfn; + +/***/ }), +/* 93 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var util = __webpack_require__(1); +var is = __webpack_require__(0); +var math = __webpack_require__(2); + +var styfn = {}; + +// a caching layer for property parsing +styfn.parse = function (name, value, propIsBypass, propIsFlat) { + var self = this; + + // function values can't be cached in all cases, and there isn't much benefit of caching them anyway + if (is.fn(value)) { + return self.parseImplWarn(name, value, propIsBypass, propIsFlat); + } + + var flatKey = propIsFlat === 'mapping' || propIsFlat === true || propIsFlat === false || propIsFlat == null ? 'dontcare' : propIsFlat; + var argHash = [name, value, propIsBypass, flatKey].join('$'); + var propCache = self.propCache = self.propCache || {}; + var ret = void 0; + + if (!(ret = propCache[argHash])) { + ret = propCache[argHash] = self.parseImplWarn(name, value, propIsBypass, propIsFlat); + } + + // - bypasses can't be shared b/c the value can be changed by animations or otherwise overridden + // - mappings can't be shared b/c mappings are per-element + if (propIsBypass || propIsFlat === 'mapping') { + // need a copy since props are mutated later in their lifecycles + ret = util.copy(ret); + + if (ret) { + ret.value = util.copy(ret.value); // because it could be an array, e.g. colour + } + } + + return ret; +}; + +styfn.parseImplWarn = function (name, value, propIsBypass, propIsFlat) { + var prop = this.parseImpl(name, value, propIsBypass, propIsFlat); + + if (!prop && value != null) { + util.error('The style property `%s: %s` is invalid', name, value); + } + + return prop; +}; + +// parse a property; return null on invalid; return parsed property otherwise +// fields : +// - name : the name of the property +// - value : the parsed, native-typed value of the property +// - strValue : a string value that represents the property value in valid css +// - bypass : true iff the property is a bypass property +styfn.parseImpl = function (name, value, propIsBypass, propIsFlat) { + var self = this; + + name = util.camel2dash(name); // make sure the property name is in dash form (e.g. 'property-name' not 'propertyName') + + var property = self.properties[name]; + var passedValue = value; + var types = self.types; + + if (!property) { + return null; + } // return null on property of unknown name + if (value === undefined) { + return null; + } // can't assign undefined + + // the property may be an alias + if (property.alias) { + property = property.pointsTo; + name = property.name; + } + + var valueIsString = is.string(value); + if (valueIsString) { + // trim the value to make parsing easier + value = value.trim(); + } + + var type = property.type; + if (!type) { + return null; + } // no type, no luck + + // check if bypass is null or empty string (i.e. indication to delete bypass property) + if (propIsBypass && (value === '' || value === null)) { + return { + name: name, + value: value, + bypass: true, + deleteBypass: true + }; + } + + // check if value is a function used as a mapper + if (is.fn(value)) { + return { + name: name, + value: value, + strValue: 'fn', + mapped: types.fn, + bypass: propIsBypass + }; + } + + // check if value is mapped + var data = void 0, + mapData = void 0; + if (!valueIsString || propIsFlat) { + // then don't bother to do the expensive regex checks + + } else if (data = new RegExp(types.data.regex).exec(value)) { + if (propIsBypass) { + return false; + } // mappers not allowed in bypass + + var mapped = types.data; + + return { + name: name, + value: data, + strValue: '' + value, + mapped: mapped, + field: data[1], + bypass: propIsBypass + }; + } else if (mapData = new RegExp(types.mapData.regex).exec(value)) { + if (propIsBypass) { + return false; + } // mappers not allowed in bypass + if (type.multiple) { + return false; + } // impossible to map to num + + var _mapped = types.mapData; + + // we can map only if the type is a colour or a number + if (!(type.color || type.number)) { + return false; + } + + var valueMin = this.parse(name, mapData[4]); // parse to validate + if (!valueMin || valueMin.mapped) { + return false; + } // can't be invalid or mapped + + var valueMax = this.parse(name, mapData[5]); // parse to validate + if (!valueMax || valueMax.mapped) { + return false; + } // can't be invalid or mapped + + // check if valueMin and valueMax are the same + if (valueMin.value === valueMax.value) { + return false; // can't make much of a mapper without a range + } else if (type.color) { + var c1 = valueMin.value; + var c2 = valueMax.value; + + var same = c1[0] === c2[0] // red + && c1[1] === c2[1] // green + && c1[2] === c2[2] // blue + && ( // optional alpha + c1[3] === c2[3] // same alpha outright + || (c1[3] == null || c1[3] === 1) && ( // full opacity for colour 1? + c2[3] == null || c2[3] === 1) // full opacity for colour 2? + ); + + if (same) { + return false; + } // can't make a mapper without a range + } + + return { + name: name, + value: mapData, + strValue: '' + value, + mapped: _mapped, + field: mapData[1], + fieldMin: parseFloat(mapData[2]), // min & max are numeric + fieldMax: parseFloat(mapData[3]), + valueMin: valueMin.value, + valueMax: valueMax.value, + bypass: propIsBypass + }; + } + + if (type.multiple && propIsFlat !== 'multiple') { + var vals = void 0; + + if (valueIsString) { + vals = value.split(/\s+/); + } else if (is.array(value)) { + vals = value; + } else { + vals = [value]; + } + + if (type.evenMultiple && vals.length % 2 !== 0) { + return null; + } + + var valArr = []; + var unitsArr = []; + var pfValArr = []; + var hasEnum = false; + + for (var i = 0; i < vals.length; i++) { + var p = self.parse(name, vals[i], propIsBypass, 'multiple'); + + hasEnum = hasEnum || is.string(p.value); + + valArr.push(p.value); + pfValArr.push(p.pfValue != null ? p.pfValue : p.value); + unitsArr.push(p.units); + } + + if (type.validate && !type.validate(valArr, unitsArr)) { + return null; + } + + if (type.singleEnum && hasEnum) { + if (valArr.length === 1 && is.string(valArr[0])) { + return { + name: name, + value: valArr[0], + strValue: valArr[0], + bypass: propIsBypass + }; + } else { + return null; + } + } + + return { + name: name, + value: valArr, + pfValue: pfValArr, + strValue: valArr.map(function (val, i) { + return val + (unitsArr[i] || ''); + }).join(' '), + bypass: propIsBypass, + units: unitsArr + }; + } + + // several types also allow enums + var checkEnums = function checkEnums() { + for (var _i = 0; _i < type.enums.length; _i++) { + var en = type.enums[_i]; + + if (en === value) { + return { + name: name, + value: value, + strValue: '' + value, + bypass: propIsBypass + }; + } + } + + return null; + }; + + // check the type and return the appropriate object + if (type.number) { + var units = void 0; + var implicitUnits = 'px'; // not set => px + + if (type.units) { + // use specified units if set + units = type.units; + } + + if (type.implicitUnits) { + implicitUnits = type.implicitUnits; + } + + if (!type.unitless) { + if (valueIsString) { + var unitsRegex = 'px|em' + (type.allowPercent ? '|\\%' : ''); + if (units) { + unitsRegex = units; + } // only allow explicit units if so set + var match = value.match('^(' + util.regex.number + ')(' + unitsRegex + ')?' + '$'); + + if (match) { + value = match[1]; + units = match[2] || implicitUnits; + } + } else if (!units || type.implicitUnits) { + units = implicitUnits; // implicitly px if unspecified + } + } + + value = parseFloat(value); + + // if not a number and enums not allowed, then the value is invalid + if (isNaN(value) && type.enums === undefined) { + return null; + } + + // check if this number type also accepts special keywords in place of numbers + // (i.e. `left`, `auto`, etc) + if (isNaN(value) && type.enums !== undefined) { + value = passedValue; + + return checkEnums(); + } + + // check if value must be an integer + if (type.integer && !is.integer(value)) { + return null; + } + + // check value is within range + if (type.min !== undefined && (value < type.min || type.strictMin && value === type.min) || type.max !== undefined && (value > type.max || type.strictMax && value === type.max)) { + return null; + } + + var ret = { + name: name, + value: value, + strValue: '' + value + (units ? units : ''), + units: units, + bypass: propIsBypass + }; + + // normalise value in pixels + if (type.unitless || units !== 'px' && units !== 'em') { + ret.pfValue = value; + } else { + ret.pfValue = units === 'px' || !units ? value : this.getEmSizeInPixels() * value; + } + + // normalise value in ms + if (units === 'ms' || units === 's') { + ret.pfValue = units === 'ms' ? value : 1000 * value; + } + + // normalise value in rad + if (units === 'deg' || units === 'rad') { + ret.pfValue = units === 'rad' ? value : math.deg2rad(value); + } + + // normalize value in % + if (units === '%') { + ret.pfValue = value / 100; + } + + return ret; + } else if (type.propList) { + + var props = []; + var propsStr = '' + value; + + if (propsStr === 'none') { + // leave empty + + } else { + // go over each prop + + var propsSplit = propsStr.split(','); + for (var _i2 = 0; _i2 < propsSplit.length; _i2++) { + var propName = propsSplit[_i2].trim(); + + if (self.properties[propName]) { + props.push(propName); + } + } + + if (props.length === 0) { + return null; + } + } + + return { + name: name, + value: props, + strValue: props.length === 0 ? 'none' : props.join(', '), + bypass: propIsBypass + }; + } else if (type.color) { + var tuple = util.color2tuple(value); + + if (!tuple) { + return null; + } + + return { + name: name, + value: tuple, + pfValue: tuple, + strValue: '' + value, + bypass: propIsBypass + }; + } else if (type.regex || type.regexes) { + + // first check enums + if (type.enums) { + var enumProp = checkEnums(); + + if (enumProp) { + return enumProp; + } + } + + var regexes = type.regexes ? type.regexes : [type.regex]; + + for (var _i3 = 0; _i3 < regexes.length; _i3++) { + var regex = new RegExp(regexes[_i3]); // make a regex from the type string + var m = regex.exec(value); + + if (m) { + // regex matches + return { + name: name, + value: type.singleRegexMatchValue ? m[1] : m, + strValue: '' + value, + bypass: propIsBypass + }; + } + } + + return null; // didn't match any + } else if (type.string) { + // just return + return { + name: name, + value: '' + value, + strValue: '' + value, + bypass: propIsBypass + }; + } else if (type.enums) { + // check enums last because it's a combo type in others + return checkEnums(); + } else { + return null; // not a type we can handle + } +}; + +module.exports = styfn; + +/***/ }), +/* 94 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var is = __webpack_require__(0); +var window = __webpack_require__(3); +var math = __webpack_require__(2); + +var corefn = { + + autolock: function autolock(bool) { + if (bool !== undefined) { this._private.autolock = bool ? true : false; } else { return this._private.autolock; @@ -7546,8 +16886,8 @@ var corefn = ({ return this; // chaining }, - autoungrabify: function( bool ){ - if( bool !== undefined ){ + autoungrabify: function autoungrabify(bool) { + if (bool !== undefined) { this._private.autoungrabify = bool ? true : false; } else { return this._private.autoungrabify; @@ -7556,8 +16896,8 @@ var corefn = ({ return this; // chaining }, - autounselectify: function( bool ){ - if( bool !== undefined ){ + autounselectify: function autounselectify(bool) { + if (bool !== undefined) { this._private.autounselectify = bool ? true : false; } else { return this._private.autounselectify; @@ -7566,8 +16906,8 @@ var corefn = ({ return this; // chaining }, - panningEnabled: function( bool ){ - if( bool !== undefined ){ + panningEnabled: function panningEnabled(bool) { + if (bool !== undefined) { this._private.panningEnabled = bool ? true : false; } else { return this._private.panningEnabled; @@ -7576,8 +16916,8 @@ var corefn = ({ return this; // chaining }, - userPanningEnabled: function( bool ){ - if( bool !== undefined ){ + userPanningEnabled: function userPanningEnabled(bool) { + if (bool !== undefined) { this._private.userPanningEnabled = bool ? true : false; } else { return this._private.userPanningEnabled; @@ -7586,8 +16926,8 @@ var corefn = ({ return this; // chaining }, - zoomingEnabled: function( bool ){ - if( bool !== undefined ){ + zoomingEnabled: function zoomingEnabled(bool) { + if (bool !== undefined) { this._private.zoomingEnabled = bool ? true : false; } else { return this._private.zoomingEnabled; @@ -7596,8 +16936,8 @@ var corefn = ({ return this; // chaining }, - userZoomingEnabled: function( bool ){ - if( bool !== undefined ){ + userZoomingEnabled: function userZoomingEnabled(bool) { + if (bool !== undefined) { this._private.userZoomingEnabled = bool ? true : false; } else { return this._private.userZoomingEnabled; @@ -7606,8 +16946,8 @@ var corefn = ({ return this; // chaining }, - boxSelectionEnabled: function( bool ){ - if( bool !== undefined ){ + boxSelectionEnabled: function boxSelectionEnabled(bool) { + if (bool !== undefined) { this._private.boxSelectionEnabled = bool ? true : false; } else { return this._private.boxSelectionEnabled; @@ -7616,154 +16956,168 @@ var corefn = ({ return this; // chaining }, - pan: function(){ + pan: function pan() { var args = arguments; var pan = this._private.pan; - var dim, val, dims, x, y; + var dim = void 0, + val = void 0, + dims = void 0, + x = void 0, + y = void 0; - switch( args.length ){ - case 0: // .pan() - return pan; + switch (args.length) { + case 0: + // .pan() + return pan; - case 1: + case 1: - if( is.string( args[0] ) ){ // .pan('x') - dim = args[0]; - return pan[ dim ]; + if (is.string(args[0])) { + // .pan('x') + dim = args[0]; + return pan[dim]; + } else if (is.plainObject(args[0])) { + // .pan({ x: 0, y: 100 }) + if (!this._private.panningEnabled) { + return this; + } - } else if( is.plainObject( args[0] ) ){ // .pan({ x: 0, y: 100 }) - if( !this._private.panningEnabled ){ + dims = args[0]; + x = dims.x; + y = dims.y; + + if (is.number(x)) { + pan.x = x; + } + + if (is.number(y)) { + pan.y = y; + } + + this.emit('pan viewport'); + } + break; + + case 2: + // .pan('x', 100) + if (!this._private.panningEnabled) { return this; } - dims = args[0]; - x = dims.x; - y = dims.y; + dim = args[0]; + val = args[1]; - if( is.number( x ) ){ - pan.x = x; + if ((dim === 'x' || dim === 'y') && is.number(val)) { + pan[dim] = val; } - if( is.number( y ) ){ - pan.y = y; - } + this.emit('pan viewport'); + break; - this.trigger( 'pan viewport' ); - } - break; - - case 2: // .pan('x', 100) - if( !this._private.panningEnabled ){ - return this; - } - - dim = args[0]; - val = args[1]; - - if( (dim === 'x' || dim === 'y') && is.number( val ) ){ - pan[ dim ] = val; - } - - this.trigger( 'pan viewport' ); - break; - - default: - break; // invalid + default: + break; // invalid } - this.notify( { // notify the renderer that the viewport changed + this.notify({ // notify the renderer that the viewport changed type: 'viewport' - } ); + }); return this; // chaining }, - panBy: function( params ){ + panBy: function panBy(arg0, arg1) { var args = arguments; var pan = this._private.pan; - var dim, val, dims, x, y; + var dim = void 0, + val = void 0, + dims = void 0, + x = void 0, + y = void 0; - if( !this._private.panningEnabled ){ + if (!this._private.panningEnabled) { return this; } - switch( args.length ){ - case 1: + switch (args.length) { + case 1: - if( is.plainObject( args[0] ) ){ // .panBy({ x: 0, y: 100 }) - dims = args[0]; - x = dims.x; - y = dims.y; + if (is.plainObject(arg0)) { + // .panBy({ x: 0, y: 100 }) + dims = args[0]; + x = dims.x; + y = dims.y; - if( is.number( x ) ){ - pan.x += x; + if (is.number(x)) { + pan.x += x; + } + + if (is.number(y)) { + pan.y += y; + } + + this.emit('pan viewport'); + } + break; + + case 2: + // .panBy('x', 100) + dim = arg0; + val = arg1; + + if ((dim === 'x' || dim === 'y') && is.number(val)) { + pan[dim] += val; } - if( is.number( y ) ){ - pan.y += y; - } + this.emit('pan viewport'); + break; - this.trigger( 'pan viewport' ); - } - break; - - case 2: // .panBy('x', 100) - dim = args[0]; - val = args[1]; - - if( (dim === 'x' || dim === 'y') && is.number( val ) ){ - pan[ dim ] += val; - } - - this.trigger( 'pan viewport' ); - break; - - default: - break; // invalid + default: + break; // invalid } - this.notify( { // notify the renderer that the viewport changed + this.notify({ // notify the renderer that the viewport changed type: 'viewport' - } ); + }); return this; // chaining }, - fit: function( elements, padding ){ - var viewportState = this.getFitViewport( elements, padding ); + fit: function fit(elements, padding) { + var viewportState = this.getFitViewport(elements, padding); - if( viewportState ){ + if (viewportState) { var _p = this._private; _p.zoom = viewportState.zoom; _p.pan = viewportState.pan; - this.trigger( 'pan zoom viewport' ); + this.emit('pan zoom viewport'); - this.notify( { // notify the renderer that the viewport changed + this.notify({ // notify the renderer that the viewport changed type: 'viewport' - } ); + }); } return this; // chaining }, - getFitViewport: function( elements, padding ){ - if( is.number( elements ) && padding === undefined ){ // elements is optional + getFitViewport: function getFitViewport(elements, padding) { + if (is.number(elements) && padding === undefined) { + // elements is optional padding = elements; elements = undefined; } - if( !this._private.panningEnabled || !this._private.zoomingEnabled ){ + if (!this._private.panningEnabled || !this._private.zoomingEnabled) { return; } - var bb; + var bb = void 0; - if( is.string( elements ) ){ + if (is.string(elements)) { var sel = elements; - elements = this.$( sel ); - - } else if( is.boundingBox( elements ) ){ // assume bb + elements = this.$(sel); + } else if (is.boundingBox(elements)) { + // assume bb var bbe = elements; bb = { x1: bbe.x1, @@ -7774,28 +17128,31 @@ var corefn = ({ bb.w = bb.x2 - bb.x1; bb.h = bb.y2 - bb.y1; - - } else if( !is.elementOrCollection( elements ) ){ + } else if (!is.elementOrCollection(elements)) { elements = this.mutableElements(); } + if (is.elementOrCollection(elements) && elements.empty()) { + return; + } // can't fit to nothing + bb = bb || elements.boundingBox(); var w = this.width(); var h = this.height(); - var zoom; - padding = is.number( padding ) ? padding : 0; + var zoom = void 0; + padding = is.number(padding) ? padding : 0; - if( !isNaN( w ) && !isNaN( h ) && w > 0 && h > 0 && !isNaN( bb.w ) && !isNaN( bb.h ) && bb.w > 0 && bb.h > 0 ){ - zoom = Math.min( (w - 2 * padding) / bb.w, (h - 2 * padding) / bb.h ); + if (!isNaN(w) && !isNaN(h) && w > 0 && h > 0 && !isNaN(bb.w) && !isNaN(bb.h) && bb.w > 0 && bb.h > 0) { + zoom = Math.min((w - 2 * padding) / bb.w, (h - 2 * padding) / bb.h); // crop zoom zoom = zoom > this._private.maxZoom ? this._private.maxZoom : zoom; zoom = zoom < this._private.minZoom ? this._private.minZoom : zoom; var pan = { // now pan to middle - x: (w - zoom * ( bb.x1 + bb.x2 )) / 2, - y: (h - zoom * ( bb.y1 + bb.y2 )) / 2 + x: (w - zoom * (bb.x1 + bb.x2)) / 2, + y: (h - zoom * (bb.y1 + bb.y2)) / 2 }; return { @@ -7807,72 +17164,71 @@ var corefn = ({ return; }, - minZoom: function( zoom ){ - if( zoom === undefined ){ + minZoom: function minZoom(zoom) { + if (zoom === undefined) { return this._private.minZoom; - } else if( is.number( zoom ) ){ + } else if (is.number(zoom)) { this._private.minZoom = zoom; } return this; }, - maxZoom: function( zoom ){ - if( zoom === undefined ){ + maxZoom: function maxZoom(zoom) { + if (zoom === undefined) { return this._private.maxZoom; - } else if( is.number( zoom ) ){ + } else if (is.number(zoom)) { this._private.maxZoom = zoom; } return this; }, - zoom: function( params ){ - var pos; // in rendered px - var zoom; + getZoomedViewport: function getZoomedViewport(params) { + var _p = this._private; + var currentPan = _p.pan; + var currentZoom = _p.zoom; + var pos = void 0; // in rendered px + var zoom = void 0; + var bail = false; - if( params === undefined ){ // then get the zoom - return this._private.zoom; + if (!_p.zoomingEnabled) { + // zooming disabled + bail = true; + } - } else if( is.number( params ) ){ // then set the zoom + if (is.number(params)) { + // then set the zoom zoom = params; - - } else if( is.plainObject( params ) ){ // then zoom about a point + } else if (is.plainObject(params)) { + // then zoom about a point zoom = params.level; - if( params.position ){ - var p = params.position; - var pan = this._private.pan; - var z = this._private.zoom; - - pos = { // convert to rendered px - x: p.x * z + pan.x, - y: p.y * z + pan.y - }; - } else if( params.renderedPosition ){ + if (params.position != null) { + pos = math.modelToRenderedPosition(params.position, currentZoom, currentPan); + } else if (params.renderedPosition != null) { pos = params.renderedPosition; } - if( pos && !this._private.panningEnabled ){ - return this; // panning disabled + if (pos != null && !_p.panningEnabled) { + // panning disabled + bail = true; } } - if( !this._private.zoomingEnabled ){ - return this; // zooming disabled - } - - if( !is.number( zoom ) || ( pos && (!is.number( pos.x ) || !is.number( pos.y )) ) ){ - return this; // can't zoom with invalid params - } - // crop zoom - zoom = zoom > this._private.maxZoom ? this._private.maxZoom : zoom; - zoom = zoom < this._private.minZoom ? this._private.minZoom : zoom; + zoom = zoom > _p.maxZoom ? _p.maxZoom : zoom; + zoom = zoom < _p.minZoom ? _p.minZoom : zoom; - if( pos ){ // set zoom about position - var pan1 = this._private.pan; - var zoom1 = this._private.zoom; + // can't zoom with invalid params + if (bail || !is.number(zoom) || zoom === currentZoom || pos != null && (!is.number(pos.x) || !is.number(pos.y))) { + return null; + } + + if (pos != null) { + // set zoom about position + var pan1 = currentPan; + var zoom1 = currentZoom; var zoom2 = zoom; var pan2 = { @@ -7880,25 +17236,54 @@ var corefn = ({ y: -zoom2 / zoom1 * (pos.y - pan1.y) + pos.y }; - this._private.zoom = zoom; - this._private.pan = pan2; - - var posChanged = pan1.x !== pan2.x || pan1.y !== pan2.y; - this.trigger( ' zoom ' + (posChanged ? ' pan ' : '') + ' viewport ' ); - - } else { // just set the zoom - this._private.zoom = zoom; - this.trigger( 'zoom viewport' ); + return { + zoomed: true, + panned: true, + zoom: zoom2, + pan: pan2 + }; + } else { + // just set the zoom + return { + zoomed: true, + panned: false, + zoom: zoom, + pan: currentPan + }; } - - this.notify( { // notify the renderer that the viewport changed - type: 'viewport' - } ); - - return this; // chaining }, - viewport: function( opts ){ + zoom: function zoom(params) { + if (params === undefined) { + // get + return this._private.zoom; + } else { + // set + var vp = this.getZoomedViewport(params); + var _p = this._private; + + if (vp == null || !vp.zoomed) { + return this; + } + + _p.zoom = vp.zoom; + + if (vp.panned) { + _p.pan.x = vp.pan.x; + _p.pan.y = vp.pan.y; + } + + this.emit('zoom' + (vp.panned ? ' pan' : '') + ' viewport'); + + this.notify({ // notify the renderer that the viewport changed + type: 'viewport' + }); + + return this; // chaining + } + }, + + viewport: function viewport(opts) { var _p = this._private; var zoomDefd = true; var panDefd = true; @@ -7906,143 +17291,161 @@ var corefn = ({ var zoomFailed = false; var panFailed = false; - if( !opts ){ return this; } - if( !is.number( opts.zoom ) ){ zoomDefd = false; } - if( !is.plainObject( opts.pan ) ){ panDefd = false; } - if( !zoomDefd && !panDefd ){ return this; } + if (!opts) { + return this; + } + if (!is.number(opts.zoom)) { + zoomDefd = false; + } + if (!is.plainObject(opts.pan)) { + panDefd = false; + } + if (!zoomDefd && !panDefd) { + return this; + } - if( zoomDefd ){ + if (zoomDefd) { var z = opts.zoom; - if( z < _p.minZoom || z > _p.maxZoom || !_p.zoomingEnabled ){ + if (z < _p.minZoom || z > _p.maxZoom || !_p.zoomingEnabled) { zoomFailed = true; - } else { _p.zoom = z; - events.push( 'zoom' ); + events.push('zoom'); } } - if( panDefd && (!zoomFailed || !opts.cancelOnFailedZoom) && _p.panningEnabled ){ + if (panDefd && (!zoomFailed || !opts.cancelOnFailedZoom) && _p.panningEnabled) { var p = opts.pan; - if( is.number( p.x ) ){ + if (is.number(p.x)) { _p.pan.x = p.x; panFailed = false; } - if( is.number( p.y ) ){ + if (is.number(p.y)) { _p.pan.y = p.y; panFailed = false; } - if( !panFailed ){ - events.push( 'pan' ); + if (!panFailed) { + events.push('pan'); } } - if( events.length > 0 ){ - events.push( 'viewport' ); - this.trigger( events.join( ' ' ) ); + if (events.length > 0) { + events.push('viewport'); + this.emit(events.join(' ')); - this.notify( { + this.notify({ type: 'viewport' - } ); + }); } return this; // chaining }, - center: function( elements ){ - var pan = this.getCenterPan( elements ); + center: function center(elements) { + var pan = this.getCenterPan(elements); - if( pan ){ + if (pan) { this._private.pan = pan; - this.trigger( 'pan viewport' ); + this.emit('pan viewport'); - this.notify( { // notify the renderer that the viewport changed + this.notify({ // notify the renderer that the viewport changed type: 'viewport' - } ); + }); } return this; // chaining }, - getCenterPan: function( elements, zoom ){ - if( !this._private.panningEnabled ){ + getCenterPan: function getCenterPan(elements, zoom) { + if (!this._private.panningEnabled) { return; } - if( is.string( elements ) ){ + if (is.string(elements)) { var selector = elements; - elements = this.mutableElements().filter( selector ); - } else if( !is.elementOrCollection( elements ) ){ + elements = this.mutableElements().filter(selector); + } else if (!is.elementOrCollection(elements)) { elements = this.mutableElements(); } + if (elements.length === 0) { + return; + } // can't centre pan to nothing + var bb = elements.boundingBox(); var w = this.width(); var h = this.height(); zoom = zoom === undefined ? this._private.zoom : zoom; var pan = { // middle - x: (w - zoom * ( bb.x1 + bb.x2 )) / 2, - y: (h - zoom * ( bb.y1 + bb.y2 )) / 2 + x: (w - zoom * (bb.x1 + bb.x2)) / 2, + y: (h - zoom * (bb.y1 + bb.y2)) / 2 }; return pan; }, - reset: function(){ - if( !this._private.panningEnabled || !this._private.zoomingEnabled ){ + reset: function reset() { + if (!this._private.panningEnabled || !this._private.zoomingEnabled) { return this; } - this.viewport( { + this.viewport({ pan: { x: 0, y: 0 }, zoom: 1 - } ); + }); return this; // chaining }, - invalidateSize: function(){ + invalidateSize: function invalidateSize() { this._private.sizeCache = null; }, - size: function(){ + size: function size() { var _p = this._private; var container = _p.container; - return ( _p.sizeCache = _p.sizeCache || ( container ? { - width: container.clientWidth, - height: container.clientHeight - } : { // fallback if no container (not 0 b/c can be used for dividing etc) + return _p.sizeCache = _p.sizeCache || (container ? function () { + var style = window.getComputedStyle(container); + var val = function val(name) { + return parseFloat(style.getPropertyValue(name)); + }; + + return { + width: container.clientWidth - val('padding-left') - val('padding-right'), + height: container.clientHeight - val('padding-top') - val('padding-bottom') + }; + }() : { // fallback if no container (not 0 b/c can be used for dividing etc) width: 1, height: 1 - } ) ); + }); }, - width: function(){ + width: function width() { return this.size().width; }, - height: function(){ + height: function height() { return this.size().height; }, - extent: function(){ + extent: function extent() { var pan = this._private.pan; var zoom = this._private.zoom; var rb = this.renderedExtent(); var b = { - x1: ( rb.x1 - pan.x ) / zoom, - x2: ( rb.x2 - pan.x ) / zoom, - y1: ( rb.y1 - pan.y ) / zoom, - y2: ( rb.y2 - pan.y ) / zoom + x1: (rb.x1 - pan.x) / zoom, + x2: (rb.x2 - pan.x) / zoom, + y1: (rb.y1 - pan.y) / zoom, + y2: (rb.y2 - pan.y) / zoom }; b.w = b.x2 - b.x1; @@ -8051,7 +17454,7 @@ var corefn = ({ return b; }, - renderedExtent: function(){ + renderedExtent: function renderedExtent() { var width = this.width(); var height = this.height(); @@ -8064,7 +17467,7 @@ var corefn = ({ h: height }; } -}); +}; // aliases corefn.centre = corefn.center; @@ -8075,946 +17478,20 @@ corefn.autoungrabifyNodes = corefn.autoungrabify; module.exports = corefn; -},{"../is":83}],44:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 95 */ +/***/ (function(module, exports, __webpack_require__) { -// use this module to cherry pick functions into your prototype -// (useful for functions shared between the core and collections, for example) +"use strict"; -// e.g. -// var foo = define.foo({ /* params... */ }) -var util = _dereq_( './util' ); -var is = _dereq_( './is' ); -var Selector = _dereq_( './selector' ); -var Promise = _dereq_( './promise' ); -var Event = _dereq_( './event' ); -var Animation = _dereq_( './animation' ); - -var define = { - - // access data field - data: function( params ){ - var defaults = { - field: 'data', - bindingEvent: 'data', - allowBinding: false, - allowSetting: false, - allowGetting: false, - settingEvent: 'data', - settingTriggersEvent: false, - triggerFnName: 'trigger', - immutableKeys: {}, // key => true if immutable - updateStyle: false, - onSet: function( self ){}, - canSet: function( self ){ return true; } - }; - params = util.extend( {}, defaults, params ); - - return function dataImpl( name, value ){ - var p = params; - var self = this; - var selfIsArrayLike = self.length !== undefined; - var all = selfIsArrayLike ? self : [ self ]; // put in array if not array-like - var single = selfIsArrayLike ? self[0] : self; - - // .data('foo', ...) - if( is.string( name ) ){ // set or get property - - // .data('foo') - if( p.allowGetting && value === undefined ){ // get - - var ret; - if( single ){ - ret = single._private[ p.field ][ name ]; - } - return ret; - - // .data('foo', 'bar') - } else if( p.allowSetting && value !== undefined ){ // set - var valid = !p.immutableKeys[ name ]; - if( valid ){ - for( var i = 0, l = all.length; i < l; i++ ){ - if( p.canSet( all[ i ] ) ){ - all[ i ]._private[ p.field ][ name ] = value; - } - } - - // update mappers if asked - if( p.updateStyle ){ self.updateStyle(); } - - // call onSet callback - p.onSet( self ); - - if( p.settingTriggersEvent ){ - self[ p.triggerFnName ]( p.settingEvent ); - } - } - } - - // .data({ 'foo': 'bar' }) - } else if( p.allowSetting && is.plainObject( name ) ){ // extend - var obj = name; - var k, v; - var keys = Object.keys( obj ); - - for( var i = 0; i < keys.length; i++ ){ - k = keys[ i ]; - v = obj[ k ]; - - var valid = !p.immutableKeys[ k ]; - if( valid ){ - for( var j = 0; j < all.length; j++ ){ - var ele = all[j]; - - if( p.canSet( ele ) ){ - ele._private[ p.field ][ k ] = v; - } - } - } - } - - // update mappers if asked - if( p.updateStyle ){ self.updateStyle(); } - - // call onSet callback - p.onSet( self ); - - if( p.settingTriggersEvent ){ - self[ p.triggerFnName ]( p.settingEvent ); - } - - // .data(function(){ ... }) - } else if( p.allowBinding && is.fn( name ) ){ // bind to event - var fn = name; - self.on( p.bindingEvent, fn ); - - // .data() - } else if( p.allowGetting && name === undefined ){ // get whole object - var ret; - if( single ){ - ret = single._private[ p.field ]; - } - return ret; - } - - return self; // maintain chainability - }; // function - }, // data - - // remove data field - removeData: function( params ){ - var defaults = { - field: 'data', - event: 'data', - triggerFnName: 'trigger', - triggerEvent: false, - immutableKeys: {} // key => true if immutable - }; - params = util.extend( {}, defaults, params ); - - return function removeDataImpl( names ){ - var p = params; - var self = this; - var selfIsArrayLike = self.length !== undefined; - var all = selfIsArrayLike ? self : [ self ]; // put in array if not array-like - - // .removeData('foo bar') - if( is.string( names ) ){ // then get the list of keys, and delete them - var keys = names.split( /\s+/ ); - var l = keys.length; - - for( var i = 0; i < l; i++ ){ // delete each non-empty key - var key = keys[ i ]; - if( is.emptyString( key ) ){ continue; } - - var valid = !p.immutableKeys[ key ]; // not valid if immutable - if( valid ){ - for( var i_a = 0, l_a = all.length; i_a < l_a; i_a++ ){ - all[ i_a ]._private[ p.field ][ key ] = undefined; - } - } - } - - if( p.triggerEvent ){ - self[ p.triggerFnName ]( p.event ); - } - - // .removeData() - } else if( names === undefined ){ // then delete all keys - - for( var i_a = 0, l_a = all.length; i_a < l_a; i_a++ ){ - var _privateFields = all[ i_a ]._private[ p.field ]; - var keys = Object.keys( _privateFields ); - - for( var i = 0; i < keys.length; i++ ){ - var key = keys[i]; - var validKeyToDelete = !p.immutableKeys[ key ]; - - if( validKeyToDelete ){ - _privateFields[ key ] = undefined; - } - } - } - - if( p.triggerEvent ){ - self[ p.triggerFnName ]( p.event ); - } - } - - return self; // maintain chaining - }; // function - }, // removeData - - // event function reusable stuff - event: { - regex: /(\w+)(\.(?:\w+|\*))?/, // regex for matching event strings (e.g. "click.namespace") - universalNamespace: '.*', // matches as if no namespace specified and prevents users from unbinding accidentally - optionalTypeRegex: /(\w+)?(\.(?:\w+|\*))?/, - falseCallback: function(){ return false; } - }, - - // event binding - on: function( params ){ - var defaults = { - unbindSelfOnTrigger: false, - unbindAllBindersOnTrigger: false - }; - params = util.extend( {}, defaults, params ); - - return function onImpl( events, selector, data, callback ){ - var self = this; - var selfIsArrayLike = self.length !== undefined; - var all = selfIsArrayLike ? self : [ self ]; // put in array if not array-like - var eventsIsString = is.string( events ); - var p = params; - - if( is.plainObject( selector ) ){ // selector is actually data - callback = data; - data = selector; - selector = undefined; - } else if( is.fn( selector ) || selector === false ){ // selector is actually callback - callback = selector; - data = undefined; - selector = undefined; - } - - if( is.fn( data ) || data === false ){ // data is actually callback - callback = data; - data = undefined; - } - - // if there isn't a callback, we can't really do anything - // (can't speak for mapped events arg version) - if( !(is.fn( callback ) || callback === false) && eventsIsString ){ - return self; // maintain chaining - } - - if( eventsIsString ){ // then convert to map - var map = {}; - map[ events ] = callback; - events = map; - } - - var keys = Object.keys( events ); - - for( var k = 0; k < keys.length; k++ ){ - var evts = keys[k]; - - callback = events[ evts ]; - if( callback === false ){ - callback = define.event.falseCallback; - } - - if( !is.fn( callback ) ){ continue; } - - evts = evts.split( /\s+/ ); - for( var i = 0; i < evts.length; i++ ){ - var evt = evts[ i ]; - if( is.emptyString( evt ) ){ continue; } - - var match = evt.match( define.event.regex ); // type[.namespace] - - if( match ){ - var type = match[1]; - var namespace = match[2] ? match[2] : undefined; - - var listener = { - callback: callback, // callback to run - data: data, // extra data in eventObj.data - delegated: selector ? true : false, // whether the evt is delegated - selector: selector, // the selector to match for delegated events - selObj: new Selector( selector ), // cached selector object to save rebuilding - type: type, // the event type (e.g. 'click') - namespace: namespace, // the event namespace (e.g. ".foo") - unbindSelfOnTrigger: p.unbindSelfOnTrigger, - unbindAllBindersOnTrigger: p.unbindAllBindersOnTrigger, - binders: all // who bound together - }; - - for( var j = 0; j < all.length; j++ ){ - var _p = all[ j ]._private = all[ j ]._private || {}; - - _p.listeners = _p.listeners || []; - _p.listeners.push( listener ); - } - } - } // for events array - } // for events map - - return self; // maintain chaining - }; // function - }, // on - - eventAliasesOn: function( proto ){ - var p = proto; - - p.addListener = p.listen = p.bind = p.on; - p.removeListener = p.unlisten = p.unbind = p.off; - p.emit = p.trigger; - - // this is just a wrapper alias of .on() - p.pon = p.promiseOn = function( events, selector ){ - var self = this; - var args = Array.prototype.slice.call( arguments, 0 ); - - return new Promise( function( resolve, reject ){ - var callback = function( e ){ - self.off.apply( self, offArgs ); - - resolve( e ); - }; - - var onArgs = args.concat( [ callback ] ); - var offArgs = onArgs.concat( [] ); - - self.on.apply( self, onArgs ); - } ); - }; - }, - - off: function offImpl( params ){ - var defaults = { - }; - params = util.extend( {}, defaults, params ); - - return function( events, selector, callback ){ - var self = this; - var selfIsArrayLike = self.length !== undefined; - var all = selfIsArrayLike ? self : [ self ]; // put in array if not array-like - var eventsIsString = is.string( events ); - - if( arguments.length === 0 ){ // then unbind all - - for( var i = 0; i < all.length; i++ ){ - all[ i ]._private = all[ i ]._private || {}; - - _p.listeners = []; - } - - return self; // maintain chaining - } - - if( is.fn( selector ) || selector === false ){ // selector is actually callback - callback = selector; - selector = undefined; - } - - if( eventsIsString ){ // then convert to map - var map = {}; - map[ events ] = callback; - events = map; - } - - var keys = Object.keys( events ); - - for( var k = 0; k < keys.length; k++ ){ - var evts = keys[k]; - - callback = events[ evts ]; - - if( callback === false ){ - callback = define.event.falseCallback; - } - - evts = evts.split( /\s+/ ); - for( var h = 0; h < evts.length; h++ ){ - var evt = evts[ h ]; - if( is.emptyString( evt ) ){ continue; } - - var match = evt.match( define.event.optionalTypeRegex ); // [type][.namespace] - if( match ){ - var type = match[1] ? match[1] : undefined; - var namespace = match[2] ? match[2] : undefined; - - for( var i = 0; i < all.length; i++ ){ // - var _p = all[ i ]._private = all[ i ]._private || {}; - var listeners = _p.listeners = _p.listeners || []; - - for( var j = 0; j < listeners.length; j++ ){ - var listener = listeners[ j ]; - var nsMatches = !namespace || namespace === listener.namespace; - var typeMatches = !type || listener.type === type; - var cbMatches = !callback || callback === listener.callback; - var listenerMatches = nsMatches && typeMatches && cbMatches; - - // delete listener if it matches - if( listenerMatches ){ - listeners.splice( j, 1 ); - j--; - } - } // for listeners - } // for all - } // if match - } // for events array - - } // for events map - - return self; // maintain chaining - }; // function - }, // off - - trigger: function( params ){ - var defaults = {}; - params = util.extend( {}, defaults, params ); - - return function triggerImpl( events, extraParams, fnToTrigger ){ - var self = this; - var selfIsArrayLike = self.length !== undefined; - var all = selfIsArrayLike ? self : [ self ]; // put in array if not array-like - var eventsIsString = is.string( events ); - var eventsIsObject = is.plainObject( events ); - var eventsIsEvent = is.event( events ); - var _p = this._private = this._private || {}; - var cy = _p.cy || ( is.core( this ) ? this : null ); - var hasCompounds = cy ? cy.hasCompoundNodes() : false; - - if( eventsIsString ){ // then make a plain event object for each event name - var evts = events.split( /\s+/ ); - events = []; - - for( var i = 0; i < evts.length; i++ ){ - var evt = evts[ i ]; - if( is.emptyString( evt ) ){ continue; } - - var match = evt.match( define.event.regex ); // type[.namespace] - var type = match[1]; - var namespace = match[2] ? match[2] : undefined; - - events.push( { - type: type, - namespace: namespace - } ); - } - } else if( eventsIsObject ){ // put in length 1 array - var eventArgObj = events; - - events = [ eventArgObj ]; - } - - if( extraParams ){ - if( !is.array( extraParams ) ){ // make sure extra params are in an array if specified - extraParams = [ extraParams ]; - } - } else { // otherwise, we've got nothing - extraParams = []; - } - - for( var i = 0; i < events.length; i++ ){ // trigger each event in order - var evtObj = events[ i ]; - - for( var j = 0; j < all.length; j++ ){ // for each - var triggerer = all[ j ]; - var _p = triggerer._private = triggerer._private || {}; - var listeners = _p.listeners = _p.listeners || []; - var triggererIsElement = is.element( triggerer ); - var bubbleUp = triggererIsElement || params.layout; - - // create the event for this element from the event object - var evt; - - if( eventsIsEvent ){ // then just get the object - evt = evtObj; - - evt.cyTarget = evt.cyTarget || triggerer; - evt.cy = evt.cy || cy; - - } else { // then we have to make one - evt = new Event( evtObj, { - cyTarget: triggerer, - cy: cy, - namespace: evtObj.namespace - } ); - } - - // if a layout was specified, then put it in the typed event - if( evtObj.layout ){ - evt.layout = evtObj.layout; - } - - // if triggered by layout, put in event - if( params.layout ){ - evt.layout = triggerer; - } - - // create a rendered position based on the passed position - if( evt.cyPosition ){ - var pos = evt.cyPosition; - var zoom = cy.zoom(); - var pan = cy.pan(); - - evt.cyRenderedPosition = { - x: pos.x * zoom + pan.x, - y: pos.y * zoom + pan.y - }; - } - - if( fnToTrigger ){ // then override the listeners list with just the one we specified - listeners = [ { - namespace: evt.namespace, - type: evt.type, - callback: fnToTrigger - } ]; - } - - for( var k = 0; k < listeners.length; k++ ){ // check each listener - var lis = listeners[ k ]; - var nsMatches = !lis.namespace || lis.namespace === evt.namespace || lis.namespace === define.event.universalNamespace; - var typeMatches = lis.type === evt.type; - var targetMatches = lis.delegated ? ( triggerer !== evt.cyTarget && is.element( evt.cyTarget ) && lis.selObj.matches( evt.cyTarget ) ) : (true); // we're not going to validate the hierarchy; that's too expensive - var listenerMatches = nsMatches && typeMatches && targetMatches; - - if( listenerMatches ){ // then trigger it - var args = [ evt ]; - args = args.concat( extraParams ); // add extra params to args list - - if( lis.data ){ // add on data plugged into binding - evt.data = lis.data; - } else { // or clear it in case the event obj is reused - evt.data = undefined; - } - - if( lis.unbindSelfOnTrigger || lis.unbindAllBindersOnTrigger ){ // then remove listener - listeners.splice( k, 1 ); - k--; - } - - if( lis.unbindAllBindersOnTrigger ){ // then delete the listener for all binders - var binders = lis.binders; - for( var l = 0; l < binders.length; l++ ){ - var binder = binders[ l ]; - if( !binder || binder === triggerer ){ continue; } // already handled triggerer or we can't handle it - - var binderListeners = binder._private.listeners; - for( var m = 0; m < binderListeners.length; m++ ){ - var binderListener = binderListeners[ m ]; - - if( binderListener === lis ){ // delete listener from list - binderListeners.splice( m, 1 ); - m--; - } - } - } - } - - // run the callback - var context = lis.delegated ? evt.cyTarget : triggerer; - var ret = lis.callback.apply( context, args ); - - if( ret === false || evt.isPropagationStopped() ){ - // then don't bubble - bubbleUp = false; - - if( ret === false ){ - // returning false is a shorthand for stopping propagation and preventing the def. action - evt.stopPropagation(); - evt.preventDefault(); - } - } - } // if listener matches - } // for each listener - - // bubble up event for elements - if( bubbleUp ){ - var parent = hasCompounds ? triggerer._private.parent : null; - var hasParent = parent != null && parent.length !== 0; - - if( hasParent ){ // then bubble up to parent - parent = parent[0]; - parent.trigger( evt ); - } else { // otherwise, bubble up to the core - cy.trigger( evt ); - } - } - - } // for each of all - } // for each event - - return self; // maintain chaining - }; // function - }, // trigger - - animated: function( fnParams ){ - var defaults = {}; - fnParams = util.extend( {}, defaults, fnParams ); - - return function animatedImpl(){ - var self = this; - var selfIsArrayLike = self.length !== undefined; - var all = selfIsArrayLike ? self : [ self ]; // put in array if not array-like - var cy = this._private.cy || this; - - if( !cy.styleEnabled() ){ return false; } - - var ele = all[0]; - - if( ele ){ - return ele._private.animation.current.length > 0; - } - }; - }, // animated - - clearQueue: function( fnParams ){ - var defaults = {}; - fnParams = util.extend( {}, defaults, fnParams ); - - return function clearQueueImpl(){ - var self = this; - var selfIsArrayLike = self.length !== undefined; - var all = selfIsArrayLike ? self : [ self ]; // put in array if not array-like - var cy = this._private.cy || this; - - if( !cy.styleEnabled() ){ return this; } - - for( var i = 0; i < all.length; i++ ){ - var ele = all[ i ]; - ele._private.animation.queue = []; - } - - return this; - }; - }, // clearQueue - - delay: function( fnParams ){ - var defaults = {}; - fnParams = util.extend( {}, defaults, fnParams ); - - return function delayImpl( time, complete ){ - var cy = this._private.cy || this; - - if( !cy.styleEnabled() ){ return this; } - - return this.animate( { - delay: time, - duration: time, - complete: complete - } ); - }; - }, // delay - - delayAnimation: function( fnParams ){ - var defaults = {}; - fnParams = util.extend( {}, defaults, fnParams ); - - return function delayAnimationImpl( time, complete ){ - var cy = this._private.cy || this; - - if( !cy.styleEnabled() ){ return this; } - - return this.animation( { - delay: time, - duration: time, - complete: complete - } ); - }; - }, // delay - - animation: function( fnParams ){ - var defaults = {}; - fnParams = util.extend( {}, defaults, fnParams ); - - return function animationImpl( properties, params ){ - var self = this; - var selfIsArrayLike = self.length !== undefined; - var all = selfIsArrayLike ? self : [ self ]; // put in array if not array-like - var cy = this._private.cy || this; - var isCore = !selfIsArrayLike; - var isEles = !isCore; - - if( !cy.styleEnabled() ){ return this; } - - var style = cy.style(); - - properties = util.extend( {}, properties, params ); - - if( properties.duration === undefined ){ - properties.duration = 400; - } - - switch( properties.duration ){ - case 'slow': - properties.duration = 600; - break; - case 'fast': - properties.duration = 200; - break; - } - - var propertiesEmpty = Object.keys( properties ).length === 0; - - if( propertiesEmpty ){ - return new Animation( all[0], properties ); // nothing to animate - } - - if( isEles ){ - properties.style = style.getPropsList( properties.style || properties.css ); - - properties.css = undefined; - } - - if( properties.renderedPosition && isEles ){ - var rpos = properties.renderedPosition; - var pan = cy.pan(); - var zoom = cy.zoom(); - - properties.position = { - x: ( rpos.x - pan.x ) / zoom, - y: ( rpos.y - pan.y ) / zoom - }; - } - - // override pan w/ panBy if set - if( properties.panBy && isCore ){ - var panBy = properties.panBy; - var cyPan = cy.pan(); - - properties.pan = { - x: cyPan.x + panBy.x, - y: cyPan.y + panBy.y - }; - } - - // override pan w/ center if set - var center = properties.center || properties.centre; - if( center && isCore ){ - var centerPan = cy.getCenterPan( center.eles, properties.zoom ); - - if( centerPan ){ - properties.pan = centerPan; - } - } - - // override pan & zoom w/ fit if set - if( properties.fit && isCore ){ - var fit = properties.fit; - var fitVp = cy.getFitViewport( fit.eles || fit.boundingBox, fit.padding ); - - if( fitVp ){ - properties.pan = fitVp.pan; - properties.zoom = fitVp.zoom; - } - } - - return new Animation( all[0], properties ); - }; - }, // animate - - animate: function( fnParams ){ - var defaults = {}; - fnParams = util.extend( {}, defaults, fnParams ); - - return function animateImpl( properties, params ){ - var self = this; - var selfIsArrayLike = self.length !== undefined; - var all = selfIsArrayLike ? self : [ self ]; // put in array if not array-like - var cy = this._private.cy || this; - - if( !cy.styleEnabled() ){ return this; } - - if( params ){ - properties = util.extend( {}, properties, params ); - } - - // manually hook and run the animation - for( var i = 0; i < all.length; i++ ){ - var ele = all[ i ]; - var queue = ele.animated() && (properties.queue === undefined || properties.queue); - - var ani = ele.animation( properties, (queue ? { queue: true } : undefined) ); - - ani.play(); - } - - return this; // chaining - }; - }, // animate - - stop: function( fnParams ){ - var defaults = {}; - fnParams = util.extend( {}, defaults, fnParams ); - - return function stopImpl( clearQueue, jumpToEnd ){ - var self = this; - var selfIsArrayLike = self.length !== undefined; - var all = selfIsArrayLike ? self : [ self ]; // put in array if not array-like - var cy = this._private.cy || this; - - if( !cy.styleEnabled() ){ return this; } - - for( var i = 0; i < all.length; i++ ){ - var ele = all[ i ]; - var _p = ele._private; - var anis = _p.animation.current; - - for( var j = 0; j < anis.length; j++ ){ - var ani = anis[ j ]; - var ani_p = ani._private; - - if( jumpToEnd ){ - // next iteration of the animation loop, the animation - // will go straight to the end and be removed - ani_p.duration = 0; - } - } - - // clear the queue of future animations - if( clearQueue ){ - _p.animation.queue = []; - } - - if( !jumpToEnd ){ - _p.animation.current = []; - } - } - - // we have to notify (the animation loop doesn't do it for us on `stop`) - cy.notify( { - eles: this, - type: 'draw' - } ); - - return this; - }; - } // stop - -}; // define - -module.exports = define; - -},{"./animation":2,"./event":45,"./is":83,"./promise":86,"./selector":87,"./util":100}],45:[function(_dereq_,module,exports){ -'use strict'; - -/*! -Event object based on jQuery events, MIT license - -https://jquery.org/license/ -https://tldrlegal.com/license/mit-license -https://github.com/jquery/jquery/blob/master/src/event.js -*/ - -var Event = function( src, props ){ - // Allow instantiation without the 'new' keyword - if( !(this instanceof Event) ){ - return new Event( src, props ); - } - - // Event object - if( src && src.type ){ - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = ( src.defaultPrevented ) ? returnTrue : returnFalse; - - // Event type - } else { - this.type = src; - } - - // Put explicitly provided properties onto the event object - if( props ){ - // util.extend( this, props ); - - // more efficient to manually copy fields we use - this.type = props.type !== undefined ? props.type : this.type; - this.cy = props.cy; - this.cyTarget = props.cyTarget; - this.cyPosition = props.cyPosition; - this.cyRenderedPosition = props.cyRenderedPosition; - this.namespace = props.namespace; - this.layout = props.layout; - this.data = props.data; - this.message = props.message; - } - - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || Date.now(); -}; - -function returnFalse(){ - return false; -} - -function returnTrue(){ - return true; -} - -// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -Event.prototype = { - instanceString: function(){ - return 'event'; - }, - - preventDefault: function(){ - this.isDefaultPrevented = returnTrue; - - var e = this.originalEvent; - if( !e ){ - return; - } - - // if preventDefault exists run it on the original event - if( e.preventDefault ){ - e.preventDefault(); - } - }, - - stopPropagation: function(){ - this.isPropagationStopped = returnTrue; - - var e = this.originalEvent; - if( !e ){ - return; - } - - // if stopPropagation exists run it on the original event - if( e.stopPropagation ){ - e.stopPropagation(); - } - }, - - stopImmediatePropagation: function(){ - this.isImmediatePropagationStopped = returnTrue; - this.stopPropagation(); - }, - - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse -}; - -module.exports = Event; - -},{}],46:[function(_dereq_,module,exports){ -'use strict'; - -var util = _dereq_( './util' ); -var define = _dereq_( './define' ); -var Collection = _dereq_( './collection' ); -var Core = _dereq_( './core' ); -var incExts = _dereq_( './extensions' ); -var is = _dereq_( './is' ); +var util = __webpack_require__(1); +var define = __webpack_require__(4); +var Collection = __webpack_require__(7); +var Core = __webpack_require__(12); +var incExts = __webpack_require__(96); +var is = __webpack_require__(0); +var Emitter = __webpack_require__(11); // registered extensions to cytoscape, indexed by name var extensions = {}; @@ -9022,224 +17499,287 @@ var extensions = {}; // registered modules for extensions, indexed by name var modules = {}; -function setExtension( type, name, registrant ){ +function setExtension(type, name, registrant) { var ext = registrant; - var overrideErr = function( field ){ - util.error( 'Can not register `' + name + '` for `' + type + '` since `' + field + '` already exists in the prototype and can not be overridden' ); + var overrideErr = function overrideErr(field) { + util.error('Can not register `' + name + '` for `' + type + '` since `' + field + '` already exists in the prototype and can not be overridden'); }; - if( type === 'core' ){ - if( Core.prototype[ name ] ){ - return overrideErr( name ); + if (type === 'core') { + if (Core.prototype[name]) { + return overrideErr(name); } else { - Core.prototype[ name ] = registrant; + Core.prototype[name] = registrant; } - - } else if( type === 'collection' ){ - if( Collection.prototype[ name ] ){ - return overrideErr( name ); + } else if (type === 'collection') { + if (Collection.prototype[name]) { + return overrideErr(name); } else { - Collection.prototype[ name ] = registrant; + Collection.prototype[name] = registrant; } - - } else if( type === 'layout' ){ + } else if (type === 'layout') { // fill in missing layout functions in the prototype - var Layout = function( options ){ + var Layout = function Layout(options) { this.options = options; - registrant.call( this, options ); + registrant.call(this, options); // make sure layout has _private for use w/ std apis like .on() - if( !is.plainObject( this._private ) ){ + if (!is.plainObject(this._private)) { this._private = {}; } this._private.cy = options.cy; this._private.listeners = []; + + this.createEmitter(); }; - var layoutProto = Layout.prototype = Object.create( registrant.prototype ); + var layoutProto = Layout.prototype = Object.create(registrant.prototype); var optLayoutFns = []; - for( var i = 0; i < optLayoutFns.length; i++ ){ - var fnName = optLayoutFns[ i ]; + for (var i = 0; i < optLayoutFns.length; i++) { + var fnName = optLayoutFns[i]; - layoutProto[ fnName ] = layoutProto[ fnName ] || function(){ return this; }; + layoutProto[fnName] = layoutProto[fnName] || function () { + return this; + }; } // either .start() or .run() is defined, so autogen the other - if( layoutProto.start && !layoutProto.run ){ - layoutProto.run = function(){ this.start(); return this; }; - } else if( !layoutProto.start && layoutProto.run ){ - layoutProto.start = function(){ this.run(); return this; }; + if (layoutProto.start && !layoutProto.run) { + layoutProto.run = function () { + this.start();return this; + }; + } else if (!layoutProto.start && layoutProto.run) { + layoutProto.start = function () { + this.run();return this; + }; } - if( !layoutProto.stop ){ - layoutProto.stop = function(){ - var opts = this.options; + var regStop = registrant.prototype.stop; + layoutProto.stop = function () { + var opts = this.options; - if( opts && opts.animate ){ - var anis = this.animations; - for( var i = 0; i < anis.length; i++ ){ - anis[ i ].stop(); + if (opts && opts.animate) { + var anis = this.animations; + + if (anis) { + for (var _i = 0; _i < anis.length; _i++) { + anis[_i].stop(); } } + } - this.trigger( 'layoutstop' ); + if (regStop) { + regStop.call(this); + } else { + this.emit('layoutstop'); + } + return this; + }; + + if (!layoutProto.destroy) { + layoutProto.destroy = function () { return this; }; } - if( !layoutProto.destroy ){ - layoutProto.destroy = function(){ + layoutProto.cy = function () { + return this._private.cy; + }; + + var getCy = function getCy(layout) { + return layout._private.cy; + }; + + util.assign(layoutProto, { + createEmitter: function createEmitter() { + this._private.emitter = new Emitter({ + eventFields: function eventFields(layout) { + return { + layout: layout, + cy: getCy(layout), + target: layout + }; + }, + bubble: function bubble() { + return true; + }, + parent: function parent(layout) { + return getCy(layout); + }, + context: this + }); + return this; - }; - } + }, + emitter: function emitter() { + return this._private.emitter; + }, + on: function on(evt, cb) { + this.emitter().on(evt, cb);return this; + }, + one: function one(evt, cb) { + this.emitter().one(evt, cb);return this; + }, + once: function once(evt, cb) { + this.emitter().one(evt, cb);return this; + }, + removeListener: function removeListener(evt, cb) { + this.emitter().removeListener(evt, cb);return this; + }, + emit: function emit(evt, params) { + this.emitter().emit(evt, params);return this; + } + }); - layoutProto.on = define.on( { layout: true } ); - layoutProto.one = define.on( { layout: true, unbindSelfOnTrigger: true } ); - layoutProto.once = define.on( { layout: true, unbindAllBindersOnTrigger: true } ); - layoutProto.off = define.off( { layout: true } ); - layoutProto.trigger = define.trigger( { layout: true } ); - - define.eventAliasesOn( layoutProto ); + define.eventAliasesOn(layoutProto); ext = Layout; // replace with our wrapped layout - - } else if( type === 'renderer' && name !== 'null' && name !== 'base' ){ + } else if (type === 'renderer' && name !== 'null' && name !== 'base') { // user registered renderers inherit from base - var BaseRenderer = getExtension( 'renderer', 'base' ); + var BaseRenderer = getExtension('renderer', 'base'); var bProto = BaseRenderer.prototype; var RegistrantRenderer = registrant; var rProto = registrant.prototype; - var Renderer = function(){ - BaseRenderer.apply( this, arguments ); - RegistrantRenderer.apply( this, arguments ); + var Renderer = function Renderer() { + BaseRenderer.apply(this, arguments); + RegistrantRenderer.apply(this, arguments); }; var proto = Renderer.prototype; - for( var pName in bProto ){ - var pVal = bProto[ pName ]; - var existsInR = rProto[ pName ] != null; + for (var pName in bProto) { + var pVal = bProto[pName]; + var existsInR = rProto[pName] != null; - if( existsInR ){ - return overrideErr( pName ); + if (existsInR) { + return overrideErr(pName); } - proto[ pName ] = pVal; // take impl from base + proto[pName] = pVal; // take impl from base } - for( var pName in rProto ){ - proto[ pName ] = rProto[ pName ]; // take impl from registrant + for (var _pName in rProto) { + proto[_pName] = rProto[_pName]; // take impl from registrant } - bProto.clientFunctions.forEach( function( name ){ - proto[ name ] = proto[ name ] || function(){ - util.error( 'Renderer does not implement `renderer.' + name + '()` on its prototype' ); + bProto.clientFunctions.forEach(function (name) { + proto[name] = proto[name] || function () { + util.error('Renderer does not implement `renderer.' + name + '()` on its prototype'); }; - } ); + }); ext = Renderer; - } - return util.setMap( { + return util.setMap({ map: extensions, - keys: [ type, name ], + keys: [type, name], value: ext - } ); + }); } -function getExtension( type, name ){ - return util.getMap( { +function getExtension(type, name) { + return util.getMap({ map: extensions, - keys: [ type, name ] - } ); + keys: [type, name] + }); } -function setModule( type, name, moduleType, moduleName, registrant ){ - return util.setMap( { +function setModule(type, name, moduleType, moduleName, registrant) { + return util.setMap({ map: modules, - keys: [ type, name, moduleType, moduleName ], + keys: [type, name, moduleType, moduleName], value: registrant - } ); + }); } -function getModule( type, name, moduleType, moduleName ){ - return util.getMap( { +function getModule(type, name, moduleType, moduleName) { + return util.getMap({ map: modules, - keys: [ type, name, moduleType, moduleName ] - } ); + keys: [type, name, moduleType, moduleName] + }); } -var extension = function(){ +var extension = function extension() { // e.g. extension('renderer', 'svg') - if( arguments.length === 2 ){ - return getExtension.apply( null, arguments ); + if (arguments.length === 2) { + return getExtension.apply(null, arguments); } // e.g. extension('renderer', 'svg', { ... }) - else if( arguments.length === 3 ){ - return setExtension.apply( null, arguments ); - } + else if (arguments.length === 3) { + return setExtension.apply(null, arguments); + } - // e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse') - else if( arguments.length === 4 ){ - return getModule.apply( null, arguments ); - } - - // e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse', { ... }) - else if( arguments.length === 5 ){ - return setModule.apply( null, arguments ); - } - - else { - util.error( 'Invalid extension access syntax' ); - } + // e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse') + else if (arguments.length === 4) { + return getModule.apply(null, arguments); + } + // e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse', { ... }) + else if (arguments.length === 5) { + return setModule.apply(null, arguments); + } else { + util.error('Invalid extension access syntax'); + } }; // allows a core instance to access extensions internally Core.prototype.extension = extension; // included extensions -incExts.forEach( function( group ){ - group.extensions.forEach( function( ext ){ - setExtension( group.type, ext.name, ext.impl ); - } ); -} ); +incExts.forEach(function (group) { + group.extensions.forEach(function (ext) { + setExtension(group.type, ext.name, ext.impl); + }); +}); module.exports = extension; -},{"./collection":26,"./core":37,"./define":44,"./extensions":47,"./is":83,"./util":100}],47:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 96 */ +/***/ (function(module, exports, __webpack_require__) { -module.exports = [ - { - type: 'layout', - extensions: _dereq_( './layout' ) - }, +"use strict"; - { - type: 'renderer', - extensions: _dereq_( './renderer' ) - } -]; -},{"./layout":53,"./renderer":78}],48:[function(_dereq_,module,exports){ -'use strict'; +module.exports = [{ + type: 'layout', + extensions: __webpack_require__(97) +}, { + type: 'renderer', + extensions: __webpack_require__(106) +}]; -var util = _dereq_( '../../util' ); -var math = _dereq_( '../../math' ); -var is = _dereq_( '../../is' ); +/***/ }), +/* 97 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = [{ name: 'breadthfirst', impl: __webpack_require__(98) }, { name: 'circle', impl: __webpack_require__(99) }, { name: 'concentric', impl: __webpack_require__(100) }, { name: 'cose', impl: __webpack_require__(101) }, { name: 'grid', impl: __webpack_require__(102) }, { name: 'null', impl: __webpack_require__(103) }, { name: 'preset', impl: __webpack_require__(104) }, { name: 'random', impl: __webpack_require__(105) }]; + +/***/ }), +/* 98 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var util = __webpack_require__(1); +var math = __webpack_require__(2); +var is = __webpack_require__(0); var defaults = { fit: true, // whether to fit the viewport to the graph @@ -9249,85 +17789,98 @@ var defaults = { spacingFactor: 1.75, // positive spacing factor, larger => more space between nodes (N.B. n/a if causes overlap) boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h } avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space + nodeDimensionsIncludeLabels: false, // Excludes the label when calculating node bounding boxes for the layout algorithm roots: undefined, // the roots of the trees maximalAdjustments: 0, // how many times to try to position the nodes in a maximal way (i.e. no backtracking) animate: false, // whether to transition the node positions animationDuration: 500, // duration of animation in ms if enabled - animationEasing: undefined, // easing of animation if enabled + animationEasing: undefined, // easing of animation if enabled, + animateFilter: function animateFilter(node, i) { + return true; + }, // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts ready: undefined, // callback on layoutready - stop: undefined // callback on layoutstop + stop: undefined, // callback on layoutstop + transform: function transform(node, position) { + return position; + } // transform a given node position. Useful for changing flow direction in discrete layouts }; -function BreadthFirstLayout( options ){ - this.options = util.extend( {}, defaults, options ); +function BreadthFirstLayout(options) { + this.options = util.extend({}, defaults, options); } -BreadthFirstLayout.prototype.run = function(){ +BreadthFirstLayout.prototype.run = function () { var params = this.options; var options = params; var cy = params.cy; var eles = options.eles; - var nodes = eles.nodes().not( ':parent' ); + var nodes = eles.nodes().not(':parent'); var graph = eles; - var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : { + var bb = math.makeBoundingBox(options.boundingBox ? options.boundingBox : { x1: 0, y1: 0, w: cy.width(), h: cy.height() - } ); + }); - var roots; - if( is.elementOrCollection( options.roots ) ){ + var roots = void 0; + if (is.elementOrCollection(options.roots)) { roots = options.roots; - } else if( is.array( options.roots ) ){ + } else if (is.array(options.roots)) { var rootsArray = []; - for( var i = 0; i < options.roots.length; i++ ){ - var id = options.roots[ i ]; - var ele = cy.getElementById( id ); - rootsArray.push( ele ); + for (var i = 0; i < options.roots.length; i++) { + var id = options.roots[i]; + var ele = cy.getElementById(id); + rootsArray.push(ele); } - roots = cy.collection( rootsArray ); - } else if( is.string( options.roots ) ){ - roots = cy.$( options.roots ); - + roots = cy.collection(rootsArray); + } else if (is.string(options.roots)) { + roots = cy.$(options.roots); } else { - if( options.directed ){ + if (options.directed) { roots = nodes.roots(); } else { var components = []; var unhandledNodes = nodes; - while( unhandledNodes.length > 0 ){ + var _loop = function _loop() { var currComp = cy.collection(); - eles.bfs( { + eles.bfs({ roots: unhandledNodes[0], - visit: function( i, depth, node, edge, pNode ){ - currComp = currComp.add( node ); + visit: function visit(node, edge, pNode, i, depth) { + currComp = currComp.add(node); }, directed: false - } ); + }); - unhandledNodes = unhandledNodes.not( currComp ); - components.push( currComp ); + unhandledNodes = unhandledNodes.not(currComp); + components.push(currComp); + }; + + while (unhandledNodes.length > 0) { + _loop(); } roots = cy.collection(); - for( var i = 0; i < components.length; i++ ){ - var comp = components[ i ]; - var maxDegree = comp.maxDegree( false ); - var compRoots = comp.filter( function(){ - return this.degree( false ) === maxDegree; - } ); - roots = roots.add( compRoots ); + var _loop2 = function _loop2(_i) { + var comp = components[_i]; + var maxDegree = comp.maxDegree(false); + var compRoots = comp.filter(function (ele) { + return ele.degree(false) === maxDegree; + }); + + roots = roots.add(compRoots); + }; + + for (var _i = 0; _i < components.length; _i++) { + _loop2(_i); } - } } - var depths = []; var foundByBfs = {}; var id2depth = {}; @@ -9336,77 +17889,77 @@ BreadthFirstLayout.prototype.run = function(){ var successors = {}; // find the depths of the nodes - graph.bfs( { + graph.bfs({ roots: roots, directed: options.directed, - visit: function( i, depth, node, edge, pNode ){ - var ele = this[0]; + visit: function visit(node, edge, pNode, i, depth) { + var ele = node[0]; var id = ele.id(); - if( !depths[ depth ] ){ - depths[ depth ] = []; + if (!depths[depth]) { + depths[depth] = []; } - depths[ depth ].push( ele ); - foundByBfs[ id ] = true; - id2depth[ id ] = depth; - prevNode[ id ] = pNode; - prevEdge[ id ] = edge; + depths[depth].push(ele); + foundByBfs[id] = true; + id2depth[id] = depth; + prevNode[id] = pNode; + prevEdge[id] = edge; - if( pNode ){ + if (pNode) { var prevId = pNode.id(); - var succ = successors[ prevId ] = successors[ prevId ] || []; + var succ = successors[prevId] = successors[prevId] || []; - succ.push( node ); + succ.push(node); } } - } ); + }); // check for nodes not found by bfs var orphanNodes = []; - for( var i = 0; i < nodes.length; i++ ){ - var ele = nodes[ i ]; + for (var _i2 = 0; _i2 < nodes.length; _i2++) { + var _ele = nodes[_i2]; - if( foundByBfs[ ele.id() ] ){ + if (foundByBfs[_ele.id()]) { continue; } else { - orphanNodes.push( ele ); + orphanNodes.push(_ele); } } // assign orphan nodes a depth from their neighborhood var maxChecks = orphanNodes.length * 3; var checks = 0; - while( orphanNodes.length !== 0 && checks < maxChecks ){ + while (orphanNodes.length !== 0 && checks < maxChecks) { var node = orphanNodes.shift(); var neighbors = node.neighborhood().nodes(); var assignedDepth = false; - for( var i = 0; i < neighbors.length; i++ ){ - var depth = id2depth[ neighbors[ i ].id() ]; + for (var _i3 = 0; _i3 < neighbors.length; _i3++) { + var depth = id2depth[neighbors[_i3].id()]; - if( depth !== undefined ){ - depths[ depth ].push( node ); + if (depth !== undefined) { + depths[depth].push(node); assignedDepth = true; break; } } - if( !assignedDepth ){ - orphanNodes.push( node ); + if (!assignedDepth) { + orphanNodes.push(node); } checks++; } // assign orphan nodes that are still left to the depth of their subgraph - while( orphanNodes.length !== 0 ){ - var node = orphanNodes.shift(); - //var subgraph = graph.bfs( node ).path; - var assignedDepth = false; + while (orphanNodes.length !== 0) { + var _node = orphanNodes.shift(); + //let subgraph = graph.bfs( node ).path; + var _assignedDepth = false; - // for( var i = 0; i < subgraph.length; i++ ){ - // var depth = id2depth[ subgraph[i].id() ]; + // for( let i = 0; i < subgraph.length; i++ ){ + // let depth = id2depth[ subgraph[i].id() ]; // if( depth !== undefined ){ // depths[depth].push( node ); @@ -9415,25 +17968,32 @@ BreadthFirstLayout.prototype.run = function(){ // } // } - if( !assignedDepth ){ // worst case if the graph really isn't tree friendly, then just dump it in 0 - if( depths.length === 0 ){ - depths.push( [] ); + if (!_assignedDepth) { + // worst case if the graph really isn't tree friendly, then just dump it in 0 + if (depths.length === 0) { + depths.push([]); } - depths[0].push( node ); + depths[0].push(_node); } } // assign the nodes a depth and index - var assignDepthsToEles = function(){ - for( var i = 0; i < depths.length; i++ ){ - var eles = depths[ i ]; + var assignDepthsToEles = function assignDepthsToEles() { + for (var _i4 = 0; _i4 < depths.length; _i4++) { + var _eles = depths[_i4]; - for( var j = 0; j < eles.length; j++ ){ - var ele = eles[ j ]; + for (var j = 0; j < _eles.length; j++) { + var _ele2 = _eles[j]; - ele._private.scratch.breadthfirst = { - depth: i, + if (_ele2 == null) { + _eles.splice(j, 1); + j--; + continue; + } + + _ele2._private.scratch.breadthfirst = { + depth: _i4, index: j }; } @@ -9441,20 +18001,20 @@ BreadthFirstLayout.prototype.run = function(){ }; assignDepthsToEles(); - - var intersectsDepth = function( node ){ // returns true if has edges pointing in from a higher depth - var edges = node.connectedEdges( function(){ - return this.data( 'target' ) === node.id(); - } ); + var intersectsDepth = function intersectsDepth(node) { + // returns true if has edges pointing in from a higher depth + var edges = node.connectedEdges(function (ele) { + return ele.data('target') === node.id(); + }); var thisInfo = node._private.scratch.breadthfirst; var highestDepthOfOther = 0; - var highestOther; - for( var i = 0; i < edges.length; i++ ){ - var edge = edges[ i ]; + var highestOther = void 0; + for (var _i5 = 0; _i5 < edges.length; _i5++) { + var edge = edges[_i5]; var otherNode = edge.source()[0]; var otherInfo = otherNode._private.scratch.breadthfirst; - if( thisInfo.depth <= otherInfo.depth && highestDepthOfOther < otherInfo.depth ){ + if (thisInfo.depth <= otherInfo.depth && highestDepthOfOther < otherInfo.depth) { highestDepthOfOther = otherInfo.depth; highestOther = otherNode; } @@ -9464,43 +18024,43 @@ BreadthFirstLayout.prototype.run = function(){ }; // make maximal if so set by adjusting depths - for( var adj = 0; adj < options.maximalAdjustments; adj++ ){ + for (var adj = 0; adj < options.maximalAdjustments; adj++) { var nDepths = depths.length; var elesToMove = []; - for( var i = 0; i < nDepths; i++ ){ - var depth = depths[ i ]; + for (var _i6 = 0; _i6 < nDepths; _i6++) { + var _depth = depths[_i6]; - var nDepth = depth.length; - for( var j = 0; j < nDepth; j++ ){ - var ele = depth[ j ]; - var info = ele._private.scratch.breadthfirst; - var intEle = intersectsDepth( ele ); + var nDepth = _depth.length; + for (var j = 0; j < nDepth; j++) { + var _ele3 = _depth[j]; + var info = _ele3._private.scratch.breadthfirst; + var intEle = intersectsDepth(_ele3); - if( intEle ){ + if (intEle) { info.intEle = intEle; - elesToMove.push( ele ); + elesToMove.push(_ele3); } } } - for( var i = 0; i < elesToMove.length; i++ ){ - var ele = elesToMove[ i ]; - var info = ele._private.scratch.breadthfirst; - var intEle = info.intEle; - var intInfo = intEle._private.scratch.breadthfirst; + for (var _i7 = 0; _i7 < elesToMove.length; _i7++) { + var _ele4 = elesToMove[_i7]; + var _info = _ele4._private.scratch.breadthfirst; + var _intEle = _info.intEle; + var intInfo = _intEle._private.scratch.breadthfirst; - depths[ info.depth ].splice( info.index, 1 ); // remove from old depth & index + depths[_info.depth][_info.index] = null; // remove from old depth & index (create hole to be cleaned) // add to end of new depth var newDepth = intInfo.depth + 1; - while( newDepth > depths.length - 1 ){ - depths.push( [] ); + while (newDepth > depths.length - 1) { + depths.push([]); } - depths[ newDepth ].push( ele ); + depths[newDepth].push(_ele4); - info.depth = newDepth; - info.index = depths[ newDepth ].length - 1; + _info.depth = newDepth; + _info.index = depths[newDepth].length - 1; } assignDepthsToEles(); @@ -9508,76 +18068,76 @@ BreadthFirstLayout.prototype.run = function(){ // find min distance we need to leave between nodes var minDistance = 0; - if( options.avoidOverlap ){ - for( var i = 0; i < nodes.length; i++ ){ - var n = nodes[ i ]; - var nbb = n.boundingBox(); + if (options.avoidOverlap) { + for (var _i8 = 0; _i8 < nodes.length; _i8++) { + var n = nodes[_i8]; + var nbb = n.layoutDimensions(options); var w = nbb.w; var h = nbb.h; - minDistance = Math.max( minDistance, w, h ); + minDistance = Math.max(minDistance, w, h); } - minDistance *= options.spacingFactor; // just to have some nice spacing } // get the weighted percent for an element based on its connectivity to other levels var cachedWeightedPercent = {}; - var getWeightedPercent = function( ele ){ - if( cachedWeightedPercent[ ele.id() ] ){ - return cachedWeightedPercent[ ele.id() ]; + var getWeightedPercent = function getWeightedPercent(ele) { + if (cachedWeightedPercent[ele.id()]) { + return cachedWeightedPercent[ele.id()]; } var eleDepth = ele._private.scratch.breadthfirst.depth; - var neighbors = ele.neighborhood().nodes().not( ':parent' ); + var neighbors = ele.neighborhood().nodes().not(':parent').intersection(nodes); var percent = 0; var samples = 0; - for( var i = 0; i < neighbors.length; i++ ){ - var neighbor = neighbors[ i ]; + for (var _i9 = 0; _i9 < neighbors.length; _i9++) { + var neighbor = neighbors[_i9]; var bf = neighbor._private.scratch.breadthfirst; var index = bf.index; - var depth = bf.depth; - var nDepth = depths[ depth ].length; + var _depth2 = bf.depth; + var _nDepth = depths[_depth2].length; - if( eleDepth > depth || eleDepth === 0 ){ // only get influenced by elements above - percent += index / nDepth; + if (eleDepth > _depth2 || eleDepth === 0) { + // only get influenced by elements above + percent += index / _nDepth; samples++; } } - samples = Math.max( 1, samples ); + samples = Math.max(1, samples); percent = percent / samples; - if( samples === 0 ){ // so lone nodes have a "don't care" state in sorting + if (samples === 0) { + // so lone nodes have a "don't care" state in sorting percent = undefined; } - cachedWeightedPercent[ ele.id() ] = percent; + cachedWeightedPercent[ele.id()] = percent; return percent; }; - // rearrange the indices in each depth level based on connectivity - var sortFn = function( a, b ){ - var apct = getWeightedPercent( a ); - var bpct = getWeightedPercent( b ); + var sortFn = function sortFn(a, b) { + var apct = getWeightedPercent(a); + var bpct = getWeightedPercent(b); return apct - bpct; }; - for( var times = 0; times < 3; times++ ){ // do it a few times b/c the depths are dynamic and we want a more stable result + for (var times = 0; times < 3; times++) { + // do it a few times b/c the depths are dynamic and we want a more stable result - for( var i = 0; i < depths.length; i++ ){ - depths[ i ] = depths[ i ].sort( sortFn ); + for (var _i10 = 0; _i10 < depths.length; _i10++) { + depths[_i10] = depths[_i10].sort(sortFn); } assignDepthsToEles(); // and update - } var biggestDepthSize = 0; - for( var i = 0; i < depths.length; i++ ){ - biggestDepthSize = Math.max( depths[ i ].length, biggestDepthSize ); + for (var _i11 = 0; _i11 < depths.length; _i11++) { + biggestDepthSize = Math.max(depths[_i11].length, biggestDepthSize); } var center = { @@ -9585,34 +18145,34 @@ BreadthFirstLayout.prototype.run = function(){ y: bb.x1 + bb.h / 2 }; - var getPosition = function( ele, isBottomDepth ){ + var getPosition = function getPosition(ele, isBottomDepth) { var info = ele._private.scratch.breadthfirst; var depth = info.depth; var index = info.index; - var depthSize = depths[ depth ].length; + var depthSize = depths[depth].length; - var distanceX = Math.max( bb.w / (depthSize + 1), minDistance ); - var distanceY = Math.max( bb.h / (depths.length + 1), minDistance ); - var radiusStepSize = Math.min( bb.w / 2 / depths.length, bb.h / 2 / depths.length ); - radiusStepSize = Math.max( radiusStepSize, minDistance ); + var distanceX = Math.max(bb.w / (depthSize + 1), minDistance); + var distanceY = Math.max(bb.h / (depths.length + 1), minDistance); + var radiusStepSize = Math.min(bb.w / 2 / depths.length, bb.h / 2 / depths.length); + radiusStepSize = Math.max(radiusStepSize, minDistance); - if( !options.circle ){ + if (!options.circle) { var epos = { x: center.x + (index + 1 - (depthSize + 1) / 2) * distanceX, y: (depth + 1) * distanceY }; - if( isBottomDepth ){ + if (isBottomDepth) { return epos; } - // var succs = successors[ ele.id() ]; + // let succs = successors[ ele.id() ]; // if( succs ){ // epos.x = 0; // - // for( var i = 0 ; i < succs.length; i++ ){ - // var spos = pos[ succs[i].id() ]; + // for( let i = 0 ; i < succs.length; i++ ){ + // let spos = pos[ succs[i].id() ]; // // epos.x += spos.x; // } @@ -9623,21 +18183,19 @@ BreadthFirstLayout.prototype.run = function(){ // } return epos; - } else { - if( options.circle ){ + if (options.circle) { var radius = radiusStepSize * depth + radiusStepSize - (depths.length > 0 && depths[0].length <= 3 ? radiusStepSize / 2 : 0); - var theta = 2 * Math.PI / depths[ depth ].length * index; + var theta = 2 * Math.PI / depths[depth].length * index; - if( depth === 0 && depths[0].length === 1 ){ + if (depth === 0 && depths[0].length === 1) { radius = 1; } return { - x: center.x + radius * Math.cos( theta ), - y: center.y + radius * Math.sin( theta ) + x: center.x + radius * Math.cos(theta), + y: center.y + radius * Math.sin(theta) }; - } else { return { x: center.x + (index + 1 - (depthSize + 1) / 2) * distanceX, @@ -9645,42 +18203,47 @@ BreadthFirstLayout.prototype.run = function(){ }; } } - }; // get positions in reverse depth order var pos = {}; - for( var i = depths.length - 1; i >= 0; i-- ){ - var depth = depths[ i ]; + for (var _i12 = depths.length - 1; _i12 >= 0; _i12--) { + var _depth3 = depths[_i12]; - for( var j = 0; j < depth.length; j++ ){ - var node = depth[ j ]; + for (var _j = 0; _j < _depth3.length; _j++) { + var _node2 = _depth3[_j]; - pos[ node.id() ] = getPosition( node, i === depths.length - 1 ); + pos[_node2.id()] = getPosition(_node2, _i12 === depths.length - 1); } } - nodes.layoutPositions( this, options, function(){ - return pos[ this.id() ]; - } ); + nodes.layoutPositions(this, options, function (node) { + return pos[node.id()]; + }); return this; // chaining }; module.exports = BreadthFirstLayout; -},{"../../is":83,"../../math":85,"../../util":100}],49:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 99 */ +/***/ (function(module, exports, __webpack_require__) { -var util = _dereq_( '../../util' ); -var math = _dereq_( '../../math' ); -var is = _dereq_( '../../is' ); +"use strict"; + + +var util = __webpack_require__(1); +var math = __webpack_require__(2); +var is = __webpack_require__(0); var defaults = { fit: true, // whether to fit the viewport to the graph padding: 30, // the padding on fit boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h } avoidOverlap: true, // prevents node overlap, may overflow boundingBox and radius if not enough space + nodeDimensionsIncludeLabels: false, // Excludes the label when calculating node bounding boxes for the layout algorithm + spacingFactor: undefined, // Applies a multiplicative factor (>0) to expand or compress the overall area that the nodes take up radius: undefined, // the radius of the circle startAngle: 3 / 2 * Math.PI, // where nodes start in radians sweep: undefined, // how many radians should be between the first and last node (defaults to full circle) @@ -9689,15 +18252,22 @@ var defaults = { animate: false, // whether to transition the node positions animationDuration: 500, // duration of animation in ms if enabled animationEasing: undefined, // easing of animation if enabled + animateFilter: function animateFilter(node, i) { + return true; + }, // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts ready: undefined, // callback on layoutready - stop: undefined // callback on layoutstop + stop: undefined, // callback on layoutstop + transform: function transform(node, position) { + return position; + } // transform a given node position. Useful for changing flow direction in discrete layouts + }; -function CircleLayout( options ){ - this.options = util.extend( {}, defaults, options ); +function CircleLayout(options) { + this.options = util.extend({}, defaults, options); } -CircleLayout.prototype.run = function(){ +CircleLayout.prototype.run = function () { var params = this.options; var options = params; @@ -9706,15 +18276,15 @@ CircleLayout.prototype.run = function(){ var clockwise = options.counterclockwise !== undefined ? !options.counterclockwise : options.clockwise; - var nodes = eles.nodes().not( ':parent' ); + var nodes = eles.nodes().not(':parent'); - if( options.sort ){ - nodes = nodes.sort( options.sort ); + if (options.sort) { + nodes = nodes.sort(options.sort); } - var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : { + var bb = math.makeBoundingBox(options.boundingBox ? options.boundingBox : { x1: 0, y1: 0, w: cy.width(), h: cy.height() - } ); + }); var center = { x: bb.x1 + bb.w / 2, @@ -9722,43 +18292,43 @@ CircleLayout.prototype.run = function(){ }; var sweep = options.sweep === undefined ? 2 * Math.PI - 2 * Math.PI / nodes.length : options.sweep; - - var dTheta = sweep / ( Math.max( 1, nodes.length - 1 ) ); - var r; + var dTheta = sweep / Math.max(1, nodes.length - 1); + var r = void 0; var minDistance = 0; - for( var i = 0; i < nodes.length; i++ ){ - var n = nodes[ i ]; - var nbb = n.boundingBox(); + for (var i = 0; i < nodes.length; i++) { + var n = nodes[i]; + var nbb = n.layoutDimensions(options); var w = nbb.w; var h = nbb.h; - minDistance = Math.max( minDistance, w, h ); + minDistance = Math.max(minDistance, w, h); } - if( is.number( options.radius ) ){ + if (is.number(options.radius)) { r = options.radius; - } else if( nodes.length <= 1 ){ + } else if (nodes.length <= 1) { r = 0; } else { - r = Math.min( bb.h, bb.w ) / 2 - minDistance; + r = Math.min(bb.h, bb.w) / 2 - minDistance; } // calculate the radius - if( nodes.length > 1 && options.avoidOverlap ){ // but only if more than one node (can't overlap) + if (nodes.length > 1 && options.avoidOverlap) { + // but only if more than one node (can't overlap) minDistance *= 1.75; // just to have some nice spacing - var dcos = Math.cos( dTheta ) - Math.cos( 0 ); - var dsin = Math.sin( dTheta ) - Math.sin( 0 ); - var rMin = Math.sqrt( minDistance * minDistance / ( dcos * dcos + dsin * dsin ) ); // s.t. no nodes overlapping - r = Math.max( rMin, r ); + var dcos = Math.cos(dTheta) - Math.cos(0); + var dsin = Math.sin(dTheta) - Math.sin(0); + var rMin = Math.sqrt(minDistance * minDistance / (dcos * dcos + dsin * dsin)); // s.t. no nodes overlapping + r = Math.max(rMin, r); } - var getPos = function( i, ele ){ - var theta = options.startAngle + i * dTheta * ( clockwise ? 1 : -1 ); + var getPos = function getPos(ele, i) { + var theta = options.startAngle + i * dTheta * (clockwise ? 1 : -1); - var rx = r * Math.cos( theta ); - var ry = r * Math.sin( theta ); + var rx = r * Math.cos(theta); + var ry = r * Math.sin(theta); var pos = { x: center.x + rx, y: center.y + ry @@ -9767,18 +18337,22 @@ CircleLayout.prototype.run = function(){ return pos; }; - nodes.layoutPositions( this, options, getPos ); + nodes.layoutPositions(this, options, getPos); return this; // chaining }; module.exports = CircleLayout; -},{"../../is":83,"../../math":85,"../../util":100}],50:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 100 */ +/***/ (function(module, exports, __webpack_require__) { -var util = _dereq_( '../../util' ); -var math = _dereq_( '../../math' ); +"use strict"; + + +var util = __webpack_require__(1); +var math = __webpack_require__(2); var defaults = { fit: true, // whether to fit the viewport to the graph @@ -9790,26 +18364,36 @@ var defaults = { minNodeSpacing: 10, // min spacing between outside of nodes (used for radius adjustment) boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h } avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space + nodeDimensionsIncludeLabels: false, // Excludes the label when calculating node bounding boxes for the layout algorithm height: undefined, // height of layout area (overrides container height) width: undefined, // width of layout area (overrides container width) - concentric: function( node ){ // returns numeric value for each node, placing higher nodes in levels towards the centre + spacingFactor: undefined, // Applies a multiplicative factor (>0) to expand or compress the overall area that the nodes take up + concentric: function concentric(node) { + // returns numeric value for each node, placing higher nodes in levels towards the centre return node.degree(); }, - levelWidth: function( nodes ){ // the variation of concentric values in each level + levelWidth: function levelWidth(nodes) { + // the letiation of concentric values in each level return nodes.maxDegree() / 4; }, animate: false, // whether to transition the node positions animationDuration: 500, // duration of animation in ms if enabled animationEasing: undefined, // easing of animation if enabled + animateFilter: function animateFilter(node, i) { + return true; + }, // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts ready: undefined, // callback on layoutready - stop: undefined // callback on layoutstop + stop: undefined, // callback on layoutstop + transform: function transform(node, position) { + return position; + } // transform a given node position. Useful for changing flow direction in discrete layouts }; -function ConcentricLayout( options ){ - this.options = util.extend( {}, defaults, options ); +function ConcentricLayout(options) { + this.options = util.extend({}, defaults, options); } -ConcentricLayout.prototype.run = function(){ +ConcentricLayout.prototype.run = function () { var params = this.options; var options = params; @@ -9818,11 +18402,11 @@ ConcentricLayout.prototype.run = function(){ var cy = params.cy; var eles = options.eles; - var nodes = eles.nodes().not( ':parent' ); + var nodes = eles.nodes().not(':parent'); - var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : { + var bb = math.makeBoundingBox(options.boundingBox ? options.boundingBox : { x1: 0, y1: 0, w: cy.width(), h: cy.height() - } ); + }); var center = { x: bb.x1 + bb.w / 2, @@ -9833,16 +18417,16 @@ ConcentricLayout.prototype.run = function(){ var theta = options.startAngle; var maxNodeSize = 0; - for( var i = 0; i < nodes.length; i++ ){ - var node = nodes[ i ]; - var value; + for (var i = 0; i < nodes.length; i++) { + var node = nodes[i]; + var value = void 0; // calculate the node value - value = options.concentric.apply( node, [ node ] ); - nodeValues.push( { + value = options.concentric(node); + nodeValues.push({ value: value, node: node - } ); + }); // for style mapping node._private.scratch.concentric = value; @@ -9852,64 +18436,66 @@ ConcentricLayout.prototype.run = function(){ nodes.updateStyle(); // calculate max size now based on potentially updated mappers - for( var i = 0; i < nodes.length; i++ ){ - var node = nodes[ i ]; - var nbb = node.boundingBox(); + for (var _i = 0; _i < nodes.length; _i++) { + var _node = nodes[_i]; + var nbb = _node.layoutDimensions(options); - maxNodeSize = Math.max( maxNodeSize, nbb.w, nbb.h ); + maxNodeSize = Math.max(maxNodeSize, nbb.w, nbb.h); } // sort node values in descreasing order - nodeValues.sort( function( a, b ){ + nodeValues.sort(function (a, b) { return b.value - a.value; - } ); + }); - var levelWidth = options.levelWidth( nodes ); + var levelWidth = options.levelWidth(nodes); // put the values into levels - var levels = [ [] ]; + var levels = [[]]; var currentLevel = levels[0]; - for( var i = 0; i < nodeValues.length; i++ ){ - var val = nodeValues[ i ]; + for (var _i2 = 0; _i2 < nodeValues.length; _i2++) { + var val = nodeValues[_i2]; - if( currentLevel.length > 0 ){ - var diff = Math.abs( currentLevel[0].value - val.value ); + if (currentLevel.length > 0) { + var diff = Math.abs(currentLevel[0].value - val.value); - if( diff >= levelWidth ){ + if (diff >= levelWidth) { currentLevel = []; - levels.push( currentLevel ); + levels.push(currentLevel); } } - currentLevel.push( val ); + currentLevel.push(val); } // create positions from levels var minDist = maxNodeSize + options.minNodeSpacing; // min dist between nodes - if( !options.avoidOverlap ){ // then strictly constrain to bb + if (!options.avoidOverlap) { + // then strictly constrain to bb var firstLvlHasMulti = levels.length > 0 && levels[0].length > 1; - var maxR = ( Math.min( bb.w, bb.h ) / 2 - minDist ); - var rStep = maxR / ( levels.length + firstLvlHasMulti ? 1 : 0 ); + var maxR = Math.min(bb.w, bb.h) / 2 - minDist; + var rStep = maxR / (levels.length + firstLvlHasMulti ? 1 : 0); - minDist = Math.min( minDist, rStep ); + minDist = Math.min(minDist, rStep); } // find the metrics for each level var r = 0; - for( var i = 0; i < levels.length; i++ ){ - var level = levels[ i ]; + for (var _i3 = 0; _i3 < levels.length; _i3++) { + var level = levels[_i3]; var sweep = options.sweep === undefined ? 2 * Math.PI - 2 * Math.PI / level.length : options.sweep; - var dTheta = level.dTheta = sweep / ( Math.max( 1, level.length - 1 ) ); + var dTheta = level.dTheta = sweep / Math.max(1, level.length - 1); // calculate the radius - if( level.length > 1 && options.avoidOverlap ){ // but only if more than one node (can't overlap) - var dcos = Math.cos( dTheta ) - Math.cos( 0 ); - var dsin = Math.sin( dTheta ) - Math.sin( 0 ); - var rMin = Math.sqrt( minDist * minDist / ( dcos * dcos + dsin * dsin ) ); // s.t. no nodes overlapping + if (level.length > 1 && options.avoidOverlap) { + // but only if more than one node (can't overlap) + var dcos = Math.cos(dTheta) - Math.cos(0); + var dsin = Math.sin(dTheta) - Math.sin(0); + var rMin = Math.sqrt(minDist * minDist / (dcos * dcos + dsin * dsin)); // s.t. no nodes overlapping - r = Math.max( rMin, r ); + r = Math.max(rMin, r); } level.r = r; @@ -9917,65 +18503,69 @@ ConcentricLayout.prototype.run = function(){ r += minDist; } - if( options.equidistant ){ + if (options.equidistant) { var rDeltaMax = 0; - var r = 0; + var _r = 0; - for( var i = 0; i < levels.length; i++ ){ - var level = levels[ i ]; - var rDelta = level.r - r; + for (var _i4 = 0; _i4 < levels.length; _i4++) { + var _level = levels[_i4]; + var rDelta = _level.r - _r; - rDeltaMax = Math.max( rDeltaMax, rDelta ); + rDeltaMax = Math.max(rDeltaMax, rDelta); } - r = 0; - for( var i = 0; i < levels.length; i++ ){ - var level = levels[ i ]; + _r = 0; + for (var _i5 = 0; _i5 < levels.length; _i5++) { + var _level2 = levels[_i5]; - if( i === 0 ){ - r = level.r; + if (_i5 === 0) { + _r = _level2.r; } - level.r = r; + _level2.r = _r; - r += rDeltaMax; + _r += rDeltaMax; } } // calculate the node positions var pos = {}; // id => position - for( var i = 0; i < levels.length; i++ ){ - var level = levels[ i ]; - var dTheta = level.dTheta; - var r = level.r; + for (var _i6 = 0; _i6 < levels.length; _i6++) { + var _level3 = levels[_i6]; + var _dTheta = _level3.dTheta; + var _r2 = _level3.r; - for( var j = 0; j < level.length; j++ ){ - var val = level[ j ]; - var theta = options.startAngle + (clockwise ? 1 : -1) * dTheta * j; + for (var j = 0; j < _level3.length; j++) { + var _val = _level3[j]; + var _theta = options.startAngle + (clockwise ? 1 : -1) * _dTheta * j; var p = { - x: center.x + r * Math.cos( theta ), - y: center.y + r * Math.sin( theta ) + x: center.x + _r2 * Math.cos(_theta), + y: center.y + _r2 * Math.sin(_theta) }; - pos[ val.node.id() ] = p; + pos[_val.node.id()] = p; } } // position the nodes - nodes.layoutPositions( this, options, function(){ - var id = this.id(); + nodes.layoutPositions(this, options, function (ele) { + var id = ele.id(); - return pos[ id ]; - } ); + return pos[id]; + }); return this; // chaining }; module.exports = ConcentricLayout; -},{"../../math":85,"../../util":100}],51:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 101 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + /* The CoSE layout was written by Gerardo Huck. @@ -9987,10 +18577,10 @@ http://dl.acm.org/citation.cfm?id=1498047 Modifications tracked on Github. */ -var util = _dereq_( '../../util' ); -var math = _dereq_( '../../math' ); -var Thread = _dereq_( '../../thread' ); -var is = _dereq_( '../../is' ); +var util = __webpack_require__(1); +var math = __webpack_require__(2); +var is = __webpack_require__(0); +var Promise = __webpack_require__(5); var DEBUG; @@ -9999,15 +18589,31 @@ var DEBUG; */ var defaults = { // Called on `layoutready` - ready: function(){}, + ready: function ready() {}, // Called on `layoutstop` - stop: function(){}, + stop: function stop() {}, // Whether to animate while running the layout + // true : Animate continuously as the layout is running + // false : Just show the end result + // 'end' : Animate with the end result, from the initial positions to the end positions animate: true, - // The layout animates only after this many milliseconds + // Easing of the animation for animate:'end' + animationEasing: undefined, + + // The duration of the animation for animate:'end' + animationDuration: undefined, + + // A function that determines whether the node should be animated + // All nodes animated by default on animate enabled + // Non-animated nodes are positioned immediately when the layout starts + animateFilter: function animateFilter(node, i) { + return true; + }, + + // The layout animates only after this many milliseconds for animate:true // (prevents flashing on fast runs) animationThreshold: 250, @@ -10024,129 +18630,194 @@ var defaults = { // Constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h } boundingBox: undefined, + // Excludes the label when calculating node bounding boxes for the layout algorithm + nodeDimensionsIncludeLabels: false, + + // Randomize the initial positions of the nodes (true) or use existing positions (false) + randomize: false, + // Extra spacing between components in non-compound graphs - componentSpacing: 100, + componentSpacing: 40, // Node repulsion (non overlapping) multiplier - nodeRepulsion: function( node ){ return 400000; }, + nodeRepulsion: function nodeRepulsion(node) { + return 2048; + }, // Node repulsion (overlapping) multiplier - nodeOverlap: 10, + nodeOverlap: 4, // Ideal edge (non nested) length - idealEdgeLength: function( edge ){ return 10; }, + idealEdgeLength: function idealEdgeLength(edge) { + return 32; + }, // Divisor to compute edge forces - edgeElasticity: function( edge ){ return 100; }, + edgeElasticity: function edgeElasticity(edge) { + return 32; + }, // Nesting factor (multiplier) to compute ideal edge length for nested edges - nestingFactor: 5, + nestingFactor: 1.2, // Gravity force (constant) - gravity: 80, + gravity: 1, // Maximum number of iterations to perform numIter: 1000, // Initial temperature (maximum node displacement) - initialTemp: 200, + initialTemp: 1000, // Cooling factor (how the temperature is reduced between consecutive iterations - coolingFactor: 0.95, + coolingFactor: 0.99, // Lower temperature threshold (below this point the layout will end) minTemp: 1.0, - // Whether to use threading to speed up the layout - useMultitasking: true + // Pass a reference to weaver to use threads for calculations + weaver: false }; - /** * @brief : constructor * @arg options : object containing layout options */ -function CoseLayout( options ){ - this.options = util.extend( {}, defaults, options ); +function CoseLayout(options) { + this.options = util.extend({}, defaults, options); this.options.layout = this; } - /** * @brief : runs the layout */ -CoseLayout.prototype.run = function(){ +CoseLayout.prototype.run = function () { var options = this.options; - var cy = options.cy; - var layout = this; - var thread = this.thread; + var cy = options.cy; + var layout = this; + var thread = this.thread; + var Thread = options.weaver ? options.weaver.Thread : null; - if( !thread || thread.stopped() ){ - thread = this.thread = Thread( { disabled: !options.useMultitasking } ); + var falseThread = { // use false thread as polyfill + listeners: [], + on: function on(e, cb) { + this.listeners.push({ event: e, callback: cb }); + + return this; + }, + trigger: function trigger(e) { + if (is.string(e)) { + e = { type: e }; + } + + var matchesEvent = function matchesEvent(l) { + return l.event === e.type; + }; + var trigger = function trigger(l) { + l.callback(e); + }; + + this.listeners.filter(matchesEvent).forEach(trigger); + + return this; + }, + pass: function pass(data) { + this.pass = data; + + return this; + }, + run: function run(cb) { + var pass = this.pass; + + return new Promise(function (resolve) { + resolve(cb(pass)); + }); + }, + stop: function stop() { + return this; + }, + stopped: function stopped() { + return true; + } + }; + + function broadcast(message) { + // for false thread + var e = { type: 'message', message: message }; + + falseThread.trigger(e); + } + + if (!thread || thread.stopped()) { + thread = this.thread = Thread ? new Thread() : falseThread; } layout.stopped = false; - layout.trigger( { type: 'layoutstart', layout: layout } ); + if (options.animate === true || options.animate === false) { + layout.emit({ type: 'layoutstart', layout: layout }); + } // Set DEBUG - Global variable - if( true === options.debug ){ + if (true === options.debug) { DEBUG = true; } else { DEBUG = false; } // Initialize layout info - var layoutInfo = createLayoutInfo( cy, layout, options ); + var layoutInfo = createLayoutInfo(cy, layout, options); // Show LayoutInfo contents if debugging - if( DEBUG ){ - printLayoutInfo( layoutInfo ); + if (DEBUG) { + printLayoutInfo(layoutInfo); } // If required, randomize node positions - // if (true === options.randomize) { - randomizePositions( layoutInfo, cy ); - // } + if (options.randomize) { + randomizePositions(layoutInfo, cy); + } var startTime = Date.now(); var refreshRequested = false; - var refresh = function( rOpts ){ + var refresh = function refresh(rOpts) { rOpts = rOpts || {}; - if( refreshRequested && !rOpts.next ){ + if (refreshRequested && !rOpts.next) { return; } - if( !rOpts.force && Date.now() - startTime < options.animationThreshold ){ + if (!rOpts.force && Date.now() - startTime < options.animationThreshold) { return; } refreshRequested = true; - util.requestAnimationFrame( function(){ - refreshPositions( layoutInfo, cy, options ); + util.requestAnimationFrame(function () { + refreshPositions(layoutInfo, cy, options); // Fit the graph if necessary - if( true === options.fit ){ - cy.fit( options.padding ); + if (true === options.fit) { + cy.fit(options.padding); } refreshRequested = false; - if( rOpts.next ){ rOpts.next(); } + if (rOpts.next) { + rOpts.next(); + } }); }; - thread.on( 'message', function( e ){ + thread.on('message', function (e) { var layoutNodes = e.message; layoutInfo.layoutNodes = layoutNodes; refresh(); - } ); + }); - thread.pass( { + thread.pass({ layoutInfo: layoutInfo, options: { animate: options.animate, @@ -10160,7 +18831,7 @@ CoseLayout.prototype.run = function(){ coolingFactor: options.coolingFactor, minTemp: options.minTemp } - } ).run( function( pass ){ + }).run(function (pass) { var layoutInfo = pass.layoutInfo; var options = pass.options; var stopped = false; @@ -10171,34 +18842,34 @@ CoseLayout.prototype.run = function(){ * @arg cy : Cytoscape object * @arg options : Layout options */ - var step = function( layoutInfo, options, step ){ + var step = function step(layoutInfo, options, _step) { // var s = "\n\n###############################"; // s += "\nSTEP: " + step; // s += "\n###############################\n"; // logDebug(s); // Calculate node repulsions - calculateNodeForces( layoutInfo, options ); + calculateNodeForces(layoutInfo, options); // Calculate edge forces - calculateEdgeForces( layoutInfo, options ); + calculateEdgeForces(layoutInfo, options); // Calculate gravity forces - calculateGravityForces( layoutInfo, options ); + calculateGravityForces(layoutInfo, options); // Propagate forces from parent to child - propagateForces( layoutInfo, options ); + propagateForces(layoutInfo, options); // Update positions based on calculated forces - updatePositions( layoutInfo, options ); + updatePositions(layoutInfo, options); }; /** * @brief : Computes the node repulsion forces */ - var calculateNodeForces = function( layoutInfo, options ){ + var calculateNodeForces = function calculateNodeForces(layoutInfo, options) { // Go through each of the graphs in graphSet // Nodes only repel each other if they belong to the same graph // var s = 'calculateNodeForces'; // logDebug(s); - for( var i = 0; i < layoutInfo.graphSet.length; i ++ ){ - var graph = layoutInfo.graphSet[ i ]; + for (var i = 0; i < layoutInfo.graphSet.length; i++) { + var graph = layoutInfo.graphSet[i]; var numNodes = graph.length; // s = "Set: " + graph.toString(); @@ -10206,84 +18877,90 @@ CoseLayout.prototype.run = function(){ // Now get all the pairs of nodes // Only get each pair once, (A, B) = (B, A) - for( var j = 0; j < numNodes; j++ ){ - var node1 = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ graph[ j ] ] ]; + for (var j = 0; j < numNodes; j++) { + var node1 = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[j]]]; - for( var k = j + 1; k < numNodes; k++ ){ - var node2 = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ graph[ k ] ] ]; + for (var k = j + 1; k < numNodes; k++) { + var node2 = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[k]]]; - nodeRepulsion( node1, node2, layoutInfo, options ); + nodeRepulsion(node1, node2, layoutInfo, options); } } } }; + var randomDistance = function randomDistance(max) { + return -max + 2 * max * Math.random(); + }; + /** * @brief : Compute the node repulsion forces between a pair of nodes */ - var nodeRepulsion = function( node1, node2, layoutInfo, options ){ + var nodeRepulsion = function nodeRepulsion(node1, node2, layoutInfo, options) { // var s = "Node repulsion. Node1: " + node1.id + " Node2: " + node2.id; var cmptId1 = node1.cmptId; var cmptId2 = node2.cmptId; - if( cmptId1 !== cmptId2 && !layoutInfo.isCompound ){ return; } + if (cmptId1 !== cmptId2 && !layoutInfo.isCompound) { + return; + } // Get direction of line connecting both node centers var directionX = node2.positionX - node1.positionX; var directionY = node2.positionY - node1.positionY; + var maxRandDist = 1; // s += "\ndirectionX: " + directionX + ", directionY: " + directionY; // If both centers are the same, apply a random force - if( 0 === directionX && 0 === directionY ){ - // s += "\nNodes have the same position."; - return; // TODO could be improved with random force + if (0 === directionX && 0 === directionY) { + directionX = randomDistance(maxRandDist); + directionY = randomDistance(maxRandDist); } - var overlap = nodesOverlap( node1, node2, directionX, directionY ); + var overlap = nodesOverlap(node1, node2, directionX, directionY); - if( overlap > 0 ){ + if (overlap > 0) { // s += "\nNodes DO overlap."; // s += "\nOverlap: " + overlap; // If nodes overlap, repulsion force is proportional // to the overlap - var force = options.nodeOverlap * overlap; + var force = options.nodeOverlap * overlap; // Compute the module and components of the force vector - var distance = Math.sqrt( directionX * directionX + directionY * directionY ); + var distance = Math.sqrt(directionX * directionX + directionY * directionY); // s += "\nDistance: " + distance; - var forceX = force * directionX / distance; - var forceY = force * directionY / distance; - + var forceX = force * directionX / distance; + var forceY = force * directionY / distance; } else { // s += "\nNodes do NOT overlap."; // If there's no overlap, force is inversely proportional // to squared distance // Get clipping points for both nodes - var point1 = findClippingPoint( node1, directionX, directionY ); - var point2 = findClippingPoint( node2, -1 * directionX, -1 * directionY ); + var point1 = findClippingPoint(node1, directionX, directionY); + var point2 = findClippingPoint(node2, -1 * directionX, -1 * directionY); // Use clipping points to compute distance - var distanceX = point2.x - point1.x; - var distanceY = point2.y - point1.y; + var distanceX = point2.x - point1.x; + var distanceY = point2.y - point1.y; var distanceSqr = distanceX * distanceX + distanceY * distanceY; - var distance = Math.sqrt( distanceSqr ); + var distance = Math.sqrt(distanceSqr); // s += "\nDistance: " + distance; // Compute the module and components of the force vector - var force = ( node1.nodeRepulsion + node2.nodeRepulsion ) / distanceSqr; + var force = (node1.nodeRepulsion + node2.nodeRepulsion) / distanceSqr; var forceX = force * distanceX / distance; var forceY = force * distanceY / distance; } // Apply force - if( !node1.isLocked ){ + if (!node1.isLocked) { node1.offsetX -= forceX; node1.offsetY -= forceY; } - if( !node2.isLocked ){ + if (!node2.isLocked) { node2.offsetX += forceX; node2.offsetY += forceY; } @@ -10298,22 +18975,22 @@ CoseLayout.prototype.run = function(){ * @brief : Determines whether two nodes overlap or not * @return : Amount of overlapping (0 => no overlap) */ - var nodesOverlap = function( node1, node2, dX, dY ){ + var nodesOverlap = function nodesOverlap(node1, node2, dX, dY) { - if( dX > 0 ){ + if (dX > 0) { var overlapX = node1.maxX - node2.minX; } else { var overlapX = node2.maxX - node1.minX; } - if( dY > 0 ){ + if (dY > 0) { var overlapY = node1.maxY - node2.minY; } else { var overlapY = node2.maxY - node1.minY; } - if( overlapX >= 0 && overlapY >= 0 ){ - return Math.sqrt( overlapX * overlapX + overlapY * overlapY ); + if (overlapX >= 0 && overlapY >= 0) { + return Math.sqrt(overlapX * overlapX + overlapY * overlapY); } else { return 0; } @@ -10323,15 +19000,15 @@ CoseLayout.prototype.run = function(){ * @brief : Finds the point in which an edge (direction dX, dY) intersects * the rectangular bounding box of it's source/target node */ - var findClippingPoint = function( node, dX, dY ){ + var findClippingPoint = function findClippingPoint(node, dX, dY) { // Shorcuts var X = node.positionX; var Y = node.positionY; var H = node.height || 1; var W = node.width || 1; - var dirSlope = dY / dX; - var nodeSlope = H / W; + var dirSlope = dY / dX; + var nodeSlope = H / W; // var s = 'Computing clipping point of node ' + node.id + // " . Height: " + H + ", Width: " + W + @@ -10339,64 +19016,60 @@ CoseLayout.prototype.run = function(){ // // Compute intersection var res = {}; - do { - // Case: Vertical direction (up) - if( 0 === dX && 0 < dY ){ - res.x = X; - // s += "\nUp direction"; - res.y = Y + H / 2; - break; - } - // Case: Vertical direction (down) - if( 0 === dX && 0 > dY ){ - res.x = X; - res.y = Y + H / 2; - // s += "\nDown direction"; - break; - } + // Case: Vertical direction (up) + if (0 === dX && 0 < dY) { + res.x = X; + // s += "\nUp direction"; + res.y = Y + H / 2; - // Case: Intersects the right border - if( 0 < dX && - -1 * nodeSlope <= dirSlope && - dirSlope <= nodeSlope ){ - res.x = X + W / 2; - res.y = Y + (W * dY / 2 / dX); - // s += "\nRightborder"; - break; - } + return res; + } - // Case: Intersects the left border - if( 0 > dX && - -1 * nodeSlope <= dirSlope && - dirSlope <= nodeSlope ){ - res.x = X - W / 2; - res.y = Y - (W * dY / 2 / dX); - // s += "\nLeftborder"; - break; - } + // Case: Vertical direction (down) + if (0 === dX && 0 > dY) { + res.x = X; + res.y = Y + H / 2; + // s += "\nDown direction"; - // Case: Intersects the top border - if( 0 < dY && - ( dirSlope <= -1 * nodeSlope || - dirSlope >= nodeSlope ) ){ - res.x = X + (H * dX / 2 / dY); - res.y = Y + H / 2; - // s += "\nTop border"; - break; - } + return res; + } - // Case: Intersects the bottom border - if( 0 > dY && - ( dirSlope <= -1 * nodeSlope || - dirSlope >= nodeSlope ) ){ - res.x = X - (H * dX / 2 / dY); - res.y = Y - H / 2; - // s += "\nBottom border"; - break; - } + // Case: Intersects the right border + if (0 < dX && -1 * nodeSlope <= dirSlope && dirSlope <= nodeSlope) { + res.x = X + W / 2; + res.y = Y + W * dY / 2 / dX; + // s += "\nRightborder"; - } while( false); + return res; + } + + // Case: Intersects the left border + if (0 > dX && -1 * nodeSlope <= dirSlope && dirSlope <= nodeSlope) { + res.x = X - W / 2; + res.y = Y - W * dY / 2 / dX; + // s += "\nLeftborder"; + + return res; + } + + // Case: Intersects the top border + if (0 < dY && (dirSlope <= -1 * nodeSlope || dirSlope >= nodeSlope)) { + res.x = X + H * dX / 2 / dY; + res.y = Y + H / 2; + // s += "\nTop border"; + + return res; + } + + // Case: Intersects the bottom border + if (0 > dY && (dirSlope <= -1 * nodeSlope || dirSlope >= nodeSlope)) { + res.x = X - H * dX / 2 / dY; + res.y = Y - H / 2; + // s += "\nBottom border"; + + return res; + } // s += "\nClipping point found at " + res.x + ", " + res.y; // logDebug(s); @@ -10406,15 +19079,15 @@ CoseLayout.prototype.run = function(){ /** * @brief : Calculates all edge forces */ - var calculateEdgeForces = function( layoutInfo, options ){ + var calculateEdgeForces = function calculateEdgeForces(layoutInfo, options) { // Iterate over all edges - for( var i = 0; i < layoutInfo.edgeSize; i++ ){ + for (var i = 0; i < layoutInfo.edgeSize; i++) { // Get edge, source & target nodes - var edge = layoutInfo.layoutEdges[ i ]; - var sourceIx = layoutInfo.idToIndex[ edge.sourceId ]; - var source = layoutInfo.layoutNodes[ sourceIx ]; - var targetIx = layoutInfo.idToIndex[ edge.targetId ]; - var target = layoutInfo.layoutNodes[ targetIx ]; + var edge = layoutInfo.layoutEdges[i]; + var sourceIx = layoutInfo.idToIndex[edge.sourceId]; + var source = layoutInfo.layoutNodes[sourceIx]; + var targetIx = layoutInfo.idToIndex[edge.targetId]; + var target = layoutInfo.layoutNodes[targetIx]; // Get direction of line connecting both node centers var directionX = target.positionX - source.positionX; @@ -10422,22 +19095,21 @@ CoseLayout.prototype.run = function(){ // If both centers are the same, do nothing. // A random force has already been applied as node repulsion - if( 0 === directionX && 0 === directionY ){ - return; + if (0 === directionX && 0 === directionY) { + continue; } // Get clipping points for both nodes - var point1 = findClippingPoint( source, directionX, directionY ); - var point2 = findClippingPoint( target, -1 * directionX, -1 * directionY ); - + var point1 = findClippingPoint(source, directionX, directionY); + var point2 = findClippingPoint(target, -1 * directionX, -1 * directionY); var lx = point2.x - point1.x; var ly = point2.y - point1.y; - var l = Math.sqrt( lx * lx + ly * ly ); + var l = Math.sqrt(lx * lx + ly * ly); - var force = Math.pow( edge.idealLength - l, 2 ) / edge.elasticity; + var force = Math.pow(edge.idealLength - l, 2) / edge.elasticity; - if( 0 !== l ){ + if (0 !== l) { var forceX = force * lx / l; var forceY = force * ly / l; } else { @@ -10446,12 +19118,12 @@ CoseLayout.prototype.run = function(){ } // Add this force to target and source nodes - if( !source.isLocked ){ + if (!source.isLocked) { source.offsetX += forceX; source.offsetY += forceY; } - if( !target.isLocked ){ + if (!target.isLocked) { target.offsetX -= forceX; target.offsetY -= forceY; } @@ -10465,26 +19137,26 @@ CoseLayout.prototype.run = function(){ /** * @brief : Computes gravity forces for all nodes */ - var calculateGravityForces = function( layoutInfo, options ){ + var calculateGravityForces = function calculateGravityForces(layoutInfo, options) { var distThreshold = 1; // var s = 'calculateGravityForces'; // logDebug(s); - for( var i = 0; i < layoutInfo.graphSet.length; i ++ ){ - var graph = layoutInfo.graphSet[ i ]; + for (var i = 0; i < layoutInfo.graphSet.length; i++) { + var graph = layoutInfo.graphSet[i]; var numNodes = graph.length; // s = "Set: " + graph.toString(); // logDebug(s); // Compute graph center - if( 0 === i ){ - var centerX = layoutInfo.clientHeight / 2; - var centerY = layoutInfo.clientWidth / 2; + if (0 === i) { + var centerX = layoutInfo.clientHeight / 2; + var centerY = layoutInfo.clientWidth / 2; } else { // Get Parent node for this graph, and use its position as center - var temp = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ graph[0] ] ]; - var parent = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ temp.parentId ] ]; + var temp = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[0]]]; + var parent = layoutInfo.layoutNodes[layoutInfo.idToIndex[temp.parentId]]; var centerX = parent.positionX; var centerY = parent.positionY; } @@ -10492,25 +19164,27 @@ CoseLayout.prototype.run = function(){ // logDebug(s); // Apply force to all nodes in graph - for( var j = 0; j < numNodes; j++ ){ - var node = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ graph[ j ] ] ]; + for (var j = 0; j < numNodes; j++) { + var node = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[j]]]; // s = "Node: " + node.id; - if( node.isLocked ){ continue; } + if (node.isLocked) { + continue; + } var dx = centerX - node.positionX; var dy = centerY - node.positionY; - var d = Math.sqrt( dx * dx + dy * dy ); - if( d > distThreshold ){ + var d = Math.sqrt(dx * dx + dy * dy); + if (d > distThreshold) { var fx = options.gravity * dx / d; var fy = options.gravity * dy / d; node.offsetX += fx; node.offsetY += fy; // s += ": Applied force: " + fx + ", " + fy; - } else { + } else {} // s += ": skypped since it's too close to center"; - } - // logDebug(s); + + // logDebug(s); } } }; @@ -10522,28 +19196,28 @@ CoseLayout.prototype.run = function(){ * @arg cy : cytoscape Object * @arg options : Layout options */ - var propagateForces = function( layoutInfo, options ){ + var propagateForces = function propagateForces(layoutInfo, options) { // Inline implementation of a queue, used for traversing the graph in BFS order var queue = []; - var start = 0; // Points to the start the queue - var end = -1; // Points to the end of the queue + var start = 0; // Points to the start the queue + var end = -1; // Points to the end of the queue // logDebug('propagateForces'); // Start by visiting the nodes in the root graph - queue.push.apply( queue, layoutInfo.graphSet[0] ); + queue.push.apply(queue, layoutInfo.graphSet[0]); end += layoutInfo.graphSet[0].length; // Traverse the graph, level by level, - while( start <= end ){ + while (start <= end) { // Get the node to visit and remove it from queue - var nodeId = queue[ start++ ]; - var nodeIndex = layoutInfo.idToIndex[ nodeId ]; - var node = layoutInfo.layoutNodes[ nodeIndex ]; - var children = node.children; + var nodeId = queue[start++]; + var nodeIndex = layoutInfo.idToIndex[nodeId]; + var node = layoutInfo.layoutNodes[nodeIndex]; + var children = node.children; // We only need to process the node if it's compound - if( 0 < children.length && !node.isLocked ){ + if (0 < children.length && !node.isLocked) { var offX = node.offsetX; var offY = node.offsetY; @@ -10552,20 +19226,19 @@ CoseLayout.prototype.run = function(){ // s += "\n Children: " + children.toString(); // logDebug(s); - for( var i = 0; i < children.length; i++ ){ - var childNode = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ children[ i ] ] ]; + for (var i = 0; i < children.length; i++) { + var childNode = layoutInfo.layoutNodes[layoutInfo.idToIndex[children[i]]]; // Propagate offset childNode.offsetX += offX; childNode.offsetY += offY; // Add children to queue to be visited - queue[ ++end ] = children[ i ]; + queue[++end] = children[i]; } // Reset parent offsets node.offsetX = 0; node.offsetY = 0; } - } }; @@ -10573,14 +19246,14 @@ CoseLayout.prototype.run = function(){ * @brief : Updates the layout model positions, based on * the accumulated forces */ - var updatePositions = function( layoutInfo, options ){ + var updatePositions = function updatePositions(layoutInfo, options) { // var s = 'Updating positions'; // logDebug(s); // Reset boundaries for compound nodes - for( var i = 0; i < layoutInfo.nodeSize; i++ ){ - var n = layoutInfo.layoutNodes[ i ]; - if( 0 < n.children.length ){ + for (var i = 0; i < layoutInfo.nodeSize; i++) { + var n = layoutInfo.layoutNodes[i]; + if (0 < n.children.length) { // logDebug("Resetting boundaries of compound node: " + n.id); n.maxX = undefined; n.minX = undefined; @@ -10589,9 +19262,9 @@ CoseLayout.prototype.run = function(){ } } - for( var i = 0; i < layoutInfo.nodeSize; i++ ){ - var n = layoutInfo.layoutNodes[ i ]; - if( 0 < n.children.length || n.isLocked ){ + for (var i = 0; i < layoutInfo.nodeSize; i++) { + var n = layoutInfo.layoutNodes[i]; + if (0 < n.children.length || n.isLocked) { // No need to set compound or locked node position // logDebug("Skipping position update of node: " + n.id); continue; @@ -10600,30 +19273,30 @@ CoseLayout.prototype.run = function(){ // n.positionX + ", " + n.positionY + ")."; // Limit displacement in order to improve stability - var tempForce = limitForce( n.offsetX, n.offsetY, layoutInfo.temperature ); + var tempForce = limitForce(n.offsetX, n.offsetY, layoutInfo.temperature); n.positionX += tempForce.x; n.positionY += tempForce.y; n.offsetX = 0; n.offsetY = 0; - n.minX = n.positionX - n.width; - n.maxX = n.positionX + n.width; - n.minY = n.positionY - n.height; - n.maxY = n.positionY + n.height; + n.minX = n.positionX - n.width; + n.maxX = n.positionX + n.width; + n.minY = n.positionY - n.height; + n.maxY = n.positionY + n.height; // s += " New Position: (" + n.positionX + ", " + n.positionY + ")."; // logDebug(s); // Update ancestry boudaries - updateAncestryBoundaries( n, layoutInfo ); + updateAncestryBoundaries(n, layoutInfo); } // Update size, position of compund nodes - for( var i = 0; i < layoutInfo.nodeSize; i++ ){ - var n = layoutInfo.layoutNodes[ i ]; - if( 0 < n.children.length && !n.isLocked ){ + for (var i = 0; i < layoutInfo.nodeSize; i++) { + var n = layoutInfo.layoutNodes[i]; + if (0 < n.children.length && !n.isLocked) { n.positionX = (n.maxX + n.minX) / 2; n.positionY = (n.maxY + n.minY) / 2; - n.width = n.maxX - n.minX; - n.height = n.maxY - n.minY; + n.width = n.maxX - n.minX; + n.height = n.maxY - n.minY; // s = "Updating position, size of compound node " + n.id; // s += "\nPositionX: " + n.positionX + ", PositionY: " + n.positionY; // s += "\nWidth: " + n.width + ", Height: " + n.height; @@ -10637,16 +19310,15 @@ CoseLayout.prototype.run = function(){ * greater (in modulo) than max. 8 Preserves force direction. */ - var limitForce = function( forceX, forceY, max ){ + var limitForce = function limitForce(forceX, forceY, max) { // var s = "Limiting force: (" + forceX + ", " + forceY + "). Max: " + max; - var force = Math.sqrt( forceX * forceX + forceY * forceY ); + var force = Math.sqrt(forceX * forceX + forceY * forceY); - if( force > max ){ + if (force > max) { var res = { x: max * forceX / force, y: max * forceY / force }; - } else { var res = { x: forceX, @@ -10664,10 +19336,10 @@ CoseLayout.prototype.run = function(){ * @brief : Function used for keeping track of compound node * sizes, since they should bound all their subnodes. */ - var updateAncestryBoundaries = function( node, layoutInfo ){ + var updateAncestryBoundaries = function updateAncestryBoundaries(node, layoutInfo) { // var s = "Propagating new position/size of node " + node.id; var parentId = node.parentId; - if( null == parentId ){ + if (null == parentId) { // If there's no parent, we are done // s += ". No parent node."; // logDebug(s); @@ -10675,41 +19347,41 @@ CoseLayout.prototype.run = function(){ } // Get Parent Node - var p = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ parentId ] ]; + var p = layoutInfo.layoutNodes[layoutInfo.idToIndex[parentId]]; var flag = false; // MaxX - if( null == p.maxX || node.maxX + p.padRight > p.maxX ){ + if (null == p.maxX || node.maxX + p.padRight > p.maxX) { p.maxX = node.maxX + p.padRight; flag = true; // s += "\nNew maxX for parent node " + p.id + ": " + p.maxX; } // MinX - if( null == p.minX || node.minX - p.padLeft < p.minX ){ + if (null == p.minX || node.minX - p.padLeft < p.minX) { p.minX = node.minX - p.padLeft; flag = true; // s += "\nNew minX for parent node " + p.id + ": " + p.minX; } // MaxY - if( null == p.maxY || node.maxY + p.padBottom > p.maxY ){ + if (null == p.maxY || node.maxY + p.padBottom > p.maxY) { p.maxY = node.maxY + p.padBottom; flag = true; // s += "\nNew maxY for parent node " + p.id + ": " + p.maxY; } // MinY - if( null == p.minY || node.minY - p.padTop < p.minY ){ + if (null == p.minY || node.minY - p.padTop < p.minY) { p.minY = node.minY - p.padTop; flag = true; // s += "\nNew minY for parent node " + p.id + ": " + p.minY; } // If updated boundaries, propagate changes upward - if( flag ){ + if (flag) { // logDebug(s); - return updateAncestryBoundaries( p, layoutInfo ); + return updateAncestryBoundaries(p, layoutInfo); } // s += ". No changes in boundaries/position of parent node " + p.id; @@ -10717,37 +19389,39 @@ CoseLayout.prototype.run = function(){ return; }; - var separateComponents = function( layutInfo, options ){ + var separateComponents = function separateComponents(layutInfo, options) { var nodes = layoutInfo.layoutNodes; var components = []; - for( var i = 0; i < nodes.length; i++ ){ - var node = nodes[ i ]; + for (var i = 0; i < nodes.length; i++) { + var node = nodes[i]; var cid = node.cmptId; - var component = components[ cid ] = components[ cid ] || []; + var component = components[cid] = components[cid] || []; - component.push( node ); + component.push(node); } var totalA = 0; - for( var i = 0; i < components.length; i++ ){ - var c = components[ i ]; + for (var i = 0; i < components.length; i++) { + var c = components[i]; - if( !c ){ continue; } + if (!c) { + continue; + } c.x1 = Infinity; c.x2 = -Infinity; c.y1 = Infinity; c.y2 = -Infinity; - for( var j = 0; j < c.length; j++ ){ - var n = c[ j ]; + for (var j = 0; j < c.length; j++) { + var n = c[j]; - c.x1 = Math.min( c.x1, n.positionX - n.width / 2 ); - c.x2 = Math.max( c.x2, n.positionX + n.width / 2 ); - c.y1 = Math.min( c.y1, n.positionY - n.height / 2 ); - c.y2 = Math.max( c.y2, n.positionY + n.height / 2 ); + c.x1 = Math.min(c.x1, n.positionX - n.width / 2); + c.x2 = Math.max(c.x2, n.positionX + n.width / 2); + c.y1 = Math.min(c.y1, n.positionY - n.height / 2); + c.y2 = Math.max(c.y2, n.positionY + n.height / 2); } c.w = c.x2 - c.x1; @@ -10756,25 +19430,27 @@ CoseLayout.prototype.run = function(){ totalA += c.w * c.h; } - components.sort( function( c1, c2 ){ + components.sort(function (c1, c2) { return c2.w * c2.h - c1.w * c1.h; - } ); + }); var x = 0; var y = 0; var usedW = 0; var rowH = 0; - var maxRowW = Math.sqrt( totalA ) * layoutInfo.clientWidth / layoutInfo.clientHeight; + var maxRowW = Math.sqrt(totalA) * layoutInfo.clientWidth / layoutInfo.clientHeight; - for( var i = 0; i < components.length; i++ ){ - var c = components[ i ]; + for (var i = 0; i < components.length; i++) { + var c = components[i]; - if( !c ){ continue; } + if (!c) { + continue; + } - for( var j = 0; j < c.length; j++ ){ - var n = c[ j ]; + for (var j = 0; j < c.length; j++) { + var n = c[j]; - if( !n.isLocked ){ + if (!n.isLocked) { n.positionX += x; n.positionY += y; } @@ -10782,9 +19458,9 @@ CoseLayout.prototype.run = function(){ x += c.w + options.componentSpacing; usedW += c.w + options.componentSpacing; - rowH = Math.max( rowH, c.h ); + rowH = Math.max(rowH, c.h); - if( usedW > maxRowW ){ + if (usedW > maxRowW) { y += rowH + options.componentSpacing; x = 0; usedW = 0; @@ -10793,20 +19469,20 @@ CoseLayout.prototype.run = function(){ } }; - var mainLoop = function( i ){ - if( stopped ){ + var mainLoop = function mainLoop(i) { + if (stopped) { // logDebug("Layout manually stopped. Stopping computation in step " + i); return false; } // Do one step in the phisical simulation - step( layoutInfo, options, i ); + step(layoutInfo, options, i); // Update temperature layoutInfo.temperature = layoutInfo.temperature * options.coolingFactor; // logDebug("New temperature: " + layoutInfo.temperature); - if( layoutInfo.temperature < options.minTemp ){ + if (layoutInfo.temperature < options.minTemp) { // logDebug("Temperature drop below minimum threshold. Stopping computation in step " + i); return false; } @@ -10820,81 +19496,88 @@ CoseLayout.prototype.run = function(){ do { var f = 0; - while( f < options.refresh && i < options.numIter ){ - var loopRet = mainLoop( i ); - if( !loopRet ){ break; } + while (f < options.refresh && i < options.numIter) { + var loopRet = mainLoop(i); + if (!loopRet) { + break; + } f++; i++; } - if( options.animate ){ - broadcast( layoutInfo.layoutNodes ); // eslint-disable-line no-undef + if (options.animate === true) { + broadcast(layoutInfo.layoutNodes); // eslint-disable-line no-undef } + } while (loopRet && i + 1 < options.numIter); - } while( loopRet && i + 1 < options.numIter ); - - separateComponents( layoutInfo, options ); + separateComponents(layoutInfo, options); return layoutInfo; - } ).then( function( layoutInfoUpdated ){ + }).then(function (layoutInfoUpdated) { layoutInfo.layoutNodes = layoutInfoUpdated.layoutNodes; // get the positions thread.stop(); done(); - } ); + }); - var done = function(){ - refresh({ - force: true, - next: function(){ - // Layout has finished - layout.one('layoutstop', options.stop); - layout.trigger({ type: 'layoutstop', layout: layout }); - } - }); + var done = function done() { + if (options.animate === true || options.animate === false) { + refresh({ + force: true, + next: function next() { + // Layout has finished + layout.one('layoutstop', options.stop); + layout.emit({ type: 'layoutstop', layout: layout }); + } + }); + } else { + options.eles.nodes().layoutPositions(layout, options, function (node) { + var lnode = layoutInfo.layoutNodes[layoutInfo.idToIndex[node.data('id')]]; + + return { x: lnode.positionX, y: lnode.positionY }; + }); + } }; return this; // chaining }; - /** * @brief : called on continuous layouts to stop them before they finish */ -CoseLayout.prototype.stop = function(){ +CoseLayout.prototype.stop = function () { this.stopped = true; - if( this.thread ){ + if (this.thread) { this.thread.stop(); } - this.trigger( 'layoutstop' ); + this.emit('layoutstop'); return this; // chaining }; -CoseLayout.prototype.destroy = function(){ - if( this.thread ){ +CoseLayout.prototype.destroy = function () { + if (this.thread) { this.thread.stop(); } return this; // chaining }; - /** * @brief : Creates an object which is contains all the data * used in the layout process * @arg cy : cytoscape.js object * @return : layoutInfo object initialized */ -var createLayoutInfo = function( cy, layout, options ){ +var createLayoutInfo = function createLayoutInfo(cy, layout, options) { // Shortcut var edges = options.eles.edges(); var nodes = options.eles.nodes(); - var layoutInfo = { + var layoutInfo = { isCompound: cy.hasCompoundNodes(), layoutNodes: [], idToIndex: {}, @@ -10906,148 +19589,148 @@ var createLayoutInfo = function( cy, layout, options ){ temperature: options.initialTemp, clientWidth: cy.width(), clientHeight: cy.width(), - boundingBox: math.makeBoundingBox( options.boundingBox ? options.boundingBox : { - x1: 0, y1: 0, w: cy.width(), h: cy.height() - } ) + boundingBox: math.makeBoundingBox(options.boundingBox ? options.boundingBox : { + x1: 0, y1: 0, w: cy.width(), h: cy.height() + }) }; var components = options.eles.components(); var id2cmptId = {}; - for( var i = 0; i < components.length; i++ ){ - var component = components[ i ]; + for (var i = 0; i < components.length; i++) { + var component = components[i]; - for( var j = 0; j < component.length; j++ ){ - var node = component[ j ]; + for (var j = 0; j < component.length; j++) { + var node = component[j]; - id2cmptId[ node.id() ] = i; + id2cmptId[node.id()] = i; } } // Iterate over all nodes, creating layout nodes - for( var i = 0; i < layoutInfo.nodeSize; i++ ){ - var n = nodes[ i ]; - var nbb = n.boundingBox(); + for (var i = 0; i < layoutInfo.nodeSize; i++) { + var n = nodes[i]; + var nbb = n.layoutDimensions(options); - var tempNode = {}; - tempNode.isLocked = n.locked(); - tempNode.id = n.data( 'id' ); - tempNode.parentId = n.data( 'parent' ); - tempNode.cmptId = id2cmptId[ n.id() ]; - tempNode.children = []; - tempNode.positionX = n.position( 'x' ); - tempNode.positionY = n.position( 'y' ); - tempNode.offsetX = 0; - tempNode.offsetY = 0; - tempNode.height = nbb.w; - tempNode.width = nbb.h; - tempNode.maxX = tempNode.positionX + tempNode.width / 2; - tempNode.minX = tempNode.positionX - tempNode.width / 2; - tempNode.maxY = tempNode.positionY + tempNode.height / 2; - tempNode.minY = tempNode.positionY - tempNode.height / 2; - tempNode.padLeft = parseFloat( n.style( 'padding-left' ) ); - tempNode.padRight = parseFloat( n.style( 'padding-right' ) ); - tempNode.padTop = parseFloat( n.style( 'padding-top' ) ); - tempNode.padBottom = parseFloat( n.style( 'padding-bottom' ) ); + var tempNode = {}; + tempNode.isLocked = n.locked(); + tempNode.id = n.data('id'); + tempNode.parentId = n.data('parent'); + tempNode.cmptId = id2cmptId[n.id()]; + tempNode.children = []; + tempNode.positionX = n.position('x'); + tempNode.positionY = n.position('y'); + tempNode.offsetX = 0; + tempNode.offsetY = 0; + tempNode.height = nbb.w; + tempNode.width = nbb.h; + tempNode.maxX = tempNode.positionX + tempNode.width / 2; + tempNode.minX = tempNode.positionX - tempNode.width / 2; + tempNode.maxY = tempNode.positionY + tempNode.height / 2; + tempNode.minY = tempNode.positionY - tempNode.height / 2; + tempNode.padLeft = parseFloat(n.style('padding')); + tempNode.padRight = parseFloat(n.style('padding')); + tempNode.padTop = parseFloat(n.style('padding')); + tempNode.padBottom = parseFloat(n.style('padding')); // forces - tempNode.nodeRepulsion = is.fn( options.nodeRepulsion ) ? options.nodeRepulsion.call( n, n ) : options.nodeRepulsion; + tempNode.nodeRepulsion = is.fn(options.nodeRepulsion) ? options.nodeRepulsion(n) : options.nodeRepulsion; // Add new node - layoutInfo.layoutNodes.push( tempNode ); + layoutInfo.layoutNodes.push(tempNode); // Add entry to id-index map - layoutInfo.idToIndex[ tempNode.id ] = i; + layoutInfo.idToIndex[tempNode.id] = i; } // Inline implementation of a queue, used for traversing the graph in BFS order var queue = []; - var start = 0; // Points to the start the queue - var end = -1; // Points to the end of the queue + var start = 0; // Points to the start the queue + var end = -1; // Points to the end of the queue var tempGraph = []; // Second pass to add child information and // initialize queue for hierarchical traversal - for( var i = 0; i < layoutInfo.nodeSize; i++ ){ - var n = layoutInfo.layoutNodes[ i ]; + for (var i = 0; i < layoutInfo.nodeSize; i++) { + var n = layoutInfo.layoutNodes[i]; var p_id = n.parentId; // Check if node n has a parent node - if( null != p_id ){ + if (null != p_id) { // Add node Id to parent's list of children - layoutInfo.layoutNodes[ layoutInfo.idToIndex[ p_id ] ].children.push( n.id ); + layoutInfo.layoutNodes[layoutInfo.idToIndex[p_id]].children.push(n.id); } else { // If a node doesn't have a parent, then it's in the root graph - queue[ ++end ] = n.id; - tempGraph.push( n.id ); + queue[++end] = n.id; + tempGraph.push(n.id); } } // Add root graph to graphSet - layoutInfo.graphSet.push( tempGraph ); + layoutInfo.graphSet.push(tempGraph); // Traverse the graph, level by level, - while( start <= end ){ + while (start <= end) { // Get the node to visit and remove it from queue - var node_id = queue[ start++ ]; - var node_ix = layoutInfo.idToIndex[ node_id ]; - var node = layoutInfo.layoutNodes[ node_ix ]; + var node_id = queue[start++]; + var node_ix = layoutInfo.idToIndex[node_id]; + var node = layoutInfo.layoutNodes[node_ix]; var children = node.children; - if( children.length > 0 ){ + if (children.length > 0) { // Add children nodes as a new graph to graph set - layoutInfo.graphSet.push( children ); + layoutInfo.graphSet.push(children); // Add children to que queue to be visited - for( var i = 0; i < children.length; i++ ){ - queue[ ++end ] = children[ i ]; + for (var i = 0; i < children.length; i++) { + queue[++end] = children[i]; } } } // Create indexToGraph map - for( var i = 0; i < layoutInfo.graphSet.length; i++ ){ - var graph = layoutInfo.graphSet[ i ]; - for( var j = 0; j < graph.length; j++ ){ - var index = layoutInfo.idToIndex[ graph[ j ] ]; - layoutInfo.indexToGraph[ index ] = i; + for (var i = 0; i < layoutInfo.graphSet.length; i++) { + var graph = layoutInfo.graphSet[i]; + for (var j = 0; j < graph.length; j++) { + var index = layoutInfo.idToIndex[graph[j]]; + layoutInfo.indexToGraph[index] = i; } } // Iterate over all edges, creating Layout Edges - for( var i = 0; i < layoutInfo.edgeSize; i++ ){ - var e = edges[ i ]; + for (var i = 0; i < layoutInfo.edgeSize; i++) { + var e = edges[i]; var tempEdge = {}; - tempEdge.id = e.data( 'id' ); - tempEdge.sourceId = e.data( 'source' ); - tempEdge.targetId = e.data( 'target' ); + tempEdge.id = e.data('id'); + tempEdge.sourceId = e.data('source'); + tempEdge.targetId = e.data('target'); // Compute ideal length - var idealLength = is.fn( options.idealEdgeLength ) ? options.idealEdgeLength.call( e, e ) : options.idealEdgeLength; - var elasticity = is.fn( options.edgeElasticity ) ? options.edgeElasticity.call( e, e ) : options.edgeElasticity; + var idealLength = is.fn(options.idealEdgeLength) ? options.idealEdgeLength(e) : options.idealEdgeLength; + var elasticity = is.fn(options.edgeElasticity) ? options.edgeElasticity(e) : options.edgeElasticity; // Check if it's an inter graph edge - var sourceIx = layoutInfo.idToIndex[ tempEdge.sourceId ]; - var targetIx = layoutInfo.idToIndex[ tempEdge.targetId ]; - var sourceGraph = layoutInfo.indexToGraph[ sourceIx ]; - var targetGraph = layoutInfo.indexToGraph[ targetIx ]; + var sourceIx = layoutInfo.idToIndex[tempEdge.sourceId]; + var targetIx = layoutInfo.idToIndex[tempEdge.targetId]; + var sourceGraph = layoutInfo.indexToGraph[sourceIx]; + var targetGraph = layoutInfo.indexToGraph[targetIx]; - if( sourceGraph != targetGraph ){ + if (sourceGraph != targetGraph) { // Find lowest common graph ancestor - var lca = findLCA( tempEdge.sourceId, tempEdge.targetId, layoutInfo ); + var lca = findLCA(tempEdge.sourceId, tempEdge.targetId, layoutInfo); // Compute sum of node depths, relative to lca graph - var lcaGraph = layoutInfo.graphSet[ lca ]; - var depth = 0; + var lcaGraph = layoutInfo.graphSet[lca]; + var depth = 0; // Source depth - var tempNode = layoutInfo.layoutNodes[ sourceIx ]; - while( -1 === lcaGraph.indexOf( tempNode.id ) ){ - tempNode = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ tempNode.parentId ] ]; + var tempNode = layoutInfo.layoutNodes[sourceIx]; + while (-1 === lcaGraph.indexOf(tempNode.id)) { + tempNode = layoutInfo.layoutNodes[layoutInfo.idToIndex[tempNode.parentId]]; depth++; } // Target depth - tempNode = layoutInfo.layoutNodes[ targetIx ]; - while( -1 === lcaGraph.indexOf( tempNode.id ) ){ - tempNode = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ tempNode.parentId ] ]; + tempNode = layoutInfo.layoutNodes[targetIx]; + while (-1 === lcaGraph.indexOf(tempNode.id)) { + tempNode = layoutInfo.layoutNodes[layoutInfo.idToIndex[tempNode.parentId]]; depth++; } @@ -11062,14 +19745,13 @@ var createLayoutInfo = function( cy, layout, options ){ tempEdge.idealLength = idealLength; tempEdge.elasticity = elasticity; - layoutInfo.layoutEdges.push( tempEdge ); + layoutInfo.layoutEdges.push(tempEdge); } // Finally, return layoutInfo object return layoutInfo; }; - /** * @brief : This function finds the index of the lowest common * graph ancestor between 2 nodes in the subtree @@ -11081,10 +19763,10 @@ var createLayoutInfo = function( cy, layout, options ){ * @arg layoutInfo: layoutInfo object * */ -var findLCA = function( node1, node2, layoutInfo ){ +var findLCA = function findLCA(node1, node2, layoutInfo) { // Find their common ancester, starting from the root graph - var res = findLCA_aux( node1, node2, 0, layoutInfo ); - if( 2 > res.count ){ + var res = findLCA_aux(node1, node2, 0, layoutInfo); + if (2 > res.count) { // If aux function couldn't find the common ancester, // then it is the root graph return 0; @@ -11093,7 +19775,6 @@ var findLCA = function( node1, node2, layoutInfo ){ } }; - /** * @brief : Auxiliary function used for LCA computation * @@ -11108,34 +19789,34 @@ var findLCA = function( node1, node2, layoutInfo ){ * Y is the graph index of the lowest graph containing * all X nodes */ -var findLCA_aux = function( node1, node2, graphIx, layoutInfo ){ - var graph = layoutInfo.graphSet[ graphIx ]; +var findLCA_aux = function findLCA_aux(node1, node2, graphIx, layoutInfo) { + var graph = layoutInfo.graphSet[graphIx]; // If both nodes belongs to graphIx - if( -1 < graph.indexOf( node1 ) && -1 < graph.indexOf( node2 ) ){ - return {count: 2, graph: graphIx}; + if (-1 < graph.indexOf(node1) && -1 < graph.indexOf(node2)) { + return { count: 2, graph: graphIx }; } // Make recursive calls for all subgraphs var c = 0; - for( var i = 0; i < graph.length; i++ ){ - var nodeId = graph[ i ]; - var nodeIx = layoutInfo.idToIndex[ nodeId ]; - var children = layoutInfo.layoutNodes[ nodeIx ].children; + for (var i = 0; i < graph.length; i++) { + var nodeId = graph[i]; + var nodeIx = layoutInfo.idToIndex[nodeId]; + var children = layoutInfo.layoutNodes[nodeIx].children; // If the node has no child, skip it - if( 0 === children.length ){ + if (0 === children.length) { continue; } - var childGraphIx = layoutInfo.indexToGraph[ layoutInfo.idToIndex[ children[0] ] ]; - var result = findLCA_aux( node1, node2, childGraphIx, layoutInfo ); - if( 0 === result.count ){ + var childGraphIx = layoutInfo.indexToGraph[layoutInfo.idToIndex[children[0]]]; + var result = findLCA_aux(node1, node2, childGraphIx, layoutInfo); + if (0 === result.count) { // Neither node1 nor node2 are present in this subgraph continue; - } else if( 1 === result.count ){ + } else if (1 === result.count) { // One of (node1, node2) is present in this subgraph c++; - if( 2 === c ){ + if (2 === c) { // We've already found both nodes, no need to keep searching break; } @@ -11145,102 +19826,85 @@ var findLCA_aux = function( node1, node2, graphIx, layoutInfo ){ } } - return {count: c, graph: graphIx}; + return { count: c, graph: graphIx }; }; - /** * @brief: printsLayoutInfo into js console * Only used for debbuging */ -var printLayoutInfo = function( layoutInfo ){ +var printLayoutInfo = function printLayoutInfo(layoutInfo) { /* eslint-disable */ - if( !DEBUG ){ + if (!DEBUG) { return; } - console.debug( 'layoutNodes:' ); - for( var i = 0; i < layoutInfo.nodeSize; i++ ){ - var n = layoutInfo.layoutNodes[ i ]; - var s = - '\nindex: ' + i + - '\nId: ' + n.id + - '\nChildren: ' + n.children.toString() + - '\nparentId: ' + n.parentId + - '\npositionX: ' + n.positionX + - '\npositionY: ' + n.positionY + - '\nOffsetX: ' + n.offsetX + - '\nOffsetY: ' + n.offsetY + - '\npadLeft: ' + n.padLeft + - '\npadRight: ' + n.padRight + - '\npadTop: ' + n.padTop + - '\npadBottom: ' + n.padBottom; + console.debug('layoutNodes:'); + for (var i = 0; i < layoutInfo.nodeSize; i++) { + var n = layoutInfo.layoutNodes[i]; + var s = '\nindex: ' + i + '\nId: ' + n.id + '\nChildren: ' + n.children.toString() + '\nparentId: ' + n.parentId + '\npositionX: ' + n.positionX + '\npositionY: ' + n.positionY + '\nOffsetX: ' + n.offsetX + '\nOffsetY: ' + n.offsetY + '\npadLeft: ' + n.padLeft + '\npadRight: ' + n.padRight + '\npadTop: ' + n.padTop + '\npadBottom: ' + n.padBottom; - console.debug( s ); + console.debug(s); } - console.debug( 'idToIndex' ); - for( var i in layoutInfo.idToIndex ){ - console.debug( 'Id: ' + i + '\nIndex: ' + layoutInfo.idToIndex[ i ] ); + console.debug('idToIndex'); + for (var i in layoutInfo.idToIndex) { + console.debug('Id: ' + i + '\nIndex: ' + layoutInfo.idToIndex[i]); } - console.debug( 'Graph Set' ); + console.debug('Graph Set'); var set = layoutInfo.graphSet; - for( var i = 0; i < set.length; i ++ ){ - console.debug( 'Set : ' + i + ': ' + set[ i ].toString() ); + for (var i = 0; i < set.length; i++) { + console.debug('Set : ' + i + ': ' + set[i].toString()); } var s = 'IndexToGraph'; - for( var i = 0; i < layoutInfo.indexToGraph.length; i ++ ){ - s += '\nIndex : ' + i + ' Graph: ' + layoutInfo.indexToGraph[ i ]; + for (var i = 0; i < layoutInfo.indexToGraph.length; i++) { + s += '\nIndex : ' + i + ' Graph: ' + layoutInfo.indexToGraph[i]; } - console.debug( s ); + console.debug(s); s = 'Layout Edges'; - for( var i = 0; i < layoutInfo.layoutEdges.length; i++ ){ - var e = layoutInfo.layoutEdges[ i ]; - s += '\nEdge Index: ' + i + ' ID: ' + e.id + - ' SouceID: ' + e.sourceId + ' TargetId: ' + e.targetId + - ' Ideal Length: ' + e.idealLength; + for (var i = 0; i < layoutInfo.layoutEdges.length; i++) { + var e = layoutInfo.layoutEdges[i]; + s += '\nEdge Index: ' + i + ' ID: ' + e.id + ' SouceID: ' + e.sourceId + ' TargetId: ' + e.targetId + ' Ideal Length: ' + e.idealLength; } - console.debug( s ); + console.debug(s); - s = 'nodeSize: ' + layoutInfo.nodeSize; + s = 'nodeSize: ' + layoutInfo.nodeSize; s += '\nedgeSize: ' + layoutInfo.edgeSize; s += '\ntemperature: ' + layoutInfo.temperature; - console.debug( s ); + console.debug(s); return; /* eslint-enable */ }; - /** * @brief : Randomizes the position of all nodes */ -var randomizePositions = function( layoutInfo, cy ){ - var width = layoutInfo.clientWidth; - var height = layoutInfo.clientHeight; +var randomizePositions = function randomizePositions(layoutInfo, cy) { + var width = layoutInfo.clientWidth; + var height = layoutInfo.clientHeight; - for( var i = 0; i < layoutInfo.nodeSize; i++ ){ - var n = layoutInfo.layoutNodes[ i ]; + for (var i = 0; i < layoutInfo.nodeSize; i++) { + var n = layoutInfo.layoutNodes[i]; // No need to randomize compound nodes or locked nodes - if( 0 === n.children.length && !n.isLocked ){ + if (0 === n.children.length && !n.isLocked) { n.positionX = Math.random() * width; n.positionY = Math.random() * height; } } }; - /** * @brief : Updates the positions of nodes in the network * @arg layoutInfo : LayoutInfo object * @arg cy : Cytoscape object * @arg options : Layout options */ -var refreshPositions = function( layoutInfo, cy, options ){ +var refreshPositions = function refreshPositions(layoutInfo, cy, options) { // var s = 'Refreshing positions'; // logDebug(s); @@ -11249,28 +19913,29 @@ var refreshPositions = function( layoutInfo, cy, options ){ var bb = layoutInfo.boundingBox; var coseBB = { x1: Infinity, x2: -Infinity, y1: Infinity, y2: -Infinity }; - if( options.boundingBox ){ - nodes.forEach( function( node ){ - var lnode = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ node.data( 'id' ) ] ]; + if (options.boundingBox) { + nodes.forEach(function (node) { + var lnode = layoutInfo.layoutNodes[layoutInfo.idToIndex[node.data('id')]]; - coseBB.x1 = Math.min( coseBB.x1, lnode.positionX ); - coseBB.x2 = Math.max( coseBB.x2, lnode.positionX ); + coseBB.x1 = Math.min(coseBB.x1, lnode.positionX); + coseBB.x2 = Math.max(coseBB.x2, lnode.positionX); - coseBB.y1 = Math.min( coseBB.y1, lnode.positionY ); - coseBB.y2 = Math.max( coseBB.y2, lnode.positionY ); - } ); + coseBB.y1 = Math.min(coseBB.y1, lnode.positionY); + coseBB.y2 = Math.max(coseBB.y2, lnode.positionY); + }); coseBB.w = coseBB.x2 - coseBB.x1; coseBB.h = coseBB.y2 - coseBB.y1; } - nodes.positions( function( i, ele ){ - var lnode = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ ele.data( 'id' ) ] ]; + nodes.positions(function (ele, i) { + var lnode = layoutInfo.layoutNodes[layoutInfo.idToIndex[ele.data('id')]]; // s = "Node: " + lnode.id + ". Refreshed position: (" + // lnode.positionX + ", " + lnode.positionY + ")."; // logDebug(s); - if( options.boundingBox ){ // then add extra bounding box constraint + if (options.boundingBox) { + // then add extra bounding box constraint var pctX = (lnode.positionX - coseBB.x1) / coseBB.w; var pctY = (lnode.positionY - coseBB.y1) / coseBB.h; @@ -11284,15 +19949,15 @@ var refreshPositions = function( layoutInfo, cy, options ){ y: lnode.positionY }; } - } ); + }); // Trigger layoutReady only on first call - if( true !== layoutInfo.ready ){ + if (true !== layoutInfo.ready) { // s = 'Triggering layoutready'; // logDebug(s); layoutInfo.ready = true; - layout.one( 'layoutready', options.ready ); - layout.trigger( { type: 'layoutready', layout: this } ); + layout.one('layoutready', options.ready); + layout.emit({ type: 'layoutready', layout: this }); } }; @@ -11307,11 +19972,15 @@ var refreshPositions = function( layoutInfo, cy, options ){ module.exports = CoseLayout; -},{"../../is":83,"../../math":85,"../../thread":98,"../../util":100}],52:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 102 */ +/***/ (function(module, exports, __webpack_require__) { -var util = _dereq_( '../../util' ); -var math = _dereq_( '../../math' ); +"use strict"; + + +var util = __webpack_require__(1); +var math = __webpack_require__(2); var defaults = { fit: true, // whether to fit the viewport to the graph @@ -11319,57 +19988,64 @@ var defaults = { boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h } avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space avoidOverlapPadding: 10, // extra spacing around nodes when avoidOverlap: true + nodeDimensionsIncludeLabels: false, // Excludes the label when calculating node bounding boxes for the layout algorithm + spacingFactor: undefined, // Applies a multiplicative factor (>0) to expand or compress the overall area that the nodes take up condense: false, // uses all available space on false, uses minimal space on true rows: undefined, // force num of rows in the grid cols: undefined, // force num of columns in the grid - position: function( node ){}, // returns { row, col } for element + position: function position(node) {}, // returns { row, col } for element sort: undefined, // a sorting function to order the nodes; e.g. function(a, b){ return a.data('weight') - b.data('weight') } animate: false, // whether to transition the node positions animationDuration: 500, // duration of animation in ms if enabled animationEasing: undefined, // easing of animation if enabled + animateFilter: function animateFilter(node, i) { + return true; + }, // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts ready: undefined, // callback on layoutready - stop: undefined // callback on layoutstop + stop: undefined, // callback on layoutstop + transform: function transform(node, position) { + return position; + } // transform a given node position. Useful for changing flow direction in discrete layouts }; -function GridLayout( options ){ - this.options = util.extend( {}, defaults, options ); +function GridLayout(options) { + this.options = util.extend({}, defaults, options); } -GridLayout.prototype.run = function(){ +GridLayout.prototype.run = function () { var params = this.options; var options = params; var cy = params.cy; var eles = options.eles; - var nodes = eles.nodes().not( ':parent' ); + var nodes = eles.nodes().not(':parent'); - if( options.sort ){ - nodes = nodes.sort( options.sort ); + if (options.sort) { + nodes = nodes.sort(options.sort); } - var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : { + var bb = math.makeBoundingBox(options.boundingBox ? options.boundingBox : { x1: 0, y1: 0, w: cy.width(), h: cy.height() - } ); + }); - if( bb.h === 0 || bb.w === 0 ){ - nodes.layoutPositions( this, options, function(){ + if (bb.h === 0 || bb.w === 0) { + nodes.layoutPositions(this, options, function (ele) { return { x: bb.x1, y: bb.y1 }; - } ); - + }); } else { // width/height * splits^2 = cells where splits is number of times to split width var cells = nodes.size(); - var splits = Math.sqrt( cells * bb.h / bb.w ); - var rows = Math.round( splits ); - var cols = Math.round( bb.w / bb.h * splits ); + var splits = Math.sqrt(cells * bb.h / bb.w); + var rows = Math.round(splits); + var cols = Math.round(bb.w / bb.h * splits); - var small = function( val ){ - if( val == null ){ - return Math.min( rows, cols ); + var small = function small(val) { + if (val == null) { + return Math.min(rows, cols); } else { - var min = Math.min( rows, cols ); - if( min == rows ){ + var min = Math.min(rows, cols); + if (min == rows) { rows = val; } else { cols = val; @@ -11377,12 +20053,12 @@ GridLayout.prototype.run = function(){ } }; - var large = function( val ){ - if( val == null ){ - return Math.max( rows, cols ); + var large = function large(val) { + if (val == null) { + return Math.max(rows, cols); } else { - var max = Math.max( rows, cols ); - if( max == rows ){ + var max = Math.max(rows, cols); + if (max == rows) { rows = val; } else { cols = val; @@ -11394,91 +20070,92 @@ GridLayout.prototype.run = function(){ var oCols = options.cols != null ? options.cols : options.columns; // if rows or columns were set in options, use those values - if( oRows != null && oCols != null ){ + if (oRows != null && oCols != null) { rows = oRows; cols = oCols; - } else if( oRows != null && oCols == null ){ + } else if (oRows != null && oCols == null) { rows = oRows; - cols = Math.ceil( cells / rows ); - } else if( oRows == null && oCols != null ){ + cols = Math.ceil(cells / rows); + } else if (oRows == null && oCols != null) { cols = oCols; - rows = Math.ceil( cells / cols ); + rows = Math.ceil(cells / cols); } // otherwise use the automatic values and adjust accordingly // if rounding was up, see if we can reduce rows or columns - else if( cols * rows > cells ){ - var sm = small(); - var lg = large(); - - // reducing the small side takes away the most cells, so try it first - if( (sm - 1) * lg >= cells ){ - small( sm - 1 ); - } else if( (lg - 1) * sm >= cells ){ - large( lg - 1 ); - } - } else { - - // if rounding was too low, add rows or columns - while( cols * rows < cells ){ + else if (cols * rows > cells) { var sm = small(); var lg = large(); - // try to add to larger side first (adds less in multiplication) - if( (lg + 1) * sm >= cells ){ - large( lg + 1 ); - } else { - small( sm + 1 ); + // reducing the small side takes away the most cells, so try it first + if ((sm - 1) * lg >= cells) { + small(sm - 1); + } else if ((lg - 1) * sm >= cells) { + large(lg - 1); + } + } else { + + // if rounding was too low, add rows or columns + while (cols * rows < cells) { + var _sm = small(); + var _lg = large(); + + // try to add to larger side first (adds less in multiplication) + if ((_lg + 1) * _sm >= cells) { + large(_lg + 1); + } else { + small(_sm + 1); + } } } - } var cellWidth = bb.w / cols; var cellHeight = bb.h / rows; - if( options.condense ){ + if (options.condense) { cellWidth = 0; cellHeight = 0; } - if( options.avoidOverlap ){ - for( var i = 0; i < nodes.length; i++ ){ - var node = nodes[ i ]; + if (options.avoidOverlap) { + for (var i = 0; i < nodes.length; i++) { + var node = nodes[i]; var pos = node._private.position; - if( pos.x == null || pos.y == null ){ // for bb + if (pos.x == null || pos.y == null) { + // for bb pos.x = 0; pos.y = 0; } - var nbb = node.boundingBox(); + var nbb = node.layoutDimensions(options); var p = options.avoidOverlapPadding; var w = nbb.w + p; var h = nbb.h + p; - cellWidth = Math.max( cellWidth, w ); - cellHeight = Math.max( cellHeight, h ); + cellWidth = Math.max(cellWidth, w); + cellHeight = Math.max(cellHeight, h); } } var cellUsed = {}; // e.g. 'c-0-2' => true - var used = function( row, col ){ - return cellUsed[ 'c-' + row + '-' + col ] ? true : false; + var used = function used(row, col) { + return cellUsed['c-' + row + '-' + col] ? true : false; }; - var use = function( row, col ){ - cellUsed[ 'c-' + row + '-' + col ] = true; + var use = function use(row, col) { + cellUsed['c-' + row + '-' + col] = true; }; // to keep track of current cell position var row = 0; var col = 0; - var moveToNextCell = function(){ + var moveToNextCell = function moveToNextCell() { col++; - if( col >= cols ){ + if (col >= cols) { col = 0; row++; } @@ -11486,107 +20163,99 @@ GridLayout.prototype.run = function(){ // get a cache of all the manual positions var id2manPos = {}; - for( var i = 0; i < nodes.length; i++ ){ - var node = nodes[ i ]; - var rcPos = options.position( node ); + for (var _i = 0; _i < nodes.length; _i++) { + var _node = nodes[_i]; + var rcPos = options.position(_node); - if( rcPos && (rcPos.row !== undefined || rcPos.col !== undefined) ){ // must have at least row or col def'd - var pos = { + if (rcPos && (rcPos.row !== undefined || rcPos.col !== undefined)) { + // must have at least row or col def'd + var _pos = { row: rcPos.row, col: rcPos.col }; - if( pos.col === undefined ){ // find unused col - pos.col = 0; + if (_pos.col === undefined) { + // find unused col + _pos.col = 0; - while( used( pos.row, pos.col ) ){ - pos.col++; + while (used(_pos.row, _pos.col)) { + _pos.col++; } - } else if( pos.row === undefined ){ // find unused row - pos.row = 0; + } else if (_pos.row === undefined) { + // find unused row + _pos.row = 0; - while( used( pos.row, pos.col ) ){ - pos.row++; + while (used(_pos.row, _pos.col)) { + _pos.row++; } } - id2manPos[ node.id() ] = pos; - use( pos.row, pos.col ); + id2manPos[_node.id()] = _pos; + use(_pos.row, _pos.col); } } - var getPos = function( i, element ){ - var x, y; + var getPos = function getPos(element, i) { + var x = void 0, + y = void 0; - if( element.locked() || element.isParent() ){ + if (element.locked() || element.isParent()) { return false; } // see if we have a manual position set - var rcPos = id2manPos[ element.id() ]; - if( rcPos ){ + var rcPos = id2manPos[element.id()]; + if (rcPos) { x = rcPos.col * cellWidth + cellWidth / 2 + bb.x1; y = rcPos.row * cellHeight + cellHeight / 2 + bb.y1; + } else { + // otherwise set automatically - } else { // otherwise set automatically - - while( used( row, col ) ){ + while (used(row, col)) { moveToNextCell(); } x = col * cellWidth + cellWidth / 2 + bb.x1; y = row * cellHeight + cellHeight / 2 + bb.y1; - use( row, col ); + use(row, col); moveToNextCell(); } return { x: x, y: y }; - }; - nodes.layoutPositions( this, options, getPos ); + nodes.layoutPositions(this, options, getPos); } return this; // chaining - }; module.exports = GridLayout; -},{"../../math":85,"../../util":100}],53:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 103 */ +/***/ (function(module, exports, __webpack_require__) { -module.exports = [ - { name: 'breadthfirst', impl: _dereq_( './breadthfirst' ) }, - { name: 'circle', impl: _dereq_( './circle' ) }, - { name: 'concentric',impl: _dereq_( './concentric' ) }, - { name: 'cose', impl: _dereq_( './cose' ) }, - { name: 'grid', impl: _dereq_( './grid' ) }, - { name: 'null', impl: _dereq_( './null' ) }, - { name: 'preset', impl: _dereq_( './preset' ) }, - { name: 'random', impl: _dereq_( './random' ) } -]; +"use strict"; -},{"./breadthfirst":48,"./circle":49,"./concentric":50,"./cose":51,"./grid":52,"./null":54,"./preset":55,"./random":56}],54:[function(_dereq_,module,exports){ -'use strict'; -var util = _dereq_( '../../util' ); +var util = __webpack_require__(1); // default layout options var defaults = { - ready: function(){}, // on layoutready - stop: function(){} // on layoutstop + ready: function ready() {}, // on layoutready + stop: function stop() {} // on layoutstop }; // constructor // options : object containing layout options -function NullLayout( options ){ - this.options = util.extend( {}, defaults, options ); +function NullLayout(options) { + this.options = util.extend({}, defaults, options); } // runs the layout -NullLayout.prototype.run = function(){ +NullLayout.prototype.run = function () { var options = this.options; var eles = options.eles; // elements to consider in the layout var layout = this; @@ -11594,39 +20263,43 @@ NullLayout.prototype.run = function(){ // cy is automatically populated for us in the constructor var cy = options.cy; // jshint ignore:line - layout.trigger( 'layoutstart' ); + layout.emit('layoutstart'); // puts all nodes at (0, 0) - eles.nodes().positions( function(){ + eles.nodes().positions(function () { return { x: 0, y: 0 }; - } ); + }); // trigger layoutready when each node has had its position set at least once - layout.one( 'layoutready', options.ready ); - layout.trigger( 'layoutready' ); + layout.one('layoutready', options.ready); + layout.emit('layoutready'); // trigger layoutstop when the layout stops (e.g. finishes) - layout.one( 'layoutstop', options.stop ); - layout.trigger( 'layoutstop' ); + layout.one('layoutstop', options.stop); + layout.emit('layoutstop'); return this; // chaining }; // called on continuous layouts to stop them before they finish -NullLayout.prototype.stop = function(){ +NullLayout.prototype.stop = function () { return this; // chaining }; module.exports = NullLayout; -},{"../../util":100}],55:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 104 */ +/***/ (function(module, exports, __webpack_require__) { -var util = _dereq_( '../../util' ); -var is = _dereq_( '../../is' ); +"use strict"; + + +var util = __webpack_require__(1); +var is = __webpack_require__(0); var defaults = { positions: undefined, // map of (node id) => (position obj); or function(node){ return somPos; } @@ -11637,59 +20310,69 @@ var defaults = { animate: false, // whether to transition the node positions animationDuration: 500, // duration of animation in ms if enabled animationEasing: undefined, // easing of animation if enabled + animateFilter: function animateFilter(node, i) { + return true; + }, // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts ready: undefined, // callback on layoutready - stop: undefined // callback on layoutstop + stop: undefined, // callback on layoutstop + transform: function transform(node, position) { + return position; + } // transform a given node position. Useful for changing flow direction in discrete layouts }; -function PresetLayout( options ){ - this.options = util.extend( {}, defaults, options ); +function PresetLayout(options) { + this.options = util.extend({}, defaults, options); } -PresetLayout.prototype.run = function(){ +PresetLayout.prototype.run = function () { var options = this.options; var eles = options.eles; var nodes = eles.nodes(); - var posIsFn = is.fn( options.positions ); + var posIsFn = is.fn(options.positions); - function getPosition( node ){ - if( options.positions == null ){ + function getPosition(node) { + if (options.positions == null) { return null; } - if( posIsFn ){ - return options.positions.apply( node, [ node ] ); + if (posIsFn) { + return options.positions(node); } - var pos = options.positions[ node._private.data.id ]; + var pos = options.positions[node._private.data.id]; - if( pos == null ){ + if (pos == null) { return null; } return pos; } - nodes.layoutPositions( this, options, function( i, node ){ - var position = getPosition( node ); + nodes.layoutPositions(this, options, function (node, i) { + var position = getPosition(node); - if( node.locked() || position == null ){ + if (node.locked() || position == null) { return false; } return position; - } ); + }); return this; // chaining }; module.exports = PresetLayout; -},{"../../is":83,"../../util":100}],56:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 105 */ +/***/ (function(module, exports, __webpack_require__) { -var util = _dereq_( '../../util' ); -var math = _dereq_( '../../math' ); +"use strict"; + + +var util = __webpack_require__(1); +var math = __webpack_require__(2); var defaults = { fit: true, // whether to fit to viewport @@ -11698,2438 +20381,161 @@ var defaults = { animate: false, // whether to transition the node positions animationDuration: 500, // duration of animation in ms if enabled animationEasing: undefined, // easing of animation if enabled + animateFilter: function animateFilter(node, i) { + return true; + }, // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts ready: undefined, // callback on layoutready - stop: undefined // callback on layoutstop + stop: undefined, // callback on layoutstop + transform: function transform(node, position) { + return position; + } // transform a given node position. Useful for changing flow direction in discrete layouts }; -function RandomLayout( options ){ - this.options = util.extend( {}, defaults, options ); +function RandomLayout(options) { + this.options = util.extend({}, defaults, options); } -RandomLayout.prototype.run = function(){ +RandomLayout.prototype.run = function () { var options = this.options; var cy = options.cy; var eles = options.eles; - var nodes = eles.nodes().not( ':parent' ); + var nodes = eles.nodes().not(':parent'); - var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : { + var bb = math.makeBoundingBox(options.boundingBox ? options.boundingBox : { x1: 0, y1: 0, w: cy.width(), h: cy.height() - } ); + }); - var getPos = function( i, node ){ + var getPos = function getPos(node, i) { return { - x: bb.x1 + Math.round( Math.random() * bb.w ), - y: bb.y1 + Math.round( Math.random() * bb.h ) + x: bb.x1 + Math.round(Math.random() * bb.w), + y: bb.y1 + Math.round(Math.random() * bb.h) }; }; - nodes.layoutPositions( this, options, getPos ); + nodes.layoutPositions(this, options, getPos); return this; // chaining }; module.exports = RandomLayout; -},{"../../math":85,"../../util":100}],57:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 106 */ +/***/ (function(module, exports, __webpack_require__) { -var math = _dereq_( '../../../math' ); -var is = _dereq_( '../../../is' ); -var util = _dereq_( '../../../util' ); +"use strict"; -var BRp = {}; -BRp.arrowShapeWidth = 0.3; +module.exports = [{ name: 'null', impl: __webpack_require__(107) }, { name: 'base', impl: __webpack_require__(108) }, { name: 'canvas', impl: __webpack_require__(124) }]; -BRp.registerArrowShapes = function(){ - var arrowShapes = this.arrowShapes = {}; - var renderer = this; +/***/ }), +/* 107 */ +/***/ (function(module, exports, __webpack_require__) { - // Contract for arrow shapes: - // 0, 0 is arrow tip - // (0, 1) is direction towards node - // (1, 0) is right - // - // functional api: - // collide: check x, y in shape - // roughCollide: called before collide, no false negatives - // draw: draw - // spacing: dist(arrowTip, nodeBoundary) - // gap: dist(edgeTip, nodeBoundary), edgeTip may != arrowTip +"use strict"; - var bbCollide = function( x, y, size, angle, translation, padding ){ - var x1 = translation.x - size / 2 - padding; - var x2 = translation.x + size / 2 + padding; - var y1 = translation.y - size / 2 - padding; - var y2 = translation.y + size / 2 + padding; - var inside = (x1 <= x && x <= x2) && (y1 <= y && y <= y2); - - return inside; - }; - - var transform = function( x, y, size, angle, translation ){ - var xRotated = x * Math.cos( angle ) - y * Math.sin( angle ); - var yRotated = x * Math.sin( angle ) + y * Math.cos( angle ); - - var xScaled = xRotated * size; - var yScaled = yRotated * size; - - var xTranslated = xScaled + translation.x; - var yTranslated = yScaled + translation.y; - - return { - x: xTranslated, - y: yTranslated - }; - }; - - var transformPoints = function( pts, size, angle, translation ){ - var retPts = []; - - for( var i = 0; i < pts.length; i += 2 ){ - var x = pts[ i ]; - var y = pts[ i + 1]; - - retPts.push( transform( x, y, size, angle, translation ) ); - } - - return retPts; - }; - - var pointsToArr = function( pts ){ - var ret = []; - - for( var i = 0; i < pts.length; i++ ){ - var p = pts[ i ]; - - ret.push( p.x, p.y ); - } - - return ret; - }; - - var defineArrowShape = function( name, defn ){ - if( is.string( defn ) ){ - defn = arrowShapes[ defn ]; - } - - arrowShapes[ name ] = util.extend( { - name: name, - - points: [ - -0.15, -0.3, - 0.15, -0.3, - 0.15, 0.3, - -0.15, 0.3 - ], - - collide: function( x, y, size, angle, translation, padding ){ - var points = pointsToArr( transformPoints( this.points, size + 2 * padding, angle, translation ) ); - var inside = math.pointInsidePolygonPoints( x, y, points ); - - return inside; - }, - - roughCollide: bbCollide, - - draw: function( context, size, angle, translation ){ - var points = transformPoints( this.points, size, angle, translation ); - - renderer.arrowShapeImpl( 'polygon' )( context, points ); - }, - - spacing: function( edge ){ - return 0; - }, - - gap: function( edge ){ - return edge.pstyle( 'width' ).pfValue * 2; - } - }, defn ); - }; - - defineArrowShape( 'none', { - collide: util.falsify, - - roughCollide: util.falsify, - - draw: util.noop, - - spacing: util.zeroify, - - gap: util.zeroify - } ); - - defineArrowShape( 'triangle', { - points: [ - -0.15, -0.3, - 0, 0, - 0.15, -0.3 - ] - } ); - - defineArrowShape( 'arrow', 'triangle' ); - - defineArrowShape( 'triangle-backcurve', { - points: arrowShapes[ 'triangle' ].points, - - controlPoint: [ 0, -0.15 ], - - roughCollide: bbCollide, - - draw: function( context, size, angle, translation ){ - var ptsTrans = transformPoints( this.points, size, angle, translation ); - var ctrlPt = this.controlPoint; - var ctrlPtTrans = transform( ctrlPt[0], ctrlPt[1], size, angle, translation ); - - renderer.arrowShapeImpl( this.name )( context, ptsTrans, ctrlPtTrans ); - }, - - gap: function( edge ){ - return edge.pstyle( 'width' ).pfValue; - } - } ); - - - defineArrowShape( 'triangle-tee', { - points: [ - -0.15, -0.3, - 0, 0, - 0.15, -0.3, - -0.15, -0.3 - ], - - pointsTee: [ - -0.15, -0.4, - -0.15, -0.5, - 0.15, -0.5, - 0.15, -0.4 - ], - - collide: function( x, y, size, angle, translation, padding ){ - var triPts = pointsToArr( transformPoints( this.points, size + 2 * padding, angle, translation ) ); - var teePts = pointsToArr( transformPoints( this.pointsTee, size + 2 * padding, angle, translation ) ); - - var inside = math.pointInsidePolygonPoints( x, y, triPts ) || math.pointInsidePolygonPoints( x, y, teePts ); - - return inside; - }, - - draw: function( context, size, angle, translation ){ - var triPts = transformPoints( this.points, size, angle, translation ); - var teePts = transformPoints( this.pointsTee, size, angle, translation ); - - renderer.arrowShapeImpl( this.name )( context, triPts, teePts ); - } - } ); - - defineArrowShape( 'vee', { - points: [ - -0.15, -0.3, - 0, 0, - 0.15, -0.3, - 0, -0.15 - ], - - gap: function( edge ){ - return edge.pstyle( 'width' ).pfValue; - } - } ); - - defineArrowShape( 'circle', { - radius: 0.15, - - collide: function( x, y, size, angle, translation, padding ){ - var t = translation; - var inside = ( Math.pow( t.x - x, 2 ) + Math.pow( t.y - y, 2 ) <= Math.pow( (size + 2 * padding) * this.radius, 2 ) ); - - return inside; - }, - - draw: function( context, size, angle, translation ){ - renderer.arrowShapeImpl( this.name )( context, translation.x, translation.y, this.radius * size ); - }, - - spacing: function( edge ){ - return renderer.getArrowWidth( edge.pstyle( 'width' ).pfValue ) - * this.radius; - } - } ); - - defineArrowShape( 'inhibitor', { - points: [ - -0.15, 0, - -0.15, -0.1, - 0.15, -0.1, - 0.15, 0 - ], - - spacing: function( edge ){ - return 1; - }, - - gap: function( edge ){ - return 1; - } - } ); - - defineArrowShape( 'tee', 'inhibitor' ); - - defineArrowShape( 'square', { - points: [ - -0.15, 0.00, - 0.15, 0.00, - 0.15, -0.3, - -0.15, -0.3 - ] - } ); - - defineArrowShape( 'diamond', { - points: [ - -0.15, -0.15, - 0, -0.3, - 0.15, -0.15, - 0, 0 - ], - - gap: function( edge ){ - return edge.pstyle( 'width' ).pfValue; - } - } ); - -}; - -module.exports = BRp; - -},{"../../../is":83,"../../../math":85,"../../../util":100}],58:[function(_dereq_,module,exports){ -'use strict'; - -var math = _dereq_( '../../../math' ); -var is = _dereq_( '../../../is' ); -var util = _dereq_( '../../../util' ); -var zIndexSort = _dereq_( '../../../collection/zsort' ); - -var BRp = {}; - -BRp.registerCalculationListeners = function(){ - var cy = this.cy; - var elesToUpdate = cy.collection(); - var r = this; - - var enqueue = function( eles, e ){ - elesToUpdate.merge( eles ); - - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[i]; - var _p = ele._private; - var rstyle = _p.rstyle; - - rstyle.clean = false; - _p.bbCache = null; - - var evts = rstyle.dirtyEvents = rstyle.dirtyEvents || { length: 0 }; - - if( !evts[ e.type ] ){ - evts[ e.type ] = true; - evts.length++; -// - // elesToUpdate.merge( ele ); - } - } - }; - - r.binder( cy ) - // nodes - - .on('position.* style.* free.*', 'node', function onDirtyModNode( e ){ - var node = e.cyTarget; - - enqueue( node, e ); - enqueue( node.connectedEdges(), e ); - - if( cy.hasCompoundNodes() ){ - var parents = node.parents(); - - enqueue( parents, e ); - enqueue( parents.connectedEdges(), e ); - } - }) - - .on('add.* background.*', 'node', function onDirtyAddNode( e ){ - var ele = e.cyTarget; - - enqueue( ele, e ); - }) - - // edges - - .on('add.* style.*', 'edge', function onDirtyEdge( e ){ - var edge = e.cyTarget; - - enqueue( edge, e ); - enqueue( edge.parallelEdges(), e ); - }) - - .on('remove.*', 'edge', function onDirtyRemoveEdge( e ){ - var edge = e.cyTarget; - var pEdges = edge.parallelEdges(); - - for( var i = 0; i < pEdges.length; i++ ){ - var pEdge = pEdges[i]; - - if( !pEdge.removed() ){ - enqueue( pEdge, e ); - } - } - }) - ; - - var updateEleCalcs = function( willDraw ){ - if( willDraw ){ - var fns = r.onUpdateEleCalcsFns; - - if( fns ){ for( var i = 0; i < fns.length; i++ ){ - var fn = fns[i]; - - fn( willDraw, elesToUpdate ); - } } - - r.recalculateRenderedStyle( elesToUpdate, false ); - - for( var i = 0; i < elesToUpdate.length; i++ ){ - elesToUpdate[i]._private.rstyle.dirtyEvents = null; - } - - elesToUpdate = cy.collection(); - } - }; - - r.beforeRender( updateEleCalcs, r.beforeRenderPriorities.eleCalcs ); -}; - -BRp.onUpdateEleCalcs = function( fn ){ - var fns = this.onUpdateEleCalcsFns = this.onUpdateEleCalcsFns || []; - - fns.push( fn ); -}; - -BRp.recalculateRenderedStyle = function( eles, useCache ){ - var edges = []; - var nodes = []; - - // use cache by default for perf - if( useCache === undefined ){ useCache = true; } - - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[ i ]; - var _p = ele._private; - var rstyle = _p.rstyle; - - // only update if dirty and in graph - if( (useCache && rstyle.clean) || ele.removed() ){ continue; } - - if( _p.group === 'nodes' ){ - var pos = _p.position; - - nodes.push( ele ); - - rstyle.nodeX = pos.x; - rstyle.nodeY = pos.y; - rstyle.nodeW = ele.pstyle( 'width' ).pfValue; - rstyle.nodeH = ele.pstyle( 'height' ).pfValue; - } else { // edges - - edges.push( ele ); - - } // if edges - - rstyle.clean = true; - // rstyle.dirtyEvents = null; - } - - this.recalculateEdgeProjections( edges ); - this.recalculateLabelProjections( nodes, edges ); - - // update edge data from projections - for( var i = 0; i < edges.length; i++ ){ - var ele = edges[ i ]; - var _p = ele._private; - var rstyle = _p.rstyle; - var rs = _p.rscratch; - - // update rstyle positions - rstyle.srcX = rs.arrowStartX; - rstyle.srcY = rs.arrowStartY; - rstyle.tgtX = rs.arrowEndX; - rstyle.tgtY = rs.arrowEndY; - rstyle.midX = rs.midX; - rstyle.midY = rs.midY; - rstyle.labelAngle = rs.labelAngle; - rstyle.sourceLabelAngle = rs.sourceLabelAngle; - rstyle.targetLabelAngle = rs.targetLabelAngle; - } -}; - -// Project mouse -BRp.projectIntoViewport = function( clientX, clientY ){ - var offsets = this.findContainerClientCoords(); - var offsetLeft = offsets[0]; - var offsetTop = offsets[1]; - - var x = clientX - offsetLeft; - var y = clientY - offsetTop; - - x -= this.cy.pan().x; y -= this.cy.pan().y; x /= this.cy.zoom(); y /= this.cy.zoom(); - return [ x, y ]; -}; - -BRp.findContainerClientCoords = function(){ - var container = this.container; - - var bb = this.containerBB = this.containerBB || container.getBoundingClientRect(); - - return [ bb.left, bb.top, bb.right - bb.left, bb.bottom - bb.top ]; -}; - -BRp.invalidateContainerClientCoordsCache = function(){ - this.containerBB = null; -}; - -BRp.findNearestElement = function( x, y, visibleElementsOnly, isTouch ){ - return this.findNearestElements( x, y, visibleElementsOnly, isTouch )[0]; -}; - -BRp.findNearestElements = function( x, y, visibleElementsOnly, isTouch ){ - var self = this; - var r = this; - var eles = r.getCachedZSortedEles(); - var near = []; // 1 node max, 1 edge max - var zoom = r.cy.zoom(); - var hasCompounds = r.cy.hasCompoundNodes(); - var edgeThreshold = (isTouch ? 24 : 8) / zoom; - var nodeThreshold = (isTouch ? 8 : 2) / zoom; - var labelThreshold = (isTouch ? 8 : 2) / zoom; - var minSqDist = Infinity; - var nearEdge; - var nearNode; - - function addEle( ele, sqDist ){ - if( ele.isNode() ){ - if( nearNode ){ - return; // can't replace node - } else { - nearNode = ele; - near.push( ele ); - } - } - - if( ele.isEdge() && ( sqDist == null || sqDist < minSqDist ) ){ - if( nearEdge ){ // then replace existing edge - // can replace only if same z-index - if( nearEdge.pstyle( 'z-index' ).value === ele.pstyle('z-index').value ){ - for( var i = 0; i < near.length; i++ ){ - if( near[i].isEdge() ){ - near[i] = ele; - nearEdge = ele; - minSqDist = sqDist != null ? sqDist : minSqDist; - break; - } - } - } - } else { - near.push( ele ); - nearEdge = ele; - minSqDist = sqDist != null ? sqDist : minSqDist; - } - } - } - - function checkNode( node ){ - var _p = node._private; - - if( node.pstyle( 'events' ).strValue === 'no' ){ return; } - - var width = node.outerWidth() + 2 * nodeThreshold; - var height = node.outerHeight() + 2 * nodeThreshold; - var hw = width / 2; - var hh = height / 2; - var pos = _p.position; - - if( - pos.x - hw <= x && x <= pos.x + hw // bb check x - && - pos.y - hh <= y && y <= pos.y + hh // bb check y - ){ - var visible = !visibleElementsOnly || ( node.visible() && !node.transparent() ); - - // exit early if invisible edge and must be visible - if( visibleElementsOnly && !visible ){ - return; - } - - var shape = r.nodeShapes[ self.getNodeShape( node ) ]; - - if( - shape.checkPoint( x, y, 0, width, height, pos.x, pos.y ) - ){ - addEle( node, 0 ); - } - - } - } - - function checkEdge( edge ){ - var _p = edge._private; - - if( edge.pstyle('events').strValue === 'no' ){ return; } - - var rs = _p.rscratch; - var width = edge.pstyle( 'width' ).pfValue / 2 + edgeThreshold; // more like a distance radius from centre - var widthSq = width * width; - var width2 = width * 2; - var src = _p.source; - var tgt = _p.target; - var inEdgeBB = false; - var sqDist; - - // exit early if invisible edge and must be visible - var passedVisibilityCheck; - var passesVisibilityCheck = function(){ - if( passedVisibilityCheck !== undefined ){ - return passedVisibilityCheck; - } - - if( !visibleElementsOnly ){ - passedVisibilityCheck = true; - return true; - } - - var visible = edge.visible() && !edge.transparent(); - if( visible ){ - passedVisibilityCheck = true; - return true; - } - - passedVisibilityCheck = false; - return false; - }; - - if( rs.edgeType === 'segments' || rs.edgeType === 'straight' || rs.edgeType === 'haystack' ){ - var pts = rs.allpts; - - for( var i = 0; i + 3 < pts.length; i += 2 ){ - if( - (inEdgeBB = math.inLineVicinity( x, y, pts[ i ], pts[ i + 1], pts[ i + 2], pts[ i + 3], width2 )) - && passesVisibilityCheck() && - widthSq > ( sqDist = math.sqdistToFiniteLine( x, y, pts[ i ], pts[ i + 1], pts[ i + 2], pts[ i + 3] ) ) - ){ - addEle( edge, sqDist ); - } - } - - } else if( rs.edgeType === 'bezier' || rs.edgeType === 'multibezier' || rs.edgeType === 'self' || rs.edgeType === 'compound' ){ - var pts = rs.allpts; - for( var i = 0; i + 5 < rs.allpts.length; i += 4 ){ - if( - (inEdgeBB = math.inBezierVicinity( x, y, pts[ i ], pts[ i + 1], pts[ i + 2], pts[ i + 3], pts[ i + 4], pts[ i + 5], width2 )) - && passesVisibilityCheck() && - (widthSq > (sqDist = math.sqdistToQuadraticBezier( x, y, pts[ i ], pts[ i + 1], pts[ i + 2], pts[ i + 3], pts[ i + 4], pts[ i + 5] )) ) - ){ - addEle( edge, sqDist ); - } - } - } - - // if we're close to the edge but didn't hit it, maybe we hit its arrows - if( inEdgeBB && passesVisibilityCheck() ){ - var src = src || _p.source; - var tgt = tgt || _p.target; - - var eWidth = edge.pstyle( 'width' ).pfValue; - var arSize = self.getArrowWidth( eWidth ); - - var arrows = [ - { name: 'source', x: rs.arrowStartX, y: rs.arrowStartY, angle: rs.srcArrowAngle }, - { name: 'target', x: rs.arrowEndX, y: rs.arrowEndY, angle: rs.tgtArrowAngle }, - { name: 'mid-source', x: rs.midX, y: rs.midY, angle: rs.midsrcArrowAngle }, - { name: 'mid-target', x: rs.midX, y: rs.midY, angle: rs.midtgtArrowAngle } - ]; - - for( var i = 0; i < arrows.length; i++ ){ - var ar = arrows[ i ]; - var shape = r.arrowShapes[ edge.pstyle( ar.name + '-arrow-shape' ).value ]; - - if( - shape.roughCollide( x, y, arSize, ar.angle, { x: ar.x, y: ar.y }, edgeThreshold ) - && - shape.collide( x, y, arSize, ar.angle, { x: ar.x, y: ar.y }, edgeThreshold ) - ){ - addEle( edge ); - break; - } - } - } - - // for compound graphs, hitting edge may actually want a connected node instead (b/c edge may have greater z-index precedence) - if( hasCompounds && near.length > 0 ){ - checkNode( src ); - checkNode( tgt ); - } - } - - function preprop( obj, name, pre ){ - return util.getPrefixedProperty( obj, name, pre ); - } - - function checkLabel( ele, prefix ){ - var _p = ele._private; - var th = labelThreshold; - - var prefixDash; - if( prefix ){ - prefixDash = prefix + '-'; - } else { - prefixDash = ''; - } - - if( ele.pstyle( 'text-events' ).strValue === 'no' ){ return; } - - var rotation = ele.pstyle( prefixDash + 'text-rotation' ); - - // adjust bb w/ angle - if( rotation.strValue === 'autorotate' || !!rotation.pfValue ){ - - var rstyle = _p.rstyle; - var bw = ele.pstyle('text-border-width').pfValue; - var lw = preprop( rstyle, 'labelWidth', prefix ) + bw/2 + 2*th; - var lh = preprop( rstyle, 'labelHeight', prefix ) + bw/2 + 2*th; - var lx = preprop( rstyle, 'labelX', prefix ); - var ly = preprop( rstyle, 'labelY', prefix ); - - var theta = preprop( _p.rscratch, 'labelAngle', prefix ); - var cos = Math.cos( theta ); - var sin = Math.sin( theta ); - - var rotate = function( x, y ){ - x = x - lx; - y = y - ly; - - return { - x: x * cos - y * sin + lx, - y: x * sin + y * cos + ly - }; - }; - - var lx1 = lx - lw / 2; - var lx2 = lx + lw / 2; - var ly1 = ly - lh / 2; - var ly2 = ly + lh / 2; - - var px1y1 = rotate( lx1, ly1 ); - var px1y2 = rotate( lx1, ly2 ); - var px2y1 = rotate( lx2, ly1 ); - var px2y2 = rotate( lx2, ly2 ); - - var points = [ - px1y1.x, px1y1.y, - px2y1.x, px2y1.y, - px2y2.x, px2y2.y, - px1y2.x, px1y2.y - ]; - - if( math.pointInsidePolygonPoints( x, y, points ) ){ - addEle( ele ); - } - - } else { - var bb = ele.boundingBox( { - includeLabels: true, - includeNodes: false, - includeEdges: false - } ); - - // adjust bb w/ threshold - bb.x1 -= th; - bb.y1 -= th; - bb.x2 += th; - bb.y2 += th; - bb.w = bb.x2 - bb.x1; - bb.h = bb.y2 - bb.y1; - - if( math.inBoundingBox( bb, x, y ) ){ - addEle( ele ); - } - } - - } - - for( var i = eles.length - 1; i >= 0; i-- ){ // reverse order for precedence - var ele = eles[ i ]; - - if( ele.isNode() ){ - checkNode( ele ); - - checkLabel( ele ); - - } else { // then edge - checkEdge( ele ); - - checkLabel( ele ); - checkLabel( ele, 'source' ); - checkLabel( ele, 'target' ); - } - } - - return near; -}; - -// 'Give me everything from this box' -BRp.getAllInBox = function( x1, y1, x2, y2 ){ - var eles = this.getCachedZSortedEles(); - var nodes = eles.nodes; - var edges = eles.edges; - var box = []; - - var x1c = Math.min( x1, x2 ); - var x2c = Math.max( x1, x2 ); - var y1c = Math.min( y1, y2 ); - var y2c = Math.max( y1, y2 ); - - x1 = x1c; - x2 = x2c; - y1 = y1c; - y2 = y2c; - - var boxBb = math.makeBoundingBox( { - x1: x1, y1: y1, - x2: x2, y2: y2 - } ); - - for( var i = 0; i < nodes.length; i++ ){ - var node = nodes[ i ]; - var nodeBb = node.boundingBox( { - includeNodes: true, - includeEdges: false, - includeLabels: false, - includeShadows: false - } ); - - if( math.boundingBoxesIntersect( boxBb, nodeBb ) ){ - box.push( nodes[ i ] ); - } - } - - for( var e = 0; e < edges.length; e++ ){ - var edge = edges[ e ]; - var _p = edge._private; - var rs = _p.rscratch; - - if( rs.startX != null && rs.startY != null && !math.inBoundingBox( boxBb, rs.startX, rs.startY ) ){ continue; } - if( rs.endX != null && rs.endY != null && !math.inBoundingBox( boxBb, rs.endX, rs.endY ) ){ continue; } - - if( rs.edgeType === 'bezier' || rs.edgeType === 'multibezier' || rs.edgeType === 'self' || rs.edgeType === 'compound' || rs.edgeType === 'segments' || rs.edgeType === 'haystack' ){ - - var pts = _p.rstyle.bezierPts || _p.rstyle.linePts || _p.rstyle.haystackPts; - var allInside = true; - - for( var i = 0; i < pts.length; i++ ){ - if( !math.pointInBoundingBox( boxBb, pts[ i ] ) ){ - allInside = false; - break; - } - } - - if( allInside ){ - box.push( edge ); - } - - } else if( rs.edgeType === 'haystack' || rs.edgeType === 'straight' ){ - box.push( edge ); - } - - } - - return box; -}; - - -/** - * Returns the shape of the given node. If the height or width of the given node - * is set to auto, the node is considered to be a compound. - * - * @param node a node - * @return {String} shape of the node - */ -BRp.getNodeShape = function( node ){ - var r = this; - var shape = node.pstyle( 'shape' ).value; - - if( node.isParent() ){ - if( shape === 'rectangle' || shape === 'roundrectangle' ){ - return shape; - } else { - return 'rectangle'; - } - } - - if( shape === 'polygon' ){ - var points = node.pstyle( 'shape-polygon-points' ).value; - - return r.nodeShapes.makePolygon( points ).name; - } - - return shape; -}; - -BRp.updateCachedZSortedEles = function(){ - this.getCachedZSortedEles( true ); -}; - -BRp.updateCachedGrabbedEles = function(){ - var eles = this.cachedZSortedEles; - - eles.drag = []; - eles.nondrag = []; - - var grabTarget; - - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[i]; - var rs = ele._private.rscratch; - - if( rs.isGrabTarget && !ele.isParent() ){ - grabTarget = ele; - } else if( rs.inDragLayer ){ - eles.drag.push( ele ); - } else { - eles.nondrag.push( ele ); - } - } - - // put the grab target node last so it's on top of its neighbourhood - if( grabTarget ){ - eles.drag.push( grabTarget ); - } -}; - -BRp.getCachedZSortedEles = function( forceRecalc ){ - if( forceRecalc || !this.cachedZSortedEles ){ - //console.time('cachezorder') - - var cyEles = this.cy.mutableElements(); - var eles = []; - - eles.nodes = []; - eles.edges = []; - - for( var i = 0; i < cyEles.length; i++ ){ - var ele = cyEles[i]; - - if( ele.animated() || (ele.visible() && !ele.transparent()) ){ - eles.push( ele ); - - if( ele.isNode() ){ - eles.nodes.push( ele ); - } else { - eles.edges.push( ele ); - } - } - } - - eles.sort( zIndexSort ); - - this.cachedZSortedEles = eles; - - this.updateCachedGrabbedEles(); - - //console.log('make cache') - - //console.timeEnd('cachezorder') - } else { - eles = this.cachedZSortedEles; - //console.log('read cache') - } - - return eles; -}; - -function pushBezierPts( r, edge, pts ){ - var qbezierAt = function( p1, p2, p3, t ){ return math.qbezierAt( p1, p2, p3, t ); }; - var _p = edge._private; - var bpts = _p.rstyle.bezierPts; - - for( var i = 0; i < r.bezierProjPcts.length; i++ ){ - var p = r.bezierProjPcts[i]; - - bpts.push( { - x: qbezierAt( pts[0], pts[2], pts[4], p ), - y: qbezierAt( pts[1], pts[3], pts[5], p ) - } ); - } +function NullRenderer(options) { + this.options = options; + this.notifications = 0; // for testing } -BRp.projectLines = function( edge ){ - var _p = edge._private; - var rs = _p.rscratch; - var et = rs.edgeType; +var noop = function noop() {}; - // clear the cached points state - _p.rstyle.bezierPts = null; - _p.rstyle.linePts = null; - _p.rstyle.haystackPts = null; - - if( et === 'multibezier' || et === 'bezier' || et === 'self' || et === 'compound' ){ - var bpts = _p.rstyle.bezierPts = []; // jshint ignore:line - - for( var i = 0; i + 5 < rs.allpts.length; i += 4 ){ - pushBezierPts( this, edge, rs.allpts.slice( i, i + 6 ) ); - } - } else if( et === 'segments' ){ - var lpts = _p.rstyle.linePts = []; - - for( var i = 0; i + 1 < rs.allpts.length; i += 2 ){ - lpts.push( { - x: rs.allpts[ i ], - y: rs.allpts[ i + 1] - } ); - } - } else if( et === 'haystack' ){ - var hpts = rs.haystackPts; - - _p.rstyle.haystackPts = [ - { x: hpts[0], y: hpts[1] }, - { x: hpts[2], y: hpts[3] } - ]; - } - - _p.rstyle.arrowWidth = this.getArrowWidth( edge.pstyle('width').pfValue ) * this.arrowShapeWidth; +NullRenderer.prototype = { + recalculateRenderedStyle: noop, + notify: function notify() { + this.notifications++; + }, + init: noop }; -BRp.projectBezier = BRp.projectLines; +module.exports = NullRenderer; -BRp.recalculateNodeLabelProjection = function( node ){ - var content = node.pstyle( 'label' ).strValue; +/***/ }), +/* 108 */ +/***/ (function(module, exports, __webpack_require__) { - if( is.emptyString(content) ){ return; } +"use strict"; - var textX, textY; - var _p = node._private; - var nodeWidth = node.width(); - var nodeHeight = node.height(); - var paddingLeft = node.pstyle('padding-left').pfValue; - var paddingRight = node.pstyle('padding-right').pfValue; - var paddingTop = node.pstyle('padding-top').pfValue; - var paddingBottom = node.pstyle('padding-bottom').pfValue; - var nodePos = _p.position; - var textHalign = node.pstyle( 'text-halign' ).strValue; - var textValign = node.pstyle( 'text-valign' ).strValue; - var rs = _p.rscratch; - var rstyle = _p.rstyle; - switch( textHalign ){ - case 'left': - textX = nodePos.x - nodeWidth / 2 - paddingLeft; - break; +var is = __webpack_require__(0); +var util = __webpack_require__(1); +var window = __webpack_require__(3); - case 'right': - textX = nodePos.x + nodeWidth / 2 + paddingRight; - break; - - default: // e.g. center - textX = nodePos.x; - } - - switch( textValign ){ - case 'top': - textY = nodePos.y - nodeHeight / 2 - paddingTop; - break; - - case 'bottom': - textY = nodePos.y + nodeHeight / 2 + paddingBottom; - break; - - default: // e.g. middle - textY = nodePos.y; - } - - rs.labelX = textX; - rs.labelY = textY; - rstyle.labelX = textX; - rstyle.labelY = textY; - - this.applyLabelDimensions( node ); +var BaseRenderer = function BaseRenderer(options) { + this.init(options); }; - -BRp.recalculateEdgeLabelProjections = function( edge ){ - var p; - var _p = edge._private; - var rs = _p.rscratch; - var r = this; - var content = { - mid: edge.pstyle('label').strValue, - source: edge.pstyle('source-label').strValue, - target: edge.pstyle('target-label').strValue - }; - - if( content.mid || content.source || content.target ){ - // then we have to calculate... - } else { - return; // no labels => no calcs - } - - // add center point to style so bounding box calculations can use it - // - p = { - x: rs.midX, - y: rs.midY - }; - - var setRs = function( propName, prefix, value ){ - util.setPrefixedProperty( _p.rscratch, propName, prefix, value ); - util.setPrefixedProperty( _p.rstyle, propName, prefix, value ); - }; - - setRs( 'labelX', null, p.x ); - setRs( 'labelY', null, p.y ); - - var createControlPointInfo = function(){ - if( createControlPointInfo.cache ){ return createControlPointInfo.cache; } // use cache so only 1x per edge - - var ctrlpts = []; - - // store each ctrlpt info init - for( var i = 0; i + 5 < rs.allpts.length; i += 4 ){ - var p0 = { x: rs.allpts[i], y: rs.allpts[i+1] }; - var p1 = { x: rs.allpts[i+2], y: rs.allpts[i+3] }; // ctrlpt - var p2 = { x: rs.allpts[i+4], y: rs.allpts[i+5] }; - - ctrlpts.push({ - p0: p0, - p1: p1, - p2: p2, - startDist: 0, - length: 0, - segments: [] - }); - } - - var bpts = _p.rstyle.bezierPts; - var nProjs = r.bezierProjPcts.length; - - function addSegment( cp, p0, p1, t0, t1 ){ - var length = math.dist( p0, p1 ); - var prevSegment = cp.segments[ cp.segments.length - 1 ]; - var segment = { - p0: p0, - p1: p1, - t0: t0, - t1: t1, - startDist: prevSegment ? prevSegment.startDist + prevSegment.length : 0, - length: length - }; - - cp.segments.push( segment ); - - cp.length += length; - } - - // update each ctrlpt with segment info - for( var i = 0; i < ctrlpts.length; i++ ){ - var cp = ctrlpts[i]; - var prevCp = ctrlpts[i - 1]; - - if( prevCp ){ - cp.startDist = prevCp.startDist + prevCp.length; - } - - addSegment( - cp, - cp.p0, bpts[ i * nProjs ], - 0, r.bezierProjPcts[ 0 ] - ); // first - - for( var j = 0; j < nProjs - 1; j++ ){ - addSegment( - cp, - bpts[ i * nProjs + j ], bpts[ i * nProjs + j + 1 ], - r.bezierProjPcts[ j ], r.bezierProjPcts[ j + 1 ] - ); - } - - addSegment( - cp, - bpts[ i * nProjs + nProjs - 1 ], cp.p2, - r.bezierProjPcts[ nProjs - 1 ], 1 - ); // last - } - - return ( createControlPointInfo.cache = ctrlpts ); - }; - - var calculateEndProjection = function( prefix ){ - var angle; - var isSrc = prefix === 'source'; - - if( !content[ prefix ] ){ return; } - - var offset = edge.pstyle(prefix+'-text-offset').pfValue; - - var lineAngle = function( p0, p1 ){ - var dx = p1.x - p0.x; - var dy = p1.y - p0.y; - - return Math.atan( dy / dx ); - }; - - var bezierAngle = function( p0, p1, p2, t ){ - var t0 = math.bound( 0, t - 0.001, 1 ); - var t1 = math.bound( 0, t + 0.001, 1 ); - - var lp0 = math.qbezierPtAt( p0, p1, p2, t0 ); - var lp1 = math.qbezierPtAt( p0, p1, p2, t1 ); - - return lineAngle( lp0, lp1 ); - }; - - switch( rs.edgeType ){ - case 'self': - case 'compound': - case 'bezier': - case 'multibezier': - var cps = createControlPointInfo(); - var selected; - var startDist = 0; - var totalDist = 0; - - // find the segment we're on - for( var i = 0; i < cps.length; i++ ){ - var cp = cps[ isSrc ? i : cps.length - 1 - i ]; - - for( var j = 0; j < cp.segments.length; j++ ){ - var seg = cp.segments[ isSrc ? j : cp.segments.length - 1 - j ]; - var lastSeg = i === cps.length - 1 && j === cp.segments.length - 1; - - startDist = totalDist; - totalDist += seg.length; - - if( totalDist >= offset || lastSeg ){ - selected = { cp: cp, segment: seg }; - break; - } - } - - if( selected ){ break; } - } - - var cp = selected.cp; - var seg = selected.segment; - var tSegment = ( offset - startDist ) / ( seg.length ); - var segDt = seg.t1 - seg.t0; - var t = isSrc ? seg.t0 + segDt * tSegment : seg.t1 - segDt * tSegment; - - t = math.bound( 0, t, 1 ); - p = math.qbezierPtAt( cp.p0, cp.p1, cp.p2, t ); - angle = bezierAngle( cp.p0, cp.p1, cp.p2, t, p ); - - break; - - case 'straight': - case 'segments': - case 'haystack': - var d = 0, di, d0; - var p0, p1; - var l = rs.allpts.length; - - for( var i = 0; i + 3 < l; i += 2 ){ - if( isSrc ){ - p0 = { x: rs.allpts[i], y: rs.allpts[i+1] }; - p1 = { x: rs.allpts[i+2], y: rs.allpts[i+3] }; - } else { - p0 = { x: rs.allpts[l-2-i], y: rs.allpts[l-1-i] }; - p1 = { x: rs.allpts[l-4-i], y: rs.allpts[l-3-i] }; - } - - di = math.dist( p0, p1 ); - d0 = d; - d += di; - - if( d >= offset ){ break; } - } - - var pD = offset - d0; - var t = pD / di; - - t = math.bound( 0, t, 1 ); - p = math.lineAt( p0, p1, t ); - angle = lineAngle( p0, p1 ); - - break; - } - - setRs( 'labelX', prefix, p.x ); - setRs( 'labelY', prefix, p.y ); - setRs( 'labelAutoAngle', prefix, angle ); - }; - - calculateEndProjection( 'source' ); - calculateEndProjection( 'target' ); - - this.applyLabelDimensions( edge ); -}; - -BRp.applyLabelDimensions = function( ele ){ - this.applyPrefixedLabelDimensions( ele ); - - if( ele.isEdge() ){ - this.applyPrefixedLabelDimensions( ele, 'source' ); - this.applyPrefixedLabelDimensions( ele, 'target' ); - } -}; - -BRp.applyPrefixedLabelDimensions = function( ele, prefix ){ - var _p = ele._private; - - var text = this.getLabelText( ele, prefix ); - var labelDims = this.calculateLabelDimensions( ele, text ); - - util.setPrefixedProperty( _p.rstyle, 'labelWidth', prefix, labelDims.width ); - util.setPrefixedProperty( _p.rscratch, 'labelWidth', prefix, labelDims.width ); - - util.setPrefixedProperty( _p.rstyle, 'labelHeight', prefix, labelDims.height ); - util.setPrefixedProperty( _p.rscratch, 'labelHeight', prefix, labelDims.height ); -}; - -BRp.getLabelText = function( ele, prefix ){ - var _p = ele._private; - var pfd = prefix ? prefix + '-' : ''; - var text = ele.pstyle( pfd + 'label' ).strValue; - var textTransform = ele.pstyle( 'text-transform' ).value; - var rscratch = function( propName, value ){ - if( value ){ - util.setPrefixedProperty( _p.rscratch, propName, prefix, value ); - return value; - } else { - return util.getPrefixedProperty( _p.rscratch, propName, prefix ); - } - }; - - if( textTransform == 'none' ){ - // passthrough - } else if( textTransform == 'uppercase' ){ - text = text.toUpperCase(); - } else if( textTransform == 'lowercase' ){ - text = text.toLowerCase(); - } - - if( ele.pstyle( 'text-wrap' ).value === 'wrap' ){ - //console.log('wrap'); - - var labelKey = rscratch( 'labelKey' ); - - // save recalc if the label is the same as before - if( labelKey && rscratch( 'labelWrapKey' ) === labelKey ){ - // console.log('wrap cache hit'); - return rscratch( 'labelWrapCachedText' ); - } - // console.log('wrap cache miss'); - - var lines = text.split( '\n' ); - var maxW = ele.pstyle( 'text-max-width' ).pfValue; - var wrappedLines = []; - - for( var l = 0; l < lines.length; l++ ){ - var line = lines[ l ]; - var lineDims = this.calculateLabelDimensions( ele, line, 'line=' + line ); - var lineW = lineDims.width; - - if( lineW > maxW ){ // line is too long - var words = line.split( /\s+/ ); // NB: assume collapsed whitespace into single space - var subline = ''; - - for( var w = 0; w < words.length; w++ ){ - var word = words[ w ]; - var testLine = subline.length === 0 ? word : subline + ' ' + word; - var testDims = this.calculateLabelDimensions( ele, testLine, 'testLine=' + testLine ); - var testW = testDims.width; - - if( testW <= maxW ){ // word fits on current line - subline += word + ' '; - } else { // word starts new line - wrappedLines.push( subline ); - subline = word + ' '; - } - } - - // if there's remaining text, put it in a wrapped line - if( !subline.match( /^\s+$/ ) ){ - wrappedLines.push( subline ); - } - } else { // line is already short enough - wrappedLines.push( line ); - } - } // for - - rscratch( 'labelWrapCachedLines', wrappedLines ); - text = rscratch( 'labelWrapCachedText', wrappedLines.join( '\n' ) ); - rscratch( 'labelWrapKey', labelKey ); - - // console.log(text) - } // if wrap - - return text; -}; - -BRp.calculateLabelDimensions = function( ele, text, extraKey ){ - var r = this; - - var cacheKey = ele._private.labelStyleKey + '$@$' + text; - - if( extraKey ){ - cacheKey += '$@$' + extraKey; - } - - var cache = r.labelDimCache || (r.labelDimCache = {}); - - if( cache[ cacheKey ] ){ - return cache[ cacheKey ]; - } - - var sizeMult = 1; // increase the scale to increase accuracy w.r.t. zoomed text - var fStyle = ele.pstyle( 'font-style' ).strValue; - var size = ( sizeMult * ele.pstyle( 'font-size' ).pfValue ) + 'px'; - var family = ele.pstyle( 'font-family' ).strValue; - var weight = ele.pstyle( 'font-weight' ).strValue; - - var div = this.labelCalcDiv; - - if( !div ){ - div = this.labelCalcDiv = document.createElement( 'div' ); // eslint-disable-line no-undef - document.body.appendChild( div ); // eslint-disable-line no-undef - } - - var ds = div.style; - - // from ele style - ds.fontFamily = family; - ds.fontStyle = fStyle; - ds.fontSize = size; - ds.fontWeight = weight; - - // forced style - ds.position = 'absolute'; - ds.left = '-9999px'; - ds.top = '-9999px'; - ds.zIndex = '-1'; - ds.visibility = 'hidden'; - ds.pointerEvents = 'none'; - ds.padding = '0'; - ds.lineHeight = '1'; - - if( ele.pstyle( 'text-wrap' ).value === 'wrap' ){ - ds.whiteSpace = 'pre'; // so newlines are taken into account - } else { - ds.whiteSpace = 'normal'; - } - - // put label content in div - div.textContent = text; - - cache[ cacheKey ] = { - width: Math.ceil( div.clientWidth / sizeMult ), - height: Math.ceil( div.clientHeight / sizeMult ) - }; - - return cache[ cacheKey ]; -}; - -BRp.recalculateLabelProjections = function( nodes, edges ){ - for( var i = 0; i < nodes.length; i++ ){ - this.recalculateNodeLabelProjection( nodes[ i ] ); - } - - for( var i = 0; i < edges.length; i++ ){ - this.recalculateEdgeLabelProjections( edges[ i ] ); - } -}; - -BRp.recalculateEdgeProjections = function( edges ){ - this.findEdgeControlPoints( edges ); -}; - - -// Find edge control points -BRp.findEdgeControlPoints = function( edges ){ - if( !edges || edges.length === 0 ){ return; } - - var r = this; - var cy = r.cy; - var hasCompounds = cy.hasCompoundNodes(); - var hashTable = {}; - var pairIds = []; - var haystackEdges = []; - - // create a table of edge (src, tgt) => list of edges between them - var pairId; - for( var i = 0; i < edges.length; i++ ){ - var edge = edges[ i ]; - var _p = edge._private; - var data = _p.data; - var curveStyle = edge.pstyle( 'curve-style' ).value; - var edgeIsUnbundled = curveStyle === 'unbundled-bezier' || curveStyle === 'segments'; - - // ignore edges who are not to be displayed - // they shouldn't take up space - if( edge.pstyle( 'display').value === 'none' ){ - continue; - } - - if( curveStyle === 'haystack' ){ - haystackEdges.push( edge ); - continue; - } - - var srcId = data.source; - var tgtId = data.target; - - pairId = srcId > tgtId ? - tgtId + '$-$' + srcId : - srcId + '$-$' + tgtId ; - - if( edgeIsUnbundled ){ - pairId = 'unbundled' + '$-$' + data.id; - } - - if( hashTable[ pairId ] == null ){ - hashTable[ pairId ] = []; - pairIds.push( pairId ); - } - - hashTable[ pairId ].push( edge ); - - if( edgeIsUnbundled ){ - hashTable[ pairId ].hasUnbundled = true; - } - } - - var src, tgt, src_p, tgt_p, srcPos, tgtPos, srcW, srcH, tgtW, tgtH, srcShape, tgtShape; - var vectorNormInverse; - var badBezier; - - // for each pair (src, tgt), create the ctrl pts - // Nested for loop is OK; total number of iterations for both loops = edgeCount - for( var p = 0; p < pairIds.length; p++ ){ - pairId = pairIds[ p ]; - var pairEdges = hashTable[ pairId ]; - - // for each pair id, the edges should be sorted by index - pairEdges.sort( function( edge1, edge2 ){ - return edge1.poolIndex() - edge2.poolIndex(); - } ); - - src = pairEdges[0]._private.source; - tgt = pairEdges[0]._private.target; - - // make sure src/tgt distinction is consistent for bundled edges - if( !pairEdges.hasUnbundled && src.id() > tgt.id() ){ - var temp = src; - src = tgt; - tgt = temp; - } - - src_p = src._private; - tgt_p = tgt._private; - - srcPos = src_p.position; - tgtPos = tgt_p.position; - - srcW = src.outerWidth(); - srcH = src.outerHeight(); - - tgtW = tgt.outerWidth(); - tgtH = tgt.outerHeight(); - - srcShape = r.nodeShapes[ this.getNodeShape( src ) ]; - tgtShape = r.nodeShapes[ this.getNodeShape( tgt ) ]; - - badBezier = false; - - - if( (pairEdges.length > 1 && src !== tgt) || pairEdges.hasUnbundled ){ - - // pt outside src shape to calc distance/displacement from src to tgt - var srcOutside = srcShape.intersectLine( - srcPos.x, - srcPos.y, - srcW, - srcH, - tgtPos.x, - tgtPos.y, - 0 - ); - - // pt outside tgt shape to calc distance/displacement from src to tgt - var tgtOutside = tgtShape.intersectLine( - tgtPos.x, - tgtPos.y, - tgtW, - tgtH, - srcPos.x, - srcPos.y, - 0 - ); - - var midptSrcPts = { - x1: srcOutside[0], - x2: tgtOutside[0], - y1: srcOutside[1], - y2: tgtOutside[1] - }; - - var posPts = { - x1: srcPos.x, - x2: tgtPos.x, - y1: srcPos.y, - y2: tgtPos.y - }; - - var dy = ( tgtOutside[1] - srcOutside[1] ); - var dx = ( tgtOutside[0] - srcOutside[0] ); - var l = Math.sqrt( dx * dx + dy * dy ); - - var vector = { - x: dx, - y: dy - }; - - var vectorNorm = { - x: vector.x / l, - y: vector.y / l - }; - vectorNormInverse = { - x: -vectorNorm.y, - y: vectorNorm.x - }; - - - // if node shapes overlap, then no ctrl pts to draw - if( - tgtShape.checkPoint( srcOutside[0], srcOutside[1], 0, tgtW, tgtH, tgtPos.x, tgtPos.y ) && - srcShape.checkPoint( tgtOutside[0], tgtOutside[1], 0, srcW, srcH, srcPos.x, srcPos.y ) - ){ - vectorNormInverse = {}; - badBezier = true; - } - - } - - var edge; - var edge_p; - var rs; - - for( var i = 0; i < pairEdges.length; i++ ){ - edge = pairEdges[ i ]; - edge_p = edge._private; - rs = edge_p.rscratch; - - var edgeIndex1 = rs.lastEdgeIndex; - var edgeIndex2 = i; - - var numEdges1 = rs.lastNumEdges; - var numEdges2 = pairEdges.length; - - var curveStyle = edge.pstyle( 'curve-style' ).value; - var ctrlptDists = edge.pstyle( 'control-point-distances' ); - var ctrlptWs = edge.pstyle( 'control-point-weights' ); - var bezierN = ctrlptDists && ctrlptWs ? Math.min( ctrlptDists.value.length, ctrlptWs.value.length ) : 1; - var stepSize = edge.pstyle( 'control-point-step-size' ).pfValue; - var ctrlptDist = ctrlptDists ? ctrlptDists.pfValue[0] : undefined; - var ctrlptWeight = ctrlptWs.value[0]; - var edgeIsUnbundled = curveStyle === 'unbundled-bezier' || curveStyle === 'segments'; - - var srcX1 = rs.lastSrcCtlPtX; - var srcX2 = srcPos.x; - var srcY1 = rs.lastSrcCtlPtY; - var srcY2 = srcPos.y; - var srcW1 = rs.lastSrcCtlPtW; - var srcW2 = src.outerWidth(); - var srcH1 = rs.lastSrcCtlPtH; - var srcH2 = src.outerHeight(); - - var tgtX1 = rs.lastTgtCtlPtX; - var tgtX2 = tgtPos.x; - var tgtY1 = rs.lastTgtCtlPtY; - var tgtY2 = tgtPos.y; - var tgtW1 = rs.lastTgtCtlPtW; - var tgtW2 = tgt.outerWidth(); - var tgtH1 = rs.lastTgtCtlPtH; - var tgtH2 = tgt.outerHeight(); - - var width1 = rs.lastW; - var width2 = edge.pstyle( 'control-point-step-size' ).pfValue; - - var edgeDistances = edge.pstyle('edge-distances').value; - - if( badBezier ){ - rs.badBezier = true; - } else { - rs.badBezier = false; - } - - if( srcX1 === srcX2 && srcY1 === srcY2 && srcW1 === srcW2 && srcH1 === srcH2 - && tgtX1 === tgtX2 && tgtY1 === tgtY2 && tgtW1 === tgtW2 && tgtH1 === tgtH2 - && width1 === width2 - && ((edgeIndex1 === edgeIndex2 && numEdges1 === numEdges2) || edgeIsUnbundled) ){ - // console.log('edge ctrl pt cache HIT') - continue; // then the control points haven't changed and we can skip calculating them - } else { - rs.lastSrcCtlPtX = srcX2; - rs.lastSrcCtlPtY = srcY2; - rs.lastSrcCtlPtW = srcW2; - rs.lastSrcCtlPtH = srcH2; - rs.lastTgtCtlPtX = tgtX2; - rs.lastTgtCtlPtY = tgtY2; - rs.lastTgtCtlPtW = tgtW2; - rs.lastTgtCtlPtH = tgtH2; - rs.lastEdgeIndex = edgeIndex2; - rs.lastNumEdges = numEdges2; - rs.lastWidth = width2; - // console.log('edge ctrl pt cache MISS') - } - - if( src === tgt ){ - // Self-edge - - rs.edgeType = 'self'; - - var j = i; - var loopDist = stepSize; - - if( edgeIsUnbundled ){ - j = 0; - loopDist = ctrlptDist; - } - - rs.ctrlpts = [ - srcPos.x, - srcPos.y - (1 + Math.pow( srcH, 1.12 ) / 100) * loopDist * (j / 3 + 1), - - srcPos.x - (1 + Math.pow( srcW, 1.12 ) / 100) * loopDist * (j / 3 + 1), - srcPos.y - ]; - - } else if( - hasCompounds && - ( src.isParent() || src.isChild() || tgt.isParent() || tgt.isChild() ) && - ( src.parents().anySame( tgt ) || tgt.parents().anySame( src ) ) - ){ - // Compound edge - - rs.edgeType = 'compound'; - - // because the line approximation doesn't apply for compound beziers - // (loop/self edges are already elided b/c of cheap src==tgt check) - rs.badBezier = false; - - var j = i; - var loopDist = stepSize; - - if( edgeIsUnbundled ){ - j = 0; - loopDist = ctrlptDist; - } - - var loopW = 50; - - var loopaPos = { - x: srcPos.x - srcW / 2, - y: srcPos.y - srcH / 2 - }; - - var loopbPos = { - x: tgtPos.x - tgtW / 2, - y: tgtPos.y - tgtH / 2 - }; - - var loopPos = { - x: Math.min( loopaPos.x, loopbPos.x ), - y: Math.min( loopaPos.y, loopbPos.y ) - }; - - // avoids cases with impossible beziers - var minCompoundStretch = 0.5; - var compoundStretchA = Math.max( minCompoundStretch, Math.log( srcW * 0.01 ) ); - var compoundStretchB = Math.max( minCompoundStretch, Math.log( tgtW * 0.01 ) ); - - rs.ctrlpts = [ - loopPos.x, - loopPos.y - (1 + Math.pow( loopW, 1.12 ) / 100) * loopDist * (j / 3 + 1) * compoundStretchA, - - loopPos.x - (1 + Math.pow( loopW, 1.12 ) / 100) * loopDist * (j / 3 + 1) * compoundStretchB, - loopPos.y - ]; - - } else if( curveStyle === 'segments' ){ - // Segments (multiple straight lines) - - rs.edgeType = 'segments'; - rs.segpts = []; - - var segmentWs = edge.pstyle( 'segment-weights' ).pfValue; - var segmentDs = edge.pstyle( 'segment-distances' ).pfValue; - var segmentsN = Math.min( segmentWs.length, segmentDs.length ); - - for( var s = 0; s < segmentsN; s++ ){ - var w = segmentWs[ s ]; - var d = segmentDs[ s ]; - - var w1 = 1 - w; - var w2 = w; - - var midptPts = edgeDistances === 'node-position' ? posPts : midptSrcPts; - - var adjustedMidpt = { - x: midptPts.x1 * w1 + midptPts.x2 * w2, - y: midptPts.y1 * w1 + midptPts.y2 * w2 - }; - - rs.segpts.push( - adjustedMidpt.x + vectorNormInverse.x * d, - adjustedMidpt.y + vectorNormInverse.y * d - ); - } - - // Straight edge - } else if( - pairEdges.length % 2 === 1 - && i === Math.floor( pairEdges.length / 2 ) - && !edgeIsUnbundled - ){ - - rs.edgeType = 'straight'; - - } else { - // (Multi)bezier - - var multi = edgeIsUnbundled; - - rs.edgeType = multi ? 'multibezier' : 'bezier'; - rs.ctrlpts = []; - - for( var b = 0; b < bezierN; b++ ){ - var normctrlptDist = (0.5 - pairEdges.length / 2 + i) * stepSize; - var manctrlptDist; - var sign = math.signum( normctrlptDist ); - - if( multi ){ - ctrlptDist = ctrlptDists ? ctrlptDists.pfValue[ b ] : stepSize; // fall back on step size - ctrlptWeight = ctrlptWs.value[ b ]; - } - - if( edgeIsUnbundled ){ // multi or single unbundled - manctrlptDist = ctrlptDist; - } else { - manctrlptDist = ctrlptDist !== undefined ? sign * ctrlptDist : undefined; - } - - var distanceFromMidpoint = manctrlptDist !== undefined ? manctrlptDist : normctrlptDist; - - var w1 = 1 - ctrlptWeight; - var w2 = ctrlptWeight; - - var midptPts = edgeDistances === 'node-position' ? posPts : midptSrcPts; - - var adjustedMidpt = { - x: midptPts.x1 * w1 + midptPts.x2 * w2, - y: midptPts.y1 * w1 + midptPts.y2 * w2 - }; - - rs.ctrlpts.push( - adjustedMidpt.x + vectorNormInverse.x * distanceFromMidpoint, - adjustedMidpt.y + vectorNormInverse.y * distanceFromMidpoint - ); - } - - } - - // find endpts for edge - this.findEndpoints( edge ); - - var badStart = !is.number( rs.startX ) || !is.number( rs.startY ); - var badAStart = !is.number( rs.arrowStartX ) || !is.number( rs.arrowStartY ); - var badEnd = !is.number( rs.endX ) || !is.number( rs.endY ); - var badAEnd = !is.number( rs.arrowEndX ) || !is.number( rs.arrowEndY ); - - var minCpADistFactor = 3; - var arrowW = this.getArrowWidth( edge.pstyle( 'width' ).pfValue ) * this.arrowShapeWidth; - var minCpADist = minCpADistFactor * arrowW; - - if( rs.edgeType === 'bezier' ){ - var startACpDist = math.dist( { x: rs.ctrlpts[0], y: rs.ctrlpts[1] }, { x: rs.startX, y: rs.startY } ); - var closeStartACp = startACpDist < minCpADist; - var endACpDist = math.dist( { x: rs.ctrlpts[0], y: rs.ctrlpts[1] }, { x: rs.endX, y: rs.endY } ); - var closeEndACp = endACpDist < minCpADist; - - var overlapping = false; - - if( badStart || badAStart || closeStartACp ){ - overlapping = true; - - // project control point along line from src centre to outside the src shape - // (otherwise intersection will yield nothing) - var cpD = { // delta - x: rs.ctrlpts[0] - srcPos.x, - y: rs.ctrlpts[1] - srcPos.y - }; - var cpL = Math.sqrt( cpD.x * cpD.x + cpD.y * cpD.y ); // length of line - var cpM = { // normalised delta - x: cpD.x / cpL, - y: cpD.y / cpL - }; - var radius = Math.max( srcW, srcH ); - var cpProj = { // *2 radius guarantees outside shape - x: rs.ctrlpts[0] + cpM.x * 2 * radius, - y: rs.ctrlpts[1] + cpM.y * 2 * radius - }; - - var srcCtrlPtIntn = srcShape.intersectLine( - srcPos.x, - srcPos.y, - srcW, - srcH, - cpProj.x, - cpProj.y, - 0 - ); - - if( closeStartACp ){ - rs.ctrlpts[0] = rs.ctrlpts[0] + cpM.x * (minCpADist - startACpDist); - rs.ctrlpts[1] = rs.ctrlpts[1] + cpM.y * (minCpADist - startACpDist); - } else { - rs.ctrlpts[0] = srcCtrlPtIntn[0] + cpM.x * minCpADist; - rs.ctrlpts[1] = srcCtrlPtIntn[1] + cpM.y * minCpADist; - } - } - - if( badEnd || badAEnd || closeEndACp ){ - overlapping = true; - - // project control point along line from tgt centre to outside the tgt shape - // (otherwise intersection will yield nothing) - var cpD = { // delta - x: rs.ctrlpts[0] - tgtPos.x, - y: rs.ctrlpts[1] - tgtPos.y - }; - var cpL = Math.sqrt( cpD.x * cpD.x + cpD.y * cpD.y ); // length of line - var cpM = { // normalised delta - x: cpD.x / cpL, - y: cpD.y / cpL - }; - var radius = Math.max( srcW, srcH ); - var cpProj = { // *2 radius guarantees outside shape - x: rs.ctrlpts[0] + cpM.x * 2 * radius, - y: rs.ctrlpts[1] + cpM.y * 2 * radius - }; - - var tgtCtrlPtIntn = tgtShape.intersectLine( - tgtPos.x, - tgtPos.y, - tgtW, - tgtH, - cpProj.x, - cpProj.y, - 0 - ); - - if( closeEndACp ){ - rs.ctrlpts[0] = rs.ctrlpts[0] + cpM.x * (minCpADist - endACpDist); - rs.ctrlpts[1] = rs.ctrlpts[1] + cpM.y * (minCpADist - endACpDist); - } else { - rs.ctrlpts[0] = tgtCtrlPtIntn[0] + cpM.x * minCpADist; - rs.ctrlpts[1] = tgtCtrlPtIntn[1] + cpM.y * minCpADist; - } - - } - - if( overlapping ){ - // recalc endpts - this.findEndpoints( edge ); - } - - } - - if( rs.edgeType === 'multibezier' || rs.edgeType === 'bezier' || rs.edgeType === 'self' || rs.edgeType === 'compound' ){ - rs.allpts = []; - - rs.allpts.push( rs.startX, rs.startY ); - - for( var b = 0; b + 1 < rs.ctrlpts.length; b += 2 ){ - // ctrl pt itself - rs.allpts.push( rs.ctrlpts[ b ], rs.ctrlpts[ b + 1] ); - - // the midpt between ctrlpts as intermediate destination pts - if( b + 3 < rs.ctrlpts.length ){ - rs.allpts.push( (rs.ctrlpts[ b ] + rs.ctrlpts[ b + 2]) / 2, (rs.ctrlpts[ b + 1] + rs.ctrlpts[ b + 3]) / 2 ); - } - } - - rs.allpts.push( rs.endX, rs.endY ); - - var m, mt; - if( rs.ctrlpts.length / 2 % 2 === 0 ){ - m = rs.allpts.length / 2 - 1; - - rs.midX = rs.allpts[ m ]; - rs.midY = rs.allpts[ m + 1]; - } else { - m = rs.allpts.length / 2 - 3; - mt = 0.5; - - rs.midX = math.qbezierAt( rs.allpts[ m ], rs.allpts[ m + 2], rs.allpts[ m + 4], mt ); - rs.midY = math.qbezierAt( rs.allpts[ m + 1], rs.allpts[ m + 3], rs.allpts[ m + 5], mt ); - } - - } else if( rs.edgeType === 'straight' ){ - // need to calc these after endpts - rs.allpts = [ rs.startX, rs.startY, rs.endX, rs.endY ]; - - // default midpt for labels etc - rs.midX = ( rs.startX + rs.endX + rs.arrowStartX + rs.arrowEndX ) / 4; - rs.midY = ( rs.startY + rs.endY + rs.arrowStartY + rs.arrowEndY ) / 4; - - } else if( rs.edgeType === 'segments' ){ - rs.allpts = []; - rs.allpts.push( rs.startX, rs.startY ); - rs.allpts.push.apply( rs.allpts, rs.segpts ); - rs.allpts.push( rs.endX, rs.endY ); - - if( rs.segpts.length % 4 === 0 ){ - var i2 = rs.segpts.length / 2; - var i1 = i2 - 2; - - rs.midX = ( rs.segpts[ i1 ] + rs.segpts[ i2 ] ) / 2; - rs.midY = ( rs.segpts[ i1 + 1] + rs.segpts[ i2 + 1] ) / 2; - } else { - var i1 = rs.segpts.length / 2 - 1; - - rs.midX = rs.segpts[ i1 ]; - rs.midY = rs.segpts[ i1 + 1]; - } - - - } - - this.projectLines( edge ); - this.calculateArrowAngles( edge ); - this.recalculateEdgeLabelProjections( edge ); - this.calculateLabelAngles( edge ); - - } // for pair edges - } // for pair ids - - for( var i = 0; i < haystackEdges.length; i++ ){ - var edge = haystackEdges[ i ]; - var _p = edge._private; - var rscratch = _p.rscratch; - var rs = rscratch; - - if( !rscratch.haystack ){ - var angle = Math.random() * 2 * Math.PI; - - rscratch.source = { - x: Math.cos( angle ), - y: Math.sin( angle ) - }; - - var angle = Math.random() * 2 * Math.PI; - - rscratch.target = { - x: Math.cos( angle ), - y: Math.sin( angle ) - }; - - } - - var src = _p.source; - var tgt = _p.target; - var srcPos = src._private.position; - var tgtPos = tgt._private.position; - var srcW = src.width(); - var tgtW = tgt.width(); - var srcH = src.height(); - var tgtH = tgt.height(); - var radius = edge.pstyle( 'haystack-radius' ).value; - var halfRadius = radius / 2; // b/c have to half width/height - - rs.haystackPts = rs.allpts = [ - rs.source.x * srcW * halfRadius + srcPos.x, - rs.source.y * srcH * halfRadius + srcPos.y, - rs.target.x * tgtW * halfRadius + tgtPos.x, - rs.target.y * tgtH * halfRadius + tgtPos.y - ]; - - rs.midX = (rs.allpts[0] + rs.allpts[2]) / 2; - rs.midY = (rs.allpts[1] + rs.allpts[3]) / 2; - - // always override as haystack in case set to different type previously - rscratch.edgeType = 'haystack'; - rscratch.haystack = true; - - this.projectLines( edge ); - this.calculateArrowAngles( edge ); - this.recalculateEdgeLabelProjections( edge ); - this.calculateLabelAngles( edge ); - } - - return hashTable; -}; - -var getAngleFromDisp = function( dispX, dispY ){ - return Math.atan2( dispY, dispX ) - Math.PI / 2; -}; - -BRp.calculateArrowAngles = function( edge ){ - var rs = edge._private.rscratch; - var isHaystack = rs.edgeType === 'haystack'; - var isMultibezier = rs.edgeType === 'multibezier'; - var isSegments = rs.edgeType === 'segments'; - var isCompound = rs.edgeType === 'compound'; - var isSelf = rs.edgeType === 'self'; - - // Displacement gives direction for arrowhead orientation - var dispX, dispY; - var startX, startY, endX, endY; - - var srcPos = edge._private.source._private.position; - var tgtPos = edge._private.target._private.position; - - if( isHaystack ){ - startX = rs.haystackPts[0]; - startY = rs.haystackPts[1]; - endX = rs.haystackPts[2]; - endY = rs.haystackPts[3]; - } else { - startX = rs.arrowStartX; - startY = rs.arrowStartY; - endX = rs.arrowEndX; - endY = rs.arrowEndY; - } - - // source - // - - dispX = srcPos.x - startX; - dispY = srcPos.y - startY; - - rs.srcArrowAngle = getAngleFromDisp( dispX, dispY ); - - // mid target - // - - var midX = rs.midX; - var midY = rs.midY; - - if( isHaystack ){ - midX = ( startX + endX ) / 2; - midY = ( startY + endY ) / 2; - } - - dispX = endX - startX; - dispY = endY - startY; - - if( isSelf ){ - dispX = -1; - dispY = 1; - } else if( isSegments ){ - var pts = rs.allpts; - - if( pts.length / 2 % 2 === 0 ){ - var i2 = pts.length / 2; - var i1 = i2 - 2; - - dispX = ( pts[ i2 ] - pts[ i1 ] ); - dispY = ( pts[ i2 + 1] - pts[ i1 + 1] ); - } else { - var i2 = pts.length / 2 - 1; - var i1 = i2 - 2; - var i3 = i2 + 2; - - dispX = ( pts[ i2 ] - pts[ i1 ] ); - dispY = ( pts[ i2 + 1] - pts[ i1 + 1] ); - } - } else if( isMultibezier || isCompound ){ - var pts = rs.allpts; - var cpts = rs.ctrlpts; - var bp0x, bp0y; - var bp1x, bp1y; - - if( cpts.length / 2 % 2 === 0 ){ - var p0 = pts.length / 2 - 1; // startpt - var ic = p0 + 2; - var p1 = ic + 2; - - bp0x = math.qbezierAt( pts[ p0 ], pts[ ic ], pts[ p1 ], 0.0 ); - bp0y = math.qbezierAt( pts[ p0 + 1], pts[ ic + 1], pts[ p1 + 1], 0.0 ); - - bp1x = math.qbezierAt( pts[ p0 ], pts[ ic ], pts[ p1 ], 0.0001 ); - bp1y = math.qbezierAt( pts[ p0 + 1], pts[ ic + 1], pts[ p1 + 1], 0.0001 ); - } else { - var ic = pts.length / 2 - 1; // ctrpt - var p0 = ic - 2; // startpt - var p1 = ic + 2; // endpt - - bp0x = math.qbezierAt( pts[ p0 ], pts[ ic ], pts[ p1 ], 0.4999 ); - bp0y = math.qbezierAt( pts[ p0 + 1], pts[ ic + 1], pts[ p1 + 1], 0.4999 ); - - bp1x = math.qbezierAt( pts[ p0 ], pts[ ic ], pts[ p1 ], 0.5 ); - bp1y = math.qbezierAt( pts[ p0 + 1], pts[ ic + 1], pts[ p1 + 1], 0.5 ); - } - - dispX = ( bp1x - bp0x ); - dispY = ( bp1y - bp0y ); - } - - rs.midtgtArrowAngle = getAngleFromDisp( dispX, dispY ); - - rs.midDispX = dispX; - rs.midDispY = dispY; - - // mid source - // - - dispX *= -1; - dispY *= -1; - - if( isSegments ){ - var pts = rs.allpts; - - if( pts.length / 2 % 2 === 0 ){ - // already ok - } else { - var i2 = pts.length / 2 - 1; - var i3 = i2 + 2; - - dispX = -( pts[ i3 ] - pts[ i2 ] ); - dispY = -( pts[ i3 + 1] - pts[ i2 + 1] ); - } - } - - rs.midsrcArrowAngle = getAngleFromDisp( dispX, dispY ); - - // target - // - - dispX = tgtPos.x - endX; - dispY = tgtPos.y - endY; - - rs.tgtArrowAngle = getAngleFromDisp( dispX, dispY ); -}; - -BRp.calculateLabelAngles = function( ele ){ - var _p = ele._private; - var rs = _p.rscratch; - var isEdge = ele.isEdge(); - var rot = ele.pstyle( 'text-rotation' ); - var rotStr = rot.strValue; - - if( rotStr === 'none' ){ - rs.labelAngle = rs.sourceLabelAngle = rs.targetLabelAngle = 0; - } else if( isEdge && rotStr === 'autorotate' ){ - rs.labelAngle = Math.atan( rs.midDispY / rs.midDispX ); - rs.sourceLabelAngle = rs.sourceLabelAutoAngle; - rs.targetLabelAngle = rs.targetLabelAutoAngle; - } else if( rotStr === 'autorotate' ){ - rs.labelAngle = rs.sourceLabelAngle = rs.targetLabelAngle = 0; - } else { - rs.labelAngle = rs.sourceLabelAngle = rs.targetLabelAngle = rot.pfValue; - } -}; - - -BRp.findEndpoints = function( edge ){ - var r = this; - var intersect; - - var source = edge.source()[0]; - var target = edge.target()[0]; - - var src_p = source._private; - var tgt_p = target._private; - - var srcPos = src_p.position; - var tgtPos = tgt_p.position; - - var tgtArShape = edge.pstyle( 'target-arrow-shape' ).value; - var srcArShape = edge.pstyle( 'source-arrow-shape' ).value; - - var rs = edge._private.rscratch; - - var et = rs.edgeType; - var bezier = et === 'bezier' || et === 'multibezier' || et === 'self' || et === 'compound'; - var multi = et !== 'bezier'; - var lines = et === 'straight' || et === 'segments'; - var segments = et === 'segments'; - var hasEndpts = bezier || multi || lines; - - var p1, p2; - - if( bezier ){ - var cpStart = [ rs.ctrlpts[0], rs.ctrlpts[1] ]; - var cpEnd = multi ? [ rs.ctrlpts[ rs.ctrlpts.length - 2], rs.ctrlpts[ rs.ctrlpts.length - 1] ] : cpStart; - - p1 = cpEnd; - p2 = cpStart; - } else if( lines ){ - var srcArrowFromPt = !segments ? [ tgtPos.x, tgtPos.y ] : rs.segpts.slice( 0, 2 ); - var tgtArrowFromPt = !segments ? [ srcPos.x, srcPos.y ] : rs.segpts.slice( rs.segpts.length - 2 ); - - p1 = tgtArrowFromPt; - p2 = srcArrowFromPt; - } - - intersect = r.nodeShapes[ this.getNodeShape( target ) ].intersectLine( - tgtPos.x, - tgtPos.y, - target.outerWidth(), - target.outerHeight(), - p1[0], - p1[1], - 0 - ); - - var arrowEnd = math.shortenIntersection( intersect, p1, - r.arrowShapes[ tgtArShape ].spacing( edge ) ); - var edgeEnd = math.shortenIntersection( intersect, p1, - r.arrowShapes[ tgtArShape ].gap( edge ) ); - - rs.endX = edgeEnd[0]; - rs.endY = edgeEnd[1]; - - rs.arrowEndX = arrowEnd[0]; - rs.arrowEndY = arrowEnd[1]; - - intersect = r.nodeShapes[ this.getNodeShape( source ) ].intersectLine( - srcPos.x, - srcPos.y, - source.outerWidth(), - source.outerHeight(), - p2[0], - p2[1], - 0 - ); - - var arrowStart = math.shortenIntersection( - intersect, p2, - r.arrowShapes[ srcArShape ].spacing( edge ) - ); - var edgeStart = math.shortenIntersection( - intersect, p2, - r.arrowShapes[ srcArShape ].gap( edge ) - ); - - rs.startX = edgeStart[0]; - rs.startY = edgeStart[1]; - - rs.arrowStartX = arrowStart[0]; - rs.arrowStartY = arrowStart[1]; - - if( hasEndpts ){ - if( !is.number( rs.startX ) || !is.number( rs.startY ) || !is.number( rs.endX ) || !is.number( rs.endY ) ){ - rs.badLine = true; - } else { - rs.badLine = false; - } - } -}; - -BRp.getArrowWidth = BRp.getArrowHeight = function( edgeWidth ){ - var cache = this.arrowWidthCache = this.arrowWidthCache || {}; - - var cachedVal = cache[ edgeWidth ]; - if( cachedVal ){ - return cachedVal; - } - - cachedVal = Math.max( Math.pow( edgeWidth * 13.37, 0.9 ), 29 ); - cache[ edgeWidth ] = cachedVal; - - return cachedVal; -}; - -module.exports = BRp; - -},{"../../../collection/zsort":32,"../../../is":83,"../../../math":85,"../../../util":100}],59:[function(_dereq_,module,exports){ -'use strict'; - -var BRp = {}; - -BRp.getCachedImage = function( url, onLoad ){ - var r = this; - var imageCache = r.imageCache = r.imageCache || {}; - - if( imageCache[ url ] && imageCache[ url ].image ){ - return imageCache[ url ].image; - } - - var cache = imageCache[ url ] = imageCache[ url ] || {}; - - var image = cache.image = new Image(); // eslint-disable-line no-undef - image.addEventListener('load', onLoad); - image.crossOrigin = 'Anonymous'; // prevent tainted canvas - image.src = url; - - return image; -}; - -module.exports = BRp; - -},{}],60:[function(_dereq_,module,exports){ -'use strict'; - -var is = _dereq_( '../../../is' ); -var util = _dereq_( '../../../util' ); - -var BaseRenderer = function( options ){ this.init( options ); }; var BR = BaseRenderer; var BRp = BR.prototype; -BRp.clientFunctions = [ 'redrawHint', 'render', 'renderTo', 'matchCanvasSize', 'nodeShapeImpl', 'arrowShapeImpl' ]; +BRp.clientFunctions = ['redrawHint', 'render', 'renderTo', 'matchCanvasSize', 'nodeShapeImpl', 'arrowShapeImpl']; -BRp.init = function( options ){ +BRp.init = function (options) { var r = this; r.options = options; r.cy = options.cy; - r.container = options.cy.container(); + var ctr = r.container = options.cy.container(); - r.selection = [ undefined, undefined, undefined, undefined, 0]; // Coordinates for selection box, plus enabled flag + // prepend a stylesheet in the head such that + if (window) { + var document = window.document; + var head = document.head; + var stylesheetId = '__________cytoscape_stylesheet'; + var className = '__________cytoscape_container'; + var stylesheetAlreadyExists = document.getElementById(stylesheetId) != null; - r.bezierProjPcts = [ 0.05, 0.225, 0.4, 0.5, 0.6, 0.775, 0.95 ]; + if (ctr.className.indexOf(className) < 0) { + ctr.className = (ctr.className || '') + ' ' + className; + } + + if (!stylesheetAlreadyExists) { + var stylesheet = document.createElement('style'); + + stylesheet.id = stylesheetId; + stylesheet.innerHTML = '.' + className + ' { position: relative; }'; + + head.insertBefore(stylesheet, head.children[0]); // first so lowest priority + } + + var computedStyle = window.getComputedStyle(ctr); + var position = computedStyle.getPropertyValue('position'); + + if (position === 'static') { + util.error('A Cytoscape container has style position:static and so can not use UI extensions properly'); + } + } + + r.selection = [undefined, undefined, undefined, undefined, 0]; // Coordinates for selection box, plus enabled flag + + r.bezierProjPcts = [0.05, 0.225, 0.4, 0.5, 0.6, 0.775, 0.95]; //--Pointer-related data - r.hoverData = {down: null, last: null, - downTime: null, triggerMode: null, - dragging: false, - initialPan: [ null, null ], capture: false}; + r.hoverData = { down: null, last: null, + downTime: null, triggerMode: null, + dragging: false, + initialPan: [null, null], capture: false }; - r.dragData = {possibleDragElements: []}; + r.dragData = { possibleDragElements: [] }; r.touchData = { start: null, capture: false, // These 3 fields related to tap, taphold events - startPosition: [ null, null, null, null, null, null ], + startPosition: [null, null, null, null, null, null], singleTouchStartTime: null, singleTouchMoved: true, - now: [ null, null, null, null, null, null ], - earlier: [ null, null, null, null, null, null ] + now: [null, null, null, null, null, null], + earlier: [null, null, null, null, null, null] }; r.redraws = 0; r.showFps = options.showFps; + r.debug = options.debug; r.hideEdgesOnViewport = options.hideEdgesOnViewport; r.hideLabelsOnViewport = options.hideLabelsOnViewport; @@ -14154,140 +20560,2884 @@ BRp.init = function( options ){ r.bindings = []; r.beforeRenderCallbacks = []; r.beforeRenderPriorities = { // higher priority execs before lower one - animations: 400, - eleCalcs: 300, - eleTxrDeq: 200, - lyrTxrDeq: 100 + animations: 400, + eleCalcs: 300, + eleTxrDeq: 200, + lyrTxrDeq: 100 }; r.registerNodeShapes(); r.registerArrowShapes(); r.registerCalculationListeners(); - r.load(); }; -BRp.notify = function( params ){ +BRp.notify = function (params) { var types; var r = this; - if( is.array( params.type ) ){ - types = params.type; + // the renderer can't be notified after it's destroyed + if (this.destroyed) { + return; + } + if (is.array(params.type)) { + types = params.type; } else { - types = [ params.type ]; + types = [params.type]; } var has = {}; - for( var i = 0; i < types.length; i++ ){ - var type = types[ i ]; + for (var i = 0; i < types.length; i++) { + var type = types[i]; - has[ type ] = true; + has[type] = true; } // for - if( has['destroy'] ){ + if (has['init']) { + r.load(); + return; + } + + if (has['destroy']) { r.destroy(); return; } - if( has['add'] || has['remove'] || has['load'] || has['style'] ){ - r.updateCachedZSortedEles(); + if (has['add'] || has['remove'] || has['load'] || has['zorder']) { + r.invalidateCachedZSortedEles(); } - if( has['viewport'] ){ - r.redrawHint( 'select', true ); + if (has['viewport']) { + r.redrawHint('select', true); } - if( has['load'] || has['resize'] ){ + if (has['load'] || has['resize']) { r.invalidateContainerClientCoordsCache(); - r.matchCanvasSize( r.container ); + r.matchCanvasSize(r.container); } - r.redrawHint( 'eles', true ); - r.redrawHint( 'drag', true ); + r.redrawHint('eles', true); + r.redrawHint('drag', true); this.startRenderLoop(); this.redraw(); }; -BRp.destroy = function(){ +BRp.destroy = function () { var r = this; r.destroyed = true; r.cy.stopAnimationLoop(); - for( var i = 0; i < r.bindings.length; i++ ){ - var binding = r.bindings[ i ]; + for (var i = 0; i < r.bindings.length; i++) { + var binding = r.bindings[i]; var b = binding; var tgt = b.target; - ( tgt.off || tgt.removeEventListener ).apply( tgt, b.args ); + (tgt.off || tgt.removeEventListener).apply(tgt, b.args); } r.bindings = []; r.beforeRenderCallbacks = []; r.onUpdateEleCalcsFns = []; - if( r.removeObserver ){ + if (r.removeObserver) { r.removeObserver.disconnect(); } - if( r.styleObserver ){ + if (r.styleObserver) { r.styleObserver.disconnect(); } - if( r.labelCalcDiv ){ + if (r.labelCalcDiv) { try { - document.body.removeChild( r.labelCalcDiv ); // eslint-disable-line no-undef - } catch( e ){ + document.body.removeChild(r.labelCalcDiv); // eslint-disable-line no-undef + } catch (e) { // ie10 issue #1014 } } }; -[ - _dereq_( './arrow-shapes' ), - _dereq_( './coord-ele-math' ), - _dereq_( './images' ), - _dereq_( './load-listeners' ), - _dereq_( './node-shapes' ), - _dereq_( './redraw' ) -].forEach( function( props ){ - util.extend( BRp, props ); -} ); +[__webpack_require__(109), __webpack_require__(110), __webpack_require__(120), __webpack_require__(121), __webpack_require__(122), __webpack_require__(123)].forEach(function (props) { + util.extend(BRp, props); +}); module.exports = BR; -},{"../../../is":83,"../../../util":100,"./arrow-shapes":57,"./coord-ele-math":58,"./images":59,"./load-listeners":61,"./node-shapes":62,"./redraw":63}],61:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 109 */ +/***/ (function(module, exports, __webpack_require__) { -var is = _dereq_( '../../../is' ); -var util = _dereq_( '../../../util' ); -var math = _dereq_( '../../../math' ); -var Event = _dereq_( '../../../event' ); +"use strict"; + + +var math = __webpack_require__(2); +var is = __webpack_require__(0); +var util = __webpack_require__(1); var BRp = {}; -BRp.registerBinding = function( target, event, handler, useCapture ){ - var args = Array.prototype.slice.apply( arguments, [1] ); // copy - var b = this.binder( target ); +BRp.arrowShapeWidth = 0.3; - return b.on.apply( b, args ); +BRp.registerArrowShapes = function () { + var arrowShapes = this.arrowShapes = {}; + var renderer = this; + + // Contract for arrow shapes: + // 0, 0 is arrow tip + // (0, 1) is direction towards node + // (1, 0) is right + // + // functional api: + // collide: check x, y in shape + // roughCollide: called before collide, no false negatives + // draw: draw + // spacing: dist(arrowTip, nodeBoundary) + // gap: dist(edgeTip, nodeBoundary), edgeTip may != arrowTip + + var bbCollide = function bbCollide(x, y, size, angle, translation, edgeWidth, padding) { + var x1 = translation.x - size / 2 - padding; + var x2 = translation.x + size / 2 + padding; + var y1 = translation.y - size / 2 - padding; + var y2 = translation.y + size / 2 + padding; + + var inside = x1 <= x && x <= x2 && y1 <= y && y <= y2; + + return inside; + }; + + var transform = function transform(x, y, size, angle, translation) { + var xRotated = x * Math.cos(angle) - y * Math.sin(angle); + var yRotated = x * Math.sin(angle) + y * Math.cos(angle); + + var xScaled = xRotated * size; + var yScaled = yRotated * size; + + var xTranslated = xScaled + translation.x; + var yTranslated = yScaled + translation.y; + + return { + x: xTranslated, + y: yTranslated + }; + }; + + var transformPoints = function transformPoints(pts, size, angle, translation) { + var retPts = []; + + for (var i = 0; i < pts.length; i += 2) { + var x = pts[i]; + var y = pts[i + 1]; + + retPts.push(transform(x, y, size, angle, translation)); + } + + return retPts; + }; + + var pointsToArr = function pointsToArr(pts) { + var ret = []; + + for (var i = 0; i < pts.length; i++) { + var p = pts[i]; + + ret.push(p.x, p.y); + } + + return ret; + }; + + var standardGap = function standardGap(edge) { + return edge.pstyle('width').pfValue * edge.pstyle('arrow-scale').pfValue * 2; + }; + + var defineArrowShape = function defineArrowShape(name, defn) { + if (is.string(defn)) { + defn = arrowShapes[defn]; + } + + arrowShapes[name] = util.extend({ + name: name, + + points: [-0.15, -0.3, 0.15, -0.3, 0.15, 0.3, -0.15, 0.3], + + collide: function collide(x, y, size, angle, translation, padding) { + var points = pointsToArr(transformPoints(this.points, size + 2 * padding, angle, translation)); + var inside = math.pointInsidePolygonPoints(x, y, points); + + return inside; + }, + + roughCollide: bbCollide, + + draw: function draw(context, size, angle, translation) { + var points = transformPoints(this.points, size, angle, translation); + + renderer.arrowShapeImpl('polygon')(context, points); + }, + + spacing: function spacing(edge) { + return 0; + }, + + gap: standardGap + }, defn); + }; + + defineArrowShape('none', { + collide: util.falsify, + + roughCollide: util.falsify, + + draw: util.noop, + + spacing: util.zeroify, + + gap: util.zeroify + }); + + defineArrowShape('triangle', { + points: [-0.15, -0.3, 0, 0, 0.15, -0.3] + }); + + defineArrowShape('arrow', 'triangle'); + + defineArrowShape('triangle-backcurve', { + points: arrowShapes['triangle'].points, + + controlPoint: [0, -0.15], + + roughCollide: bbCollide, + + draw: function draw(context, size, angle, translation, edgeWidth) { + var ptsTrans = transformPoints(this.points, size, angle, translation); + var ctrlPt = this.controlPoint; + var ctrlPtTrans = transform(ctrlPt[0], ctrlPt[1], size, angle, translation); + + renderer.arrowShapeImpl(this.name)(context, ptsTrans, ctrlPtTrans); + }, + + gap: function gap(edge) { + return standardGap(edge) * 0.8; + } + }); + + defineArrowShape('triangle-tee', { + points: [-0.15, -0.3, 0, 0, 0.15, -0.3, -0.15, -0.3], + + pointsTee: [-0.15, -0.4, -0.15, -0.5, 0.15, -0.5, 0.15, -0.4], + + collide: function collide(x, y, size, angle, translation, edgeWidth, padding) { + var triPts = pointsToArr(transformPoints(this.points, size + 2 * padding, angle, translation)); + var teePts = pointsToArr(transformPoints(this.pointsTee, size + 2 * padding, angle, translation)); + + var inside = math.pointInsidePolygonPoints(x, y, triPts) || math.pointInsidePolygonPoints(x, y, teePts); + + return inside; + }, + + draw: function draw(context, size, angle, translation, edgeWidth) { + var triPts = transformPoints(this.points, size, angle, translation); + var teePts = transformPoints(this.pointsTee, size, angle, translation); + + renderer.arrowShapeImpl(this.name)(context, triPts, teePts); + } + }); + + defineArrowShape('triangle-cross', { + points: [-0.15, -0.3, 0, 0, 0.15, -0.3, -0.15, -0.3], + + baseCrossLinePts: [-0.15, -0.4, // first half of the rectangle + -0.15, -0.4, 0.15, -0.4, // second half of the rectangle + 0.15, -0.4], + + crossLinePts: function crossLinePts(size, edgeWidth) { + // shift points so that the distance between the cross points matches edge width + var p = this.baseCrossLinePts.slice(); + var shiftFactor = edgeWidth / size; + var y0 = 3; + var y1 = 5; + + p[y0] = p[y0] - shiftFactor; + p[y1] = p[y1] - shiftFactor; + + return p; + }, + + collide: function collide(x, y, size, angle, translation, edgeWidth, padding) { + var triPts = pointsToArr(transformPoints(this.points, size + 2 * padding, angle, translation)); + var teePts = pointsToArr(transformPoints(this.crossLinePts(size, edgeWidth), size + 2 * padding, angle, translation)); + var inside = math.pointInsidePolygonPoints(x, y, triPts) || math.pointInsidePolygonPoints(x, y, teePts); + + return inside; + }, + + draw: function draw(context, size, angle, translation, edgeWidth) { + var triPts = transformPoints(this.points, size, angle, translation); + var crossLinePts = transformPoints(this.crossLinePts(size, edgeWidth), size, angle, translation); + + renderer.arrowShapeImpl(this.name)(context, triPts, crossLinePts); + } + }); + + defineArrowShape('vee', { + points: [-0.15, -0.3, 0, 0, 0.15, -0.3, 0, -0.15], + + gap: function gap(edge) { + return standardGap(edge) * 0.525; + } + }); + + defineArrowShape('circle', { + radius: 0.15, + + collide: function collide(x, y, size, angle, translation, edgeWidth, padding) { + var t = translation; + var inside = Math.pow(t.x - x, 2) + Math.pow(t.y - y, 2) <= Math.pow((size + 2 * padding) * this.radius, 2); + + return inside; + }, + + draw: function draw(context, size, angle, translation, edgeWidth) { + renderer.arrowShapeImpl(this.name)(context, translation.x, translation.y, this.radius * size); + }, + + spacing: function spacing(edge) { + return renderer.getArrowWidth(edge.pstyle('width').pfValue, edge.pstyle('arrow-scale').value) * this.radius; + } + }); + + defineArrowShape('tee', { + points: [-0.15, 0, -0.15, -0.1, 0.15, -0.1, 0.15, 0], + + spacing: function spacing(edge) { + return 1; + }, + + gap: function gap(edge) { + return 1; + } + }); + + defineArrowShape('square', { + points: [-0.15, 0.00, 0.15, 0.00, 0.15, -0.3, -0.15, -0.3] + }); + + defineArrowShape('diamond', { + points: [-0.15, -0.15, 0, -0.3, 0.15, -0.15, 0, 0], + + gap: function gap(edge) { + return edge.pstyle('width').pfValue * edge.pstyle('arrow-scale').value; + } + }); }; -BRp.binder = function( tgt ){ +module.exports = BRp; + +/***/ }), +/* 110 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var util = __webpack_require__(1); + +var BRp = {}; + +[__webpack_require__(111), __webpack_require__(112), __webpack_require__(113), __webpack_require__(114), __webpack_require__(115), __webpack_require__(116), __webpack_require__(117), __webpack_require__(118), __webpack_require__(119)].forEach(function (props) { + util.extend(BRp, props); +}); + +module.exports = BRp; + +/***/ }), +/* 111 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var window = __webpack_require__(3); +var math = __webpack_require__(2); +var util = __webpack_require__(1); +var window = __webpack_require__(3); + +var BRp = {}; + +// Project mouse +BRp.projectIntoViewport = function (clientX, clientY) { + var cy = this.cy; + var offsets = this.findContainerClientCoords(); + var offsetLeft = offsets[0]; + var offsetTop = offsets[1]; + var scale = offsets[4]; + var pan = cy.pan(); + var zoom = cy.zoom(); + + var x = ((clientX - offsetLeft) / scale - pan.x) / zoom; + var y = ((clientY - offsetTop) / scale - pan.y) / zoom; + + return [x, y]; +}; + +BRp.findContainerClientCoords = function () { + if (this.containerBB) { + return this.containerBB; + } + + var container = this.container; + var rect = container.getBoundingClientRect(); + var style = window.getComputedStyle(container); + var styleValue = function styleValue(name) { + return parseFloat(style.getPropertyValue(name)); + }; + + var padding = { + left: styleValue('padding-left'), + right: styleValue('padding-right'), + top: styleValue('padding-top'), + bottom: styleValue('padding-bottom') + }; + + var border = { + left: styleValue('border-left-width'), + right: styleValue('border-right-width'), + top: styleValue('border-top-width'), + bottom: styleValue('border-bottom-width') + }; + + var clientWidth = container.clientWidth; + var clientHeight = container.clientHeight; + + var paddingHor = padding.left + padding.right; + var paddingVer = padding.top + padding.bottom; + + var borderHor = border.left + border.right; + var borderVer = border.top + border.bottom; + + var scale = rect.width / (clientWidth + borderHor); + + var unscaledW = clientWidth - paddingHor; + var unscaledH = clientHeight - paddingVer; + + var scaledW = rect.width - (paddingHor + borderHor) * scale; + var scaledH = rect.height - (paddingVer + borderVer) * scale; + + var left = rect.left + padding.left + border.left; + var top = rect.top + padding.top + border.top; + + return this.containerBB = [left, top, unscaledW, unscaledH, scale]; +}; + +BRp.invalidateContainerClientCoordsCache = function () { + this.containerBB = null; +}; + +BRp.findNearestElement = function (x, y, interactiveElementsOnly, isTouch) { + return this.findNearestElements(x, y, interactiveElementsOnly, isTouch)[0]; +}; + +BRp.findNearestElements = function (x, y, interactiveElementsOnly, isTouch) { + var self = this; + var r = this; + var eles = r.getCachedZSortedEles(); + var near = []; // 1 node max, 1 edge max + var zoom = r.cy.zoom(); + var hasCompounds = r.cy.hasCompoundNodes(); + var edgeThreshold = (isTouch ? 24 : 8) / zoom; + var nodeThreshold = (isTouch ? 8 : 2) / zoom; + var labelThreshold = (isTouch ? 8 : 2) / zoom; + var minSqDist = Infinity; + var nearEdge; + var nearNode; + + if (interactiveElementsOnly) { + eles = eles.interactive; + } + + function addEle(ele, sqDist) { + if (ele.isNode()) { + if (nearNode) { + return; // can't replace node + } else { + nearNode = ele; + near.push(ele); + } + } + + if (ele.isEdge() && (sqDist == null || sqDist < minSqDist)) { + if (nearEdge) { + // then replace existing edge + // can replace only if same z-index + if (nearEdge.pstyle('z-compound-depth').value === ele.pstyle('z-compound-depth').value && nearEdge.pstyle('z-compound-depth').value === ele.pstyle('z-compound-depth').value) { + for (var i = 0; i < near.length; i++) { + if (near[i].isEdge()) { + near[i] = ele; + nearEdge = ele; + minSqDist = sqDist != null ? sqDist : minSqDist; + break; + } + } + } + } else { + near.push(ele); + nearEdge = ele; + minSqDist = sqDist != null ? sqDist : minSqDist; + } + } + } + + function checkNode(node) { + var width = node.outerWidth() + 2 * nodeThreshold; + var height = node.outerHeight() + 2 * nodeThreshold; + var hw = width / 2; + var hh = height / 2; + var pos = node.position(); + + if (pos.x - hw <= x && x <= pos.x + hw // bb check x + && pos.y - hh <= y && y <= pos.y + hh // bb check y + ) { + var shape = r.nodeShapes[self.getNodeShape(node)]; + + if (shape.checkPoint(x, y, 0, width, height, pos.x, pos.y)) { + addEle(node, 0); + return true; + } + } + } + + function checkEdge(edge) { + var _p = edge._private; + + var rs = _p.rscratch; + var styleWidth = edge.pstyle('width').pfValue; + var scale = edge.pstyle('arrow-scale').value; + var width = styleWidth / 2 + edgeThreshold; // more like a distance radius from centre + var widthSq = width * width; + var width2 = width * 2; + var src = _p.source; + var tgt = _p.target; + var inEdgeBB = false; + var sqDist; + + if (rs.edgeType === 'segments' || rs.edgeType === 'straight' || rs.edgeType === 'haystack') { + var pts = rs.allpts; + + for (var i = 0; i + 3 < pts.length; i += 2) { + if ((inEdgeBB = math.inLineVicinity(x, y, pts[i], pts[i + 1], pts[i + 2], pts[i + 3], width2)) && widthSq > (sqDist = math.sqdistToFiniteLine(x, y, pts[i], pts[i + 1], pts[i + 2], pts[i + 3]))) { + addEle(edge, sqDist); + return true; + } + } + } else if (rs.edgeType === 'bezier' || rs.edgeType === 'multibezier' || rs.edgeType === 'self' || rs.edgeType === 'compound') { + var pts = rs.allpts; + for (var i = 0; i + 5 < rs.allpts.length; i += 4) { + if ((inEdgeBB = math.inBezierVicinity(x, y, pts[i], pts[i + 1], pts[i + 2], pts[i + 3], pts[i + 4], pts[i + 5], width2)) && widthSq > (sqDist = math.sqdistToQuadraticBezier(x, y, pts[i], pts[i + 1], pts[i + 2], pts[i + 3], pts[i + 4], pts[i + 5]))) { + addEle(edge, sqDist); + return true; + } + } + } + + // if we're close to the edge but didn't hit it, maybe we hit its arrows + + var src = src || _p.source; + var tgt = tgt || _p.target; + + var arSize = self.getArrowWidth(styleWidth, scale); + + var arrows = [{ name: 'source', x: rs.arrowStartX, y: rs.arrowStartY, angle: rs.srcArrowAngle }, { name: 'target', x: rs.arrowEndX, y: rs.arrowEndY, angle: rs.tgtArrowAngle }, { name: 'mid-source', x: rs.midX, y: rs.midY, angle: rs.midsrcArrowAngle }, { name: 'mid-target', x: rs.midX, y: rs.midY, angle: rs.midtgtArrowAngle }]; + + for (var i = 0; i < arrows.length; i++) { + var ar = arrows[i]; + var shape = r.arrowShapes[edge.pstyle(ar.name + '-arrow-shape').value]; + var edgeWidth = edge.pstyle('width').pfValue; + if (shape.roughCollide(x, y, arSize, ar.angle, { x: ar.x, y: ar.y }, edgeWidth, edgeThreshold) && shape.collide(x, y, arSize, ar.angle, { x: ar.x, y: ar.y }, edgeWidth, edgeThreshold)) { + addEle(edge); + return true; + } + } + + // for compound graphs, hitting edge may actually want a connected node instead (b/c edge may have greater z-index precedence) + if (hasCompounds && near.length > 0) { + checkNode(src); + checkNode(tgt); + } + } + + function preprop(obj, name, pre) { + return util.getPrefixedProperty(obj, name, pre); + } + + function checkLabel(ele, prefix) { + var _p = ele._private; + var th = labelThreshold; + + var prefixDash; + if (prefix) { + prefixDash = prefix + '-'; + } else { + prefixDash = ''; + } + + var text = ele.pstyle(prefixDash + 'label').value; + var eventsEnabled = ele.pstyle('text-events').strValue === 'yes'; + + if (!eventsEnabled || !text) { + return; + } + + var rstyle = _p.rstyle; + var bw = ele.pstyle('text-border-width').pfValue; + var pw = ele.pstyle('text-background-padding').pfValue; + var lw = preprop(rstyle, 'labelWidth', prefix) + bw + 2 * th + 2 * pw; + var lh = preprop(rstyle, 'labelHeight', prefix) + bw + 2 * th + 2 * pw; + var lx = preprop(rstyle, 'labelX', prefix); + var ly = preprop(rstyle, 'labelY', prefix); + + var theta = preprop(_p.rscratch, 'labelAngle', prefix); + + var lx1 = lx - lw / 2; + var lx2 = lx + lw / 2; + var ly1 = ly - lh / 2; + var ly2 = ly + lh / 2; + + if (theta) { + var cos = Math.cos(theta); + var sin = Math.sin(theta); + + var rotate = function rotate(x, y) { + x = x - lx; + y = y - ly; + + return { + x: x * cos - y * sin + lx, + y: x * sin + y * cos + ly + }; + }; + + var px1y1 = rotate(lx1, ly1); + var px1y2 = rotate(lx1, ly2); + var px2y1 = rotate(lx2, ly1); + var px2y2 = rotate(lx2, ly2); + + var points = [px1y1.x, px1y1.y, px2y1.x, px2y1.y, px2y2.x, px2y2.y, px1y2.x, px1y2.y]; + + if (math.pointInsidePolygonPoints(x, y, points)) { + addEle(ele); + return true; + } + } else { + // do a cheaper bb check + var bb = { + w: lw, + h: lh, + x1: lx1, + x2: lx2, + y1: ly1, + y2: ly2 + }; + + if (math.inBoundingBox(bb, x, y)) { + addEle(ele); + return true; + } + } + } + + for (var i = eles.length - 1; i >= 0; i--) { + // reverse order for precedence + var ele = eles[i]; + + if (ele.isNode()) { + checkNode(ele) || checkLabel(ele); + } else { + // then edge + checkEdge(ele) || checkLabel(ele) || checkLabel(ele, 'source') || checkLabel(ele, 'target'); + } + } + + return near; +}; + +// 'Give me everything from this box' +BRp.getAllInBox = function (x1, y1, x2, y2) { + var eles = this.getCachedZSortedEles().interactive; + var box = []; + + var x1c = Math.min(x1, x2); + var x2c = Math.max(x1, x2); + var y1c = Math.min(y1, y2); + var y2c = Math.max(y1, y2); + + x1 = x1c; + x2 = x2c; + y1 = y1c; + y2 = y2c; + + var boxBb = math.makeBoundingBox({ + x1: x1, y1: y1, + x2: x2, y2: y2 + }); + + for (var e = 0; e < eles.length; e++) { + var ele = eles[e]; + + if (ele.isNode()) { + var node = ele; + var nodeBb = node.boundingBox({ + includeNodes: true, + includeEdges: false, + includeLabels: false + }); + + if (math.boundingBoxesIntersect(boxBb, nodeBb) && !math.boundingBoxInBoundingBox(nodeBb, boxBb)) { + box.push(node); + } + } else { + var edge = ele; + var _p = edge._private; + var rs = _p.rscratch; + + if (rs.startX != null && rs.startY != null && !math.inBoundingBox(boxBb, rs.startX, rs.startY)) { + continue; + } + if (rs.endX != null && rs.endY != null && !math.inBoundingBox(boxBb, rs.endX, rs.endY)) { + continue; + } + + if (rs.edgeType === 'bezier' || rs.edgeType === 'multibezier' || rs.edgeType === 'self' || rs.edgeType === 'compound' || rs.edgeType === 'segments' || rs.edgeType === 'haystack') { + + var pts = _p.rstyle.bezierPts || _p.rstyle.linePts || _p.rstyle.haystackPts; + var allInside = true; + + for (var i = 0; i < pts.length; i++) { + if (!math.pointInBoundingBox(boxBb, pts[i])) { + allInside = false; + break; + } + } + + if (allInside) { + box.push(edge); + } + } else if (rs.edgeType === 'haystack' || rs.edgeType === 'straight') { + box.push(edge); + } + } + } + + return box; +}; + +module.exports = BRp; + +/***/ }), +/* 112 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var math = __webpack_require__(2); + +var BRp = {}; + +BRp.calculateArrowAngles = function (edge) { + var rs = edge._private.rscratch; + var isHaystack = rs.edgeType === 'haystack'; + var isBezier = rs.edgeType === 'bezier'; + var isMultibezier = rs.edgeType === 'multibezier'; + var isSegments = rs.edgeType === 'segments'; + var isCompound = rs.edgeType === 'compound'; + var isSelf = rs.edgeType === 'self'; + + // Displacement gives direction for arrowhead orientation + var dispX, dispY; + var startX, startY, endX, endY, midX, midY; + + if (isHaystack) { + startX = rs.haystackPts[0]; + startY = rs.haystackPts[1]; + endX = rs.haystackPts[2]; + endY = rs.haystackPts[3]; + } else { + startX = rs.arrowStartX; + startY = rs.arrowStartY; + endX = rs.arrowEndX; + endY = rs.arrowEndY; + } + + midX = rs.midX; + midY = rs.midY; + + // source + // + + if (isSegments) { + dispX = startX - rs.segpts[0]; + dispY = startY - rs.segpts[1]; + } else if (isMultibezier || isCompound || isSelf || isBezier) { + var pts = rs.allpts; + var bX = math.qbezierAt(pts[0], pts[2], pts[4], 0.1); + var bY = math.qbezierAt(pts[1], pts[3], pts[5], 0.1); + + dispX = startX - bX; + dispY = startY - bY; + } else { + dispX = startX - midX; + dispY = startY - midY; + } + + rs.srcArrowAngle = math.getAngleFromDisp(dispX, dispY); + + // mid target + // + + var midX = rs.midX; + var midY = rs.midY; + + if (isHaystack) { + midX = (startX + endX) / 2; + midY = (startY + endY) / 2; + } + + dispX = endX - startX; + dispY = endY - startY; + + if (isSegments) { + var pts = rs.allpts; + + if (pts.length / 2 % 2 === 0) { + var i2 = pts.length / 2; + var i1 = i2 - 2; + + dispX = pts[i2] - pts[i1]; + dispY = pts[i2 + 1] - pts[i1 + 1]; + } else { + var i2 = pts.length / 2 - 1; + var i1 = i2 - 2; + var i3 = i2 + 2; + + dispX = pts[i2] - pts[i1]; + dispY = pts[i2 + 1] - pts[i1 + 1]; + } + } else if (isMultibezier || isCompound || isSelf) { + var pts = rs.allpts; + var cpts = rs.ctrlpts; + var bp0x, bp0y; + var bp1x, bp1y; + + if (cpts.length / 2 % 2 === 0) { + var p0 = pts.length / 2 - 1; // startpt + var ic = p0 + 2; + var p1 = ic + 2; + + bp0x = math.qbezierAt(pts[p0], pts[ic], pts[p1], 0.0); + bp0y = math.qbezierAt(pts[p0 + 1], pts[ic + 1], pts[p1 + 1], 0.0); + + bp1x = math.qbezierAt(pts[p0], pts[ic], pts[p1], 0.0001); + bp1y = math.qbezierAt(pts[p0 + 1], pts[ic + 1], pts[p1 + 1], 0.0001); + } else { + var ic = pts.length / 2 - 1; // ctrpt + var p0 = ic - 2; // startpt + var p1 = ic + 2; // endpt + + bp0x = math.qbezierAt(pts[p0], pts[ic], pts[p1], 0.4999); + bp0y = math.qbezierAt(pts[p0 + 1], pts[ic + 1], pts[p1 + 1], 0.4999); + + bp1x = math.qbezierAt(pts[p0], pts[ic], pts[p1], 0.5); + bp1y = math.qbezierAt(pts[p0 + 1], pts[ic + 1], pts[p1 + 1], 0.5); + } + + dispX = bp1x - bp0x; + dispY = bp1y - bp0y; + } + + rs.midtgtArrowAngle = math.getAngleFromDisp(dispX, dispY); + + rs.midDispX = dispX; + rs.midDispY = dispY; + + // mid source + // + + dispX *= -1; + dispY *= -1; + + if (isSegments) { + var pts = rs.allpts; + + if (pts.length / 2 % 2 === 0) { + // already ok + } else { + var i2 = pts.length / 2 - 1; + var i3 = i2 + 2; + + dispX = -(pts[i3] - pts[i2]); + dispY = -(pts[i3 + 1] - pts[i2 + 1]); + } + } + + rs.midsrcArrowAngle = math.getAngleFromDisp(dispX, dispY); + + // target + // + + if (isSegments) { + dispX = endX - rs.segpts[rs.segpts.length - 2]; + dispY = endY - rs.segpts[rs.segpts.length - 1]; + } else if (isMultibezier || isCompound || isSelf || isBezier) { + var pts = rs.allpts; + var l = pts.length; + var bX = math.qbezierAt(pts[l - 6], pts[l - 4], pts[l - 2], 0.9); + var bY = math.qbezierAt(pts[l - 5], pts[l - 3], pts[l - 1], 0.9); + + dispX = endX - bX; + dispY = endY - bY; + } else { + dispX = endX - midX; + dispY = endY - midY; + } + + rs.tgtArrowAngle = math.getAngleFromDisp(dispX, dispY); +}; + +BRp.getArrowWidth = BRp.getArrowHeight = function (edgeWidth, scale) { + var cache = this.arrowWidthCache = this.arrowWidthCache || {}; + + var cachedVal = cache[edgeWidth + ', ' + scale]; + if (cachedVal) { + return cachedVal; + } + + cachedVal = Math.max(Math.pow(edgeWidth * 13.37, 0.9), 29) * scale; + cache[edgeWidth + ', ' + scale] = cachedVal; + + return cachedVal; +}; + +module.exports = BRp; + +/***/ }), +/* 113 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var math = __webpack_require__(2); +var is = __webpack_require__(0); + +var BRp = {}; + +BRp.findEdgeControlPoints = function (edges) { + if (!edges || edges.length === 0) { + return; + } + + var r = this; + var cy = r.cy; + var hasCompounds = cy.hasCompoundNodes(); + var hashTable = {}; + var pairIds = []; + var haystackEdges = []; + + // create a table of edge (src, tgt) => list of edges between them + var pairId; + for (var i = 0; i < edges.length; i++) { + var edge = edges[i]; + var _p = edge._private; + var data = _p.data; + var curveStyle = edge.pstyle('curve-style').value; + var edgeIsUnbundled = curveStyle === 'unbundled-bezier' || curveStyle === 'segments'; + var edgeIsBezier = curveStyle === 'unbundled-bezier' || curveStyle === 'bezier'; + + // ignore edges who are not to be displayed + // they shouldn't take up space + if (edge.pstyle('display').value === 'none') { + continue; + } + + if (curveStyle === 'haystack') { + haystackEdges.push(edge); + continue; + } + + var srcId = data.source; + var tgtId = data.target; + + pairId = srcId > tgtId ? tgtId + '$-$' + srcId : srcId + '$-$' + tgtId; + + if (edgeIsUnbundled) { + pairId = 'unbundled' + '$-$' + data.id; + } + + var tableEntry = hashTable[pairId]; + + if (tableEntry == null) { + tableEntry = hashTable[pairId] = []; + pairIds.push(pairId); + } + + tableEntry.push(edge); + + if (edgeIsUnbundled) { + tableEntry.hasUnbundled = true; + } + + if (edgeIsBezier) { + tableEntry.hasBezier = true; + } + } + + var src, tgt, srcPos, tgtPos, srcW, srcH, tgtW, tgtH, srcShape, tgtShape; + var vectorNormInverse; + var badBezier; + + // for each pair (src, tgt), create the ctrl pts + // Nested for loop is OK; total number of iterations for both loops = edgeCount + for (var p = 0; p < pairIds.length; p++) { + pairId = pairIds[p]; + var pairEdges = hashTable[pairId]; + + // for each pair id, the edges should be sorted by index + pairEdges.sort(function (edge1, edge2) { + return edge1.poolIndex() - edge2.poolIndex(); + }); + + src = pairEdges[0]._private.source; + tgt = pairEdges[0]._private.target; + + // make sure src/tgt distinction is consistent for bundled edges + if (!pairEdges.hasUnbundled && src.id() > tgt.id()) { + var temp = src; + src = tgt; + tgt = temp; + } + + srcPos = src.position(); + tgtPos = tgt.position(); + + srcW = src.outerWidth(); + srcH = src.outerHeight(); + + tgtW = tgt.outerWidth(); + tgtH = tgt.outerHeight(); + + srcShape = r.nodeShapes[this.getNodeShape(src)]; + tgtShape = r.nodeShapes[this.getNodeShape(tgt)]; + + badBezier = false; + + var edge; + var edge_p; + var rs; + + var dirCounts = { + 'north': 0, + 'west': 0, + 'south': 0, + 'east': 0, + 'northwest': 0, + 'southwest': 0, + 'northeast': 0, + 'southeast': 0 + }; + + var srcX2 = srcPos.x; + var srcY2 = srcPos.y; + var srcW2 = srcW; + var srcH2 = srcH; + + var tgtX2 = tgtPos.x; + var tgtY2 = tgtPos.y; + var tgtW2 = tgtW; + var tgtH2 = tgtH; + + var numEdges2 = pairEdges.length; + + for (var i = 0; i < pairEdges.length; i++) { + edge = pairEdges[i]; + edge_p = edge._private; + rs = edge_p.rscratch; + + var edgeIndex1 = rs.lastEdgeIndex; + var edgeIndex2 = i; + + var numEdges1 = rs.lastNumEdges; + + var curveStyle = edge.pstyle('curve-style').value; + + var edgeIsUnbundled = curveStyle === 'unbundled-bezier' || curveStyle === 'segments'; + + // whether the normalised pair order is the reverse of the edge's src-tgt order + var edgeIsSwapped = src.id() !== edge.source().id(); + + var ctrlptDists = edge.pstyle('control-point-distances'); + var loopDir = edge.pstyle('loop-direction').pfValue; + var loopSwp = edge.pstyle('loop-sweep').pfValue; + var ctrlptWs = edge.pstyle('control-point-weights'); + var bezierN = ctrlptDists && ctrlptWs ? Math.min(ctrlptDists.value.length, ctrlptWs.value.length) : 1; + var stepSize = edge.pstyle('control-point-step-size').pfValue; + var ctrlptDist = ctrlptDists ? ctrlptDists.pfValue[0] : undefined; + var ctrlptWeight = ctrlptWs.value[0]; + var edgeDistances = edge.pstyle('edge-distances').value; + var srcDistFNode = edge.pstyle('source-distance-from-node').pfValue; + var tgtDistFNode = edge.pstyle('target-distance-from-node').pfValue; + var segmentWs = edge.pstyle('segment-weights'); + var segmentDs = edge.pstyle('segment-distances'); + var segmentsN = Math.min(segmentWs.pfValue.length, segmentDs.pfValue.length); + var srcEndpt = edge.pstyle('source-endpoint').value; + var tgtEndpt = edge.pstyle('target-endpoint').value; + var srcArrShape = edge.pstyle('source-arrow-shape').value; + var tgtArrShape = edge.pstyle('target-arrow-shape').value; + var arrowScale = edge.pstyle('arrow-scale').value; + var lineWidth = edge.pstyle('width').pfValue; + + var srcX1 = rs.lastSrcCtlPtX; + var srcY1 = rs.lastSrcCtlPtY; + var srcW1 = rs.lastSrcCtlPtW; + var srcH1 = rs.lastSrcCtlPtH; + + var tgtX1 = rs.lastTgtCtlPtX; + var tgtY1 = rs.lastTgtCtlPtY; + var tgtW1 = rs.lastTgtCtlPtW; + var tgtH1 = rs.lastTgtCtlPtH; + + var curveStyle1 = rs.lastCurveStyle; + var curveStyle2 = curveStyle; + + var ctrlptDists1 = rs.lastCtrlptDists; + var ctrlptDists2 = ctrlptDists ? ctrlptDists.strValue : null; + + var ctrlptWs1 = rs.lastCtrlptWs; + var ctrlptWs2 = ctrlptWs.strValue; + + var segmentWs1 = rs.lastSegmentWs; + var segmentWs2 = segmentWs.strValue; + + var segmentDs1 = rs.lastSegmentDs; + var segmentDs2 = segmentDs.strValue; + + var stepSize1 = rs.lastStepSize; + var stepSize2 = stepSize; + + var loopDir1 = rs.lastLoopDir; + var loopDir2 = loopDir; + + var loopSwp1 = rs.lastLoopSwp; + var loopSwp2 = loopSwp; + + var edgeDistances1 = rs.lastEdgeDistances; + var edgeDistances2 = edgeDistances; + + var srcDistFNode1 = rs.lastSrcDistFNode; + var srcDistFNode2 = srcDistFNode; + + var tgtDistFNode1 = rs.lastTgtDistFNode; + var tgtDistFNode2 = tgtDistFNode; + + var srcEndpt1 = rs.lastSrcEndpt; + var srcEndpt2 = srcEndpt; + + var tgtEndpt1 = rs.lastTgtEndpt; + var tgtEndpt2 = tgtEndpt; + + var srcArr1 = rs.lastSrcArr; + var srcArr2 = srcArrShape; + + var tgtArr1 = rs.lastTgtArr; + var tgtArr2 = tgtArrShape; + + var lineW1 = rs.lastLineW; + var lineW2 = lineWidth; + + var arrScl1 = rs.lastArrScl; + var arrScl2 = arrowScale; + + if (badBezier) { + rs.badBezier = true; + } else { + rs.badBezier = false; + } + + var ptCacheHit; + + if (srcX1 === srcX2 && srcY1 === srcY2 && srcW1 === srcW2 && srcH1 === srcH2 && tgtX1 === tgtX2 && tgtY1 === tgtY2 && tgtW1 === tgtW2 && tgtH1 === tgtH2 && curveStyle1 === curveStyle2 && ctrlptDists1 === ctrlptDists2 && ctrlptWs1 === ctrlptWs2 && segmentWs1 === segmentWs2 && segmentDs1 === segmentDs2 && stepSize1 === stepSize2 && loopDir1 === loopDir2 && loopSwp1 === loopSwp2 && edgeDistances1 === edgeDistances2 && srcDistFNode1 === srcDistFNode2 && tgtDistFNode1 === tgtDistFNode2 && srcEndpt1 === srcEndpt2 && tgtEndpt1 === tgtEndpt2 && srcArr1 === srcArr2 && tgtArr1 === tgtArr2 && lineW1 === lineW2 && arrScl1 === arrScl2 && (edgeIndex1 === edgeIndex2 && numEdges1 === numEdges2 || edgeIsUnbundled)) { + ptCacheHit = true; // then the control points haven't changed and we can skip calculating them + } else { + ptCacheHit = false; + + rs.lastSrcCtlPtX = srcX2; + rs.lastSrcCtlPtY = srcY2; + rs.lastSrcCtlPtW = srcW2; + rs.lastSrcCtlPtH = srcH2; + rs.lastTgtCtlPtX = tgtX2; + rs.lastTgtCtlPtY = tgtY2; + rs.lastTgtCtlPtW = tgtW2; + rs.lastTgtCtlPtH = tgtH2; + rs.lastEdgeIndex = edgeIndex2; + rs.lastNumEdges = numEdges2; + rs.lastCurveStyle = curveStyle2; + rs.lastCtrlptDists = ctrlptDists2; + rs.lastCtrlptWs = ctrlptWs2; + rs.lastSegmentDs = segmentDs2; + rs.lastSegmentWs = segmentWs2; + rs.lastStepSize = stepSize2; + rs.lastLoopDir = loopDir2; + rs.lastLoopSwp = loopSwp2; + rs.lastEdgeDistances = edgeDistances2; + rs.lastSrcDistFNode = srcDistFNode2; + rs.lastTgtDistFNode = tgtDistFNode2; + rs.lastSrcEndpt = srcEndpt2; + rs.lastTgtEndpt = tgtEndpt2; + rs.lastSrcArr = srcArr2; + rs.lastTgtArr = tgtArr2; + rs.lastLineW = lineW2; + rs.lastArrScl = arrScl2; + } + + if (!ptCacheHit) { + + if (!pairEdges.calculatedIntersection && src !== tgt && (pairEdges.hasBezier || pairEdges.hasUnbundled)) { + + pairEdges.calculatedIntersection = true; + + // pt outside src shape to calc distance/displacement from src to tgt + var srcOutside = srcShape.intersectLine(srcPos.x, srcPos.y, srcW, srcH, tgtPos.x, tgtPos.y, 0); + + pairEdges.srcIntn = srcOutside; + + // pt outside tgt shape to calc distance/displacement from src to tgt + var tgtOutside = tgtShape.intersectLine(tgtPos.x, tgtPos.y, tgtW, tgtH, srcPos.x, srcPos.y, 0); + + pairEdges.tgtIntn = tgtOutside; + + var midptSrcPts = { + x1: srcOutside[0], + x2: tgtOutside[0], + y1: srcOutside[1], + y2: tgtOutside[1] + }; + + var posPts = { + x1: srcPos.x, + x2: tgtPos.x, + y1: srcPos.y, + y2: tgtPos.y + }; + + var dy = tgtOutside[1] - srcOutside[1]; + var dx = tgtOutside[0] - srcOutside[0]; + var l = Math.sqrt(dx * dx + dy * dy); + + var vector = { + x: dx, + y: dy + }; + + var vectorNorm = { + x: vector.x / l, + y: vector.y / l + }; + vectorNormInverse = { + x: -vectorNorm.y, + y: vectorNorm.x + }; + + // if node shapes overlap, then no ctrl pts to draw + if (tgtShape.checkPoint(srcOutside[0], srcOutside[1], 0, tgtW, tgtH, tgtPos.x, tgtPos.y) && srcShape.checkPoint(tgtOutside[0], tgtOutside[1], 0, srcW, srcH, srcPos.x, srcPos.y)) { + vectorNormInverse = {}; + badBezier = true; + } + } + + if (!edgeIsSwapped) { + rs.srcIntn = pairEdges.srcIntn; + rs.tgtIntn = pairEdges.tgtIntn; + } else { + // ensure that the per-edge cached value for intersections are correct for swapped bundled edges + rs.srcIntn = pairEdges.tgtIntn; + rs.tgtIntn = pairEdges.srcIntn; + } + + if (src === tgt) { + // Self-edge + + rs.edgeType = 'self'; + + var j = i; + var loopDist = stepSize; + + if (edgeIsUnbundled) { + j = 0; + loopDist = ctrlptDist; + } + + var loopAngle = loopDir - Math.PI / 2; + var outAngle = loopAngle - loopSwp / 2; + var inAngle = loopAngle + loopSwp / 2; + + // increase by step size for overlapping loops, keyed on direction and sweep values + var dc = String(loopDir + '_' + loopSwp); + j = dirCounts[dc] === undefined ? dirCounts[dc] = 0 : ++dirCounts[dc]; + + rs.ctrlpts = [srcPos.x + Math.cos(outAngle) * 1.4 * loopDist * (j / 3 + 1), srcPos.y + Math.sin(outAngle) * 1.4 * loopDist * (j / 3 + 1), srcPos.x + Math.cos(inAngle) * 1.4 * loopDist * (j / 3 + 1), srcPos.y + Math.sin(inAngle) * 1.4 * loopDist * (j / 3 + 1)]; + } else if (hasCompounds && (src.isParent() || src.isChild() || tgt.isParent() || tgt.isChild()) && (src.parents().anySame(tgt) || tgt.parents().anySame(src))) { + // Compound edge + + rs.edgeType = 'compound'; + + // because the line approximation doesn't apply for compound beziers + // (loop/self edges are already elided b/c of cheap src==tgt check) + rs.badBezier = false; + + var j = i; + var loopDist = stepSize; + + if (edgeIsUnbundled) { + j = 0; + loopDist = ctrlptDist; + } + + var loopW = 50; + + var loopaPos = { + x: srcPos.x - srcW / 2, + y: srcPos.y - srcH / 2 + }; + + var loopbPos = { + x: tgtPos.x - tgtW / 2, + y: tgtPos.y - tgtH / 2 + }; + + var loopPos = { + x: Math.min(loopaPos.x, loopbPos.x), + y: Math.min(loopaPos.y, loopbPos.y) + }; + + // avoids cases with impossible beziers + var minCompoundStretch = 0.5; + var compoundStretchA = Math.max(minCompoundStretch, Math.log(srcW * 0.01)); + var compoundStretchB = Math.max(minCompoundStretch, Math.log(tgtW * 0.01)); + + rs.ctrlpts = [loopPos.x, loopPos.y - (1 + Math.pow(loopW, 1.12) / 100) * loopDist * (j / 3 + 1) * compoundStretchA, loopPos.x - (1 + Math.pow(loopW, 1.12) / 100) * loopDist * (j / 3 + 1) * compoundStretchB, loopPos.y]; + } else if (curveStyle === 'segments') { + // Segments (multiple straight lines) + + rs.edgeType = 'segments'; + rs.segpts = []; + + for (var s = 0; s < segmentsN; s++) { + var w = segmentWs.pfValue[s]; + var d = segmentDs.pfValue[s]; + + var w1 = 1 - w; + var w2 = w; + + var midptPts = edgeDistances === 'node-position' ? posPts : midptSrcPts; + + var adjustedMidpt = { + x: midptPts.x1 * w1 + midptPts.x2 * w2, + y: midptPts.y1 * w1 + midptPts.y2 * w2 + }; + + rs.segpts.push(adjustedMidpt.x + vectorNormInverse.x * d, adjustedMidpt.y + vectorNormInverse.y * d); + } + + // Straight edge + } else if (pairEdges.length % 2 === 1 && i === Math.floor(pairEdges.length / 2) && !edgeIsUnbundled) { + + rs.edgeType = 'straight'; + } else { + // (Multi)bezier + + var multi = edgeIsUnbundled; + + rs.edgeType = multi ? 'multibezier' : 'bezier'; + rs.ctrlpts = []; + + for (var b = 0; b < bezierN; b++) { + var normctrlptDist = (0.5 - pairEdges.length / 2 + i) * stepSize; + var manctrlptDist; + var sign = math.signum(normctrlptDist); + + if (multi) { + ctrlptDist = ctrlptDists ? ctrlptDists.pfValue[b] : stepSize; // fall back on step size + ctrlptWeight = ctrlptWs.value[b]; + } + + if (edgeIsUnbundled) { + // multi or single unbundled + manctrlptDist = ctrlptDist; + } else { + manctrlptDist = ctrlptDist !== undefined ? sign * ctrlptDist : undefined; + } + + var distanceFromMidpoint = manctrlptDist !== undefined ? manctrlptDist : normctrlptDist; + + var w1 = 1 - ctrlptWeight; + var w2 = ctrlptWeight; + + if (edgeIsSwapped) { + var temp = w1; + w1 = w2; + w2 = temp; + } + + var midptPts = edgeDistances === 'node-position' ? posPts : midptSrcPts; + + var adjustedMidpt = { + x: midptPts.x1 * w1 + midptPts.x2 * w2, + y: midptPts.y1 * w1 + midptPts.y2 * w2 + }; + + rs.ctrlpts.push(adjustedMidpt.x + vectorNormInverse.x * distanceFromMidpoint, adjustedMidpt.y + vectorNormInverse.y * distanceFromMidpoint); + } + } + + // find endpts for edge + this.findEndpoints(edge); + + var badStart = !is.number(rs.startX) || !is.number(rs.startY); + var badAStart = !is.number(rs.arrowStartX) || !is.number(rs.arrowStartY); + var badEnd = !is.number(rs.endX) || !is.number(rs.endY); + var badAEnd = !is.number(rs.arrowEndX) || !is.number(rs.arrowEndY); + + var minCpADistFactor = 3; + var arrowW = this.getArrowWidth(edge.pstyle('width').pfValue, edge.pstyle('arrow-scale').value) * this.arrowShapeWidth; + var minCpADist = minCpADistFactor * arrowW; + + if (rs.edgeType === 'bezier') { + var startACpDist = math.dist({ x: rs.ctrlpts[0], y: rs.ctrlpts[1] }, { x: rs.startX, y: rs.startY }); + var closeStartACp = startACpDist < minCpADist; + var endACpDist = math.dist({ x: rs.ctrlpts[0], y: rs.ctrlpts[1] }, { x: rs.endX, y: rs.endY }); + var closeEndACp = endACpDist < minCpADist; + + var overlapping = false; + + if (badStart || badAStart || closeStartACp) { + overlapping = true; + + // project control point along line from src centre to outside the src shape + // (otherwise intersection will yield nothing) + var cpD = { // delta + x: rs.ctrlpts[0] - srcPos.x, + y: rs.ctrlpts[1] - srcPos.y + }; + var cpL = Math.sqrt(cpD.x * cpD.x + cpD.y * cpD.y); // length of line + var cpM = { // normalised delta + x: cpD.x / cpL, + y: cpD.y / cpL + }; + var radius = Math.max(srcW, srcH); + var cpProj = { // *2 radius guarantees outside shape + x: rs.ctrlpts[0] + cpM.x * 2 * radius, + y: rs.ctrlpts[1] + cpM.y * 2 * radius + }; + + var srcCtrlPtIntn = srcShape.intersectLine(srcPos.x, srcPos.y, srcW, srcH, cpProj.x, cpProj.y, 0); + + if (closeStartACp) { + rs.ctrlpts[0] = rs.ctrlpts[0] + cpM.x * (minCpADist - startACpDist); + rs.ctrlpts[1] = rs.ctrlpts[1] + cpM.y * (minCpADist - startACpDist); + } else { + rs.ctrlpts[0] = srcCtrlPtIntn[0] + cpM.x * minCpADist; + rs.ctrlpts[1] = srcCtrlPtIntn[1] + cpM.y * minCpADist; + } + } + + if (badEnd || badAEnd || closeEndACp) { + overlapping = true; + + // project control point along line from tgt centre to outside the tgt shape + // (otherwise intersection will yield nothing) + var cpD = { // delta + x: rs.ctrlpts[0] - tgtPos.x, + y: rs.ctrlpts[1] - tgtPos.y + }; + var cpL = Math.sqrt(cpD.x * cpD.x + cpD.y * cpD.y); // length of line + var cpM = { // normalised delta + x: cpD.x / cpL, + y: cpD.y / cpL + }; + var radius = Math.max(srcW, srcH); + var cpProj = { // *2 radius guarantees outside shape + x: rs.ctrlpts[0] + cpM.x * 2 * radius, + y: rs.ctrlpts[1] + cpM.y * 2 * radius + }; + + var tgtCtrlPtIntn = tgtShape.intersectLine(tgtPos.x, tgtPos.y, tgtW, tgtH, cpProj.x, cpProj.y, 0); + + if (closeEndACp) { + rs.ctrlpts[0] = rs.ctrlpts[0] + cpM.x * (minCpADist - endACpDist); + rs.ctrlpts[1] = rs.ctrlpts[1] + cpM.y * (minCpADist - endACpDist); + } else { + rs.ctrlpts[0] = tgtCtrlPtIntn[0] + cpM.x * minCpADist; + rs.ctrlpts[1] = tgtCtrlPtIntn[1] + cpM.y * minCpADist; + } + } + + if (overlapping) { + // recalc endpts + this.findEndpoints(edge); + } + } + + if (rs.edgeType === 'multibezier' || rs.edgeType === 'bezier' || rs.edgeType === 'self' || rs.edgeType === 'compound') { + rs.allpts = []; + + rs.allpts.push(rs.startX, rs.startY); + + for (var b = 0; b + 1 < rs.ctrlpts.length; b += 2) { + // ctrl pt itself + rs.allpts.push(rs.ctrlpts[b], rs.ctrlpts[b + 1]); + + // the midpt between ctrlpts as intermediate destination pts + if (b + 3 < rs.ctrlpts.length) { + rs.allpts.push((rs.ctrlpts[b] + rs.ctrlpts[b + 2]) / 2, (rs.ctrlpts[b + 1] + rs.ctrlpts[b + 3]) / 2); + } + } + + rs.allpts.push(rs.endX, rs.endY); + + var m, mt; + if (rs.ctrlpts.length / 2 % 2 === 0) { + m = rs.allpts.length / 2 - 1; + + rs.midX = rs.allpts[m]; + rs.midY = rs.allpts[m + 1]; + } else { + m = rs.allpts.length / 2 - 3; + mt = 0.5; + + rs.midX = math.qbezierAt(rs.allpts[m], rs.allpts[m + 2], rs.allpts[m + 4], mt); + rs.midY = math.qbezierAt(rs.allpts[m + 1], rs.allpts[m + 3], rs.allpts[m + 5], mt); + } + } else if (rs.edgeType === 'straight') { + // need to calc these after endpts + rs.allpts = [rs.startX, rs.startY, rs.endX, rs.endY]; + + // default midpt for labels etc + rs.midX = (rs.startX + rs.endX + rs.arrowStartX + rs.arrowEndX) / 4; + rs.midY = (rs.startY + rs.endY + rs.arrowStartY + rs.arrowEndY) / 4; + } else if (rs.edgeType === 'segments') { + rs.allpts = []; + rs.allpts.push(rs.startX, rs.startY); + rs.allpts.push.apply(rs.allpts, rs.segpts); + rs.allpts.push(rs.endX, rs.endY); + + if (rs.segpts.length % 4 === 0) { + var i2 = rs.segpts.length / 2; + var i1 = i2 - 2; + + rs.midX = (rs.segpts[i1] + rs.segpts[i2]) / 2; + rs.midY = (rs.segpts[i1 + 1] + rs.segpts[i2 + 1]) / 2; + } else { + var i1 = rs.segpts.length / 2 - 1; + + rs.midX = rs.segpts[i1]; + rs.midY = rs.segpts[i1 + 1]; + } + } + + this.storeEdgeProjections(edge); + this.calculateArrowAngles(edge); + } // if point cache miss + + this.recalculateEdgeLabelProjections(edge); + this.calculateLabelAngles(edge); + } // for pair edges + } // for pair ids + + for (var i = 0; i < haystackEdges.length; i++) { + var edge = haystackEdges[i]; + var _p = edge._private; + var rscratch = _p.rscratch; + var rs = rscratch; + + if (!rscratch.haystack) { + var angle = Math.random() * 2 * Math.PI; + + rscratch.source = { + x: Math.cos(angle), + y: Math.sin(angle) + }; + + var angle = Math.random() * 2 * Math.PI; + + rscratch.target = { + x: Math.cos(angle), + y: Math.sin(angle) + }; + } + + var src = _p.source; + var tgt = _p.target; + var srcPos = src.position(); + var tgtPos = tgt.position(); + var srcW = src.width(); + var tgtW = tgt.width(); + var srcH = src.height(); + var tgtH = tgt.height(); + var radius = edge.pstyle('haystack-radius').value; + var halfRadius = radius / 2; // b/c have to half width/height + + rs.haystackPts = rs.allpts = [rs.source.x * srcW * halfRadius + srcPos.x, rs.source.y * srcH * halfRadius + srcPos.y, rs.target.x * tgtW * halfRadius + tgtPos.x, rs.target.y * tgtH * halfRadius + tgtPos.y]; + + rs.midX = (rs.allpts[0] + rs.allpts[2]) / 2; + rs.midY = (rs.allpts[1] + rs.allpts[3]) / 2; + + // always override as haystack in case set to different type previously + rscratch.edgeType = rscratch.lastCurveStyle = 'haystack'; + rscratch.haystack = true; + + this.storeEdgeProjections(edge); + this.calculateArrowAngles(edge); + this.recalculateEdgeLabelProjections(edge); + this.calculateLabelAngles(edge); + } +}; + +function getPts(pts) { + var retPts = []; + + if (pts == null) { + return; + } + + for (var i = 0; i < pts.length; i += 2) { + var x = pts[i]; + var y = pts[i + 1]; + + retPts.push({ x: x, y: y }); + } + + return retPts; +} + +BRp.getSegmentPoints = function (edge) { + var rs = edge[0]._private.rscratch; + var type = rs.edgeType; + + if (type === 'segments') { + return getPts(rs.segpts); + } +}; + +BRp.getControlPoints = function (edge) { + var rs = edge[0]._private.rscratch; + var type = rs.edgeType; + + if (type === 'bezier' || type === 'multibezier' || type === 'self' || type === 'compound') { + return getPts(rs.ctrlpts); + } +}; + +BRp.getEdgeMidpoint = function (edge) { + var rs = edge[0]._private.rscratch; + + return { + x: rs.midX, + y: rs.midY + }; +}; + +module.exports = BRp; + +/***/ }), +/* 114 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var math = __webpack_require__(2); +var is = __webpack_require__(0); + +var BRp = {}; + +BRp.manualEndptToPx = function (node, prop) { + var r = this; + var npos = node.position(); + var w = node.outerWidth(); + var h = node.outerHeight(); + + if (prop.value.length === 2) { + var p = [prop.pfValue[0], prop.pfValue[1]]; + + if (prop.units[0] === '%') { + p[0] = p[0] * w; + } + + if (prop.units[1] === '%') { + p[1] = p[1] * h; + } + + p[0] += npos.x; + p[1] += npos.y; + + return p; + } else { + var angle = prop.pfValue[0]; + + angle = -Math.PI / 2 + angle; // start at 12 o'clock + + var l = 2 * Math.max(w, h); + + var _p = [npos.x + Math.cos(angle) * l, npos.y + Math.sin(angle) * l]; + + return r.nodeShapes[this.getNodeShape(node)].intersectLine(npos.x, npos.y, w, h, _p[0], _p[1], 0); + } +}; + +BRp.findEndpoints = function (edge) { + var r = this; + var intersect = void 0; + + var source = edge.source()[0]; + var target = edge.target()[0]; + + var srcPos = source.position(); + var tgtPos = target.position(); + + var tgtArShape = edge.pstyle('target-arrow-shape').value; + var srcArShape = edge.pstyle('source-arrow-shape').value; + + var tgtDist = edge.pstyle('target-distance-from-node').pfValue; + var srcDist = edge.pstyle('source-distance-from-node').pfValue; + + var rs = edge._private.rscratch; + + var et = rs.edgeType; + var self = et === 'self' || et === 'compound'; + var bezier = et === 'bezier' || et === 'multibezier' || self; + var multi = et !== 'bezier'; + var lines = et === 'straight' || et === 'segments'; + var segments = et === 'segments'; + var hasEndpts = bezier || multi || lines; + var srcManEndpt = edge.pstyle('source-endpoint'); + var srcManEndptVal = self ? 'outside-to-node' : srcManEndpt.value; + var tgtManEndpt = edge.pstyle('target-endpoint'); + var tgtManEndptVal = self ? 'outside-to-node' : tgtManEndpt.value; + + rs.srcManEndpt = srcManEndpt; + rs.tgtManEndpt = tgtManEndpt; + + var p1 = void 0; // last known point of edge on target side + var p2 = void 0; // last known point of edge on source side + + var p1_i = void 0; // point to intersect with target shape + var p2_i = void 0; // point to intersect with source shape + + if (bezier) { + var cpStart = [rs.ctrlpts[0], rs.ctrlpts[1]]; + var cpEnd = multi ? [rs.ctrlpts[rs.ctrlpts.length - 2], rs.ctrlpts[rs.ctrlpts.length - 1]] : cpStart; + + p1 = cpEnd; + p2 = cpStart; + } else if (lines) { + var srcArrowFromPt = !segments ? [tgtPos.x, tgtPos.y] : rs.segpts.slice(0, 2); + var tgtArrowFromPt = !segments ? [srcPos.x, srcPos.y] : rs.segpts.slice(rs.segpts.length - 2); + + p1 = tgtArrowFromPt; + p2 = srcArrowFromPt; + } + + if (tgtManEndptVal === 'inside-to-node') { + intersect = [tgtPos.x, tgtPos.y]; + } else if (tgtManEndpt.units) { + intersect = this.manualEndptToPx(target, tgtManEndpt); + } else if (tgtManEndptVal === 'outside-to-line') { + intersect = rs.tgtIntn; // use cached value from ctrlpt calc + } else { + if (tgtManEndptVal === 'outside-to-node') { + p1_i = p1; + } else if (tgtManEndptVal === 'outside-to-line') { + p1_i = [srcPos.x, srcPos.y]; + } + + intersect = r.nodeShapes[this.getNodeShape(target)].intersectLine(tgtPos.x, tgtPos.y, target.outerWidth(), target.outerHeight(), p1_i[0], p1_i[1], 0); + } + + var arrowEnd = math.shortenIntersection(intersect, p1, r.arrowShapes[tgtArShape].spacing(edge) + tgtDist); + var edgeEnd = math.shortenIntersection(intersect, p1, r.arrowShapes[tgtArShape].gap(edge) + tgtDist); + + rs.endX = edgeEnd[0]; + rs.endY = edgeEnd[1]; + + rs.arrowEndX = arrowEnd[0]; + rs.arrowEndY = arrowEnd[1]; + + if (srcManEndptVal === 'inside-to-node') { + intersect = [srcPos.x, srcPos.y]; + } else if (srcManEndpt.units) { + intersect = this.manualEndptToPx(source, srcManEndpt); + } else if (srcManEndptVal === 'outside-to-line') { + intersect = rs.srcIntn; // use cached value from ctrlpt calc + } else { + if (srcManEndptVal === 'outside-to-node') { + p2_i = p2; + } else if (srcManEndptVal === 'outside-to-line') { + p2_i = [tgtPos.x, tgtPos.y]; + } + + intersect = r.nodeShapes[this.getNodeShape(source)].intersectLine(srcPos.x, srcPos.y, source.outerWidth(), source.outerHeight(), p2_i[0], p2_i[1], 0); + } + + var arrowStart = math.shortenIntersection(intersect, p2, r.arrowShapes[srcArShape].spacing(edge) + srcDist); + var edgeStart = math.shortenIntersection(intersect, p2, r.arrowShapes[srcArShape].gap(edge) + srcDist); + + rs.startX = edgeStart[0]; + rs.startY = edgeStart[1]; + + rs.arrowStartX = arrowStart[0]; + rs.arrowStartY = arrowStart[1]; + + if (hasEndpts) { + if (!is.number(rs.startX) || !is.number(rs.startY) || !is.number(rs.endX) || !is.number(rs.endY)) { + rs.badLine = true; + } else { + rs.badLine = false; + } + } +}; + +BRp.getSourceEndpoint = function (edge) { + var rs = edge[0]._private.rscratch; + + switch (rs.edgeType) { + case 'haystack': + return { + x: rs.haystackPts[0], + y: rs.haystackPts[1] + }; + default: + return { + x: rs.arrowStartX, + y: rs.arrowStartY + }; + } +}; + +BRp.getTargetEndpoint = function (edge) { + var rs = edge[0]._private.rscratch; + + switch (rs.edgeType) { + case 'haystack': + return { + x: rs.haystackPts[2], + y: rs.haystackPts[3] + }; + default: + return { + x: rs.arrowEndX, + y: rs.arrowEndY + }; + } +}; + +module.exports = BRp; + +/***/ }), +/* 115 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var math = __webpack_require__(2); + +var BRp = {}; + +function pushBezierPts(r, edge, pts) { + var qbezierAt = function qbezierAt(p1, p2, p3, t) { + return math.qbezierAt(p1, p2, p3, t); + }; + var _p = edge._private; + var bpts = _p.rstyle.bezierPts; + + for (var i = 0; i < r.bezierProjPcts.length; i++) { + var p = r.bezierProjPcts[i]; + + bpts.push({ + x: qbezierAt(pts[0], pts[2], pts[4], p), + y: qbezierAt(pts[1], pts[3], pts[5], p) + }); + } +} + +BRp.storeEdgeProjections = function (edge) { + var _p = edge._private; + var rs = _p.rscratch; + var et = rs.edgeType; + + // clear the cached points state + _p.rstyle.bezierPts = null; + _p.rstyle.linePts = null; + _p.rstyle.haystackPts = null; + + if (et === 'multibezier' || et === 'bezier' || et === 'self' || et === 'compound') { + var bpts = _p.rstyle.bezierPts = []; // jshint ignore:line + + for (var i = 0; i + 5 < rs.allpts.length; i += 4) { + pushBezierPts(this, edge, rs.allpts.slice(i, i + 6)); + } + } else if (et === 'segments') { + var lpts = _p.rstyle.linePts = []; + + for (var i = 0; i + 1 < rs.allpts.length; i += 2) { + lpts.push({ + x: rs.allpts[i], + y: rs.allpts[i + 1] + }); + } + } else if (et === 'haystack') { + var hpts = rs.haystackPts; + + _p.rstyle.haystackPts = [{ x: hpts[0], y: hpts[1] }, { x: hpts[2], y: hpts[3] }]; + } + + _p.rstyle.arrowWidth = this.getArrowWidth(edge.pstyle('width').pfValue, edge.pstyle('arrow-scale').value) * this.arrowShapeWidth; +}; + +BRp.recalculateEdgeProjections = function (edges) { + this.findEdgeControlPoints(edges); +}; + +module.exports = BRp; + +/***/ }), +/* 116 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var math = __webpack_require__(2); +var is = __webpack_require__(0); +var util = __webpack_require__(1); + +var BRp = {}; + +BRp.recalculateNodeLabelProjection = function (node) { + var content = node.pstyle('label').strValue; + + if (is.emptyString(content)) { + return; + } + + var textX, textY; + var _p = node._private; + var nodeWidth = node.width(); + var nodeHeight = node.height(); + var padding = node.padding(); + var nodePos = node.position(); + var textHalign = node.pstyle('text-halign').strValue; + var textValign = node.pstyle('text-valign').strValue; + var rs = _p.rscratch; + var rstyle = _p.rstyle; + + switch (textHalign) { + case 'left': + textX = nodePos.x - nodeWidth / 2 - padding; + break; + + case 'right': + textX = nodePos.x + nodeWidth / 2 + padding; + break; + + default: + // e.g. center + textX = nodePos.x; + } + + switch (textValign) { + case 'top': + textY = nodePos.y - nodeHeight / 2 - padding; + break; + + case 'bottom': + textY = nodePos.y + nodeHeight / 2 + padding; + break; + + default: + // e.g. middle + textY = nodePos.y; + } + + rs.labelX = textX; + rs.labelY = textY; + rstyle.labelX = textX; + rstyle.labelY = textY; + + this.applyLabelDimensions(node); +}; + +var lineAngleFromDelta = function lineAngleFromDelta(dx, dy) { + var angle = Math.atan(dy / dx); + + if (dx === 0 && angle < 0) { + angle = angle * -1; + } + + return angle; +}; + +var lineAngle = function lineAngle(p0, p1) { + var dx = p1.x - p0.x; + var dy = p1.y - p0.y; + + return lineAngleFromDelta(dx, dy); +}; + +var bezierAngle = function bezierAngle(p0, p1, p2, t) { + var t0 = math.bound(0, t - 0.001, 1); + var t1 = math.bound(0, t + 0.001, 1); + + var lp0 = math.qbezierPtAt(p0, p1, p2, t0); + var lp1 = math.qbezierPtAt(p0, p1, p2, t1); + + return lineAngle(lp0, lp1); +}; + +BRp.recalculateEdgeLabelProjections = function (edge) { + var p; + var _p = edge._private; + var rs = _p.rscratch; + var r = this; + var content = { + mid: edge.pstyle('label').strValue, + source: edge.pstyle('source-label').strValue, + target: edge.pstyle('target-label').strValue + }; + + if (content.mid || content.source || content.target) { + // then we have to calculate... + } else { + return; // no labels => no calcs + } + + // add center point to style so bounding box calculations can use it + // + p = { + x: rs.midX, + y: rs.midY + }; + + var setRs = function setRs(propName, prefix, value) { + util.setPrefixedProperty(_p.rscratch, propName, prefix, value); + util.setPrefixedProperty(_p.rstyle, propName, prefix, value); + }; + + setRs('labelX', null, p.x); + setRs('labelY', null, p.y); + + var midAngle = lineAngleFromDelta(rs.midDispX, rs.midDispY); + setRs('labelAutoAngle', null, midAngle); + + var createControlPointInfo = function createControlPointInfo() { + if (createControlPointInfo.cache) { + return createControlPointInfo.cache; + } // use cache so only 1x per edge + + var ctrlpts = []; + + // store each ctrlpt info init + for (var i = 0; i + 5 < rs.allpts.length; i += 4) { + var p0 = { x: rs.allpts[i], y: rs.allpts[i + 1] }; + var p1 = { x: rs.allpts[i + 2], y: rs.allpts[i + 3] }; // ctrlpt + var p2 = { x: rs.allpts[i + 4], y: rs.allpts[i + 5] }; + + ctrlpts.push({ + p0: p0, + p1: p1, + p2: p2, + startDist: 0, + length: 0, + segments: [] + }); + } + + var bpts = _p.rstyle.bezierPts; + var nProjs = r.bezierProjPcts.length; + + function addSegment(cp, p0, p1, t0, t1) { + var length = math.dist(p0, p1); + var prevSegment = cp.segments[cp.segments.length - 1]; + var segment = { + p0: p0, + p1: p1, + t0: t0, + t1: t1, + startDist: prevSegment ? prevSegment.startDist + prevSegment.length : 0, + length: length + }; + + cp.segments.push(segment); + + cp.length += length; + } + + // update each ctrlpt with segment info + for (var i = 0; i < ctrlpts.length; i++) { + var cp = ctrlpts[i]; + var prevCp = ctrlpts[i - 1]; + + if (prevCp) { + cp.startDist = prevCp.startDist + prevCp.length; + } + + addSegment(cp, cp.p0, bpts[i * nProjs], 0, r.bezierProjPcts[0]); // first + + for (var j = 0; j < nProjs - 1; j++) { + addSegment(cp, bpts[i * nProjs + j], bpts[i * nProjs + j + 1], r.bezierProjPcts[j], r.bezierProjPcts[j + 1]); + } + + addSegment(cp, bpts[i * nProjs + nProjs - 1], cp.p2, r.bezierProjPcts[nProjs - 1], 1); // last + } + + return createControlPointInfo.cache = ctrlpts; + }; + + var calculateEndProjection = function calculateEndProjection(prefix) { + var angle; + var isSrc = prefix === 'source'; + + if (!content[prefix]) { + return; + } + + var offset = edge.pstyle(prefix + '-text-offset').pfValue; + + switch (rs.edgeType) { + case 'self': + case 'compound': + case 'bezier': + case 'multibezier': + var cps = createControlPointInfo(); + var selected; + var startDist = 0; + var totalDist = 0; + + // find the segment we're on + for (var i = 0; i < cps.length; i++) { + var cp = cps[isSrc ? i : cps.length - 1 - i]; + + for (var j = 0; j < cp.segments.length; j++) { + var seg = cp.segments[isSrc ? j : cp.segments.length - 1 - j]; + var lastSeg = i === cps.length - 1 && j === cp.segments.length - 1; + + startDist = totalDist; + totalDist += seg.length; + + if (totalDist >= offset || lastSeg) { + selected = { cp: cp, segment: seg }; + break; + } + } + + if (selected) { + break; + } + } + + var cp = selected.cp; + var seg = selected.segment; + var tSegment = (offset - startDist) / seg.length; + var segDt = seg.t1 - seg.t0; + var t = isSrc ? seg.t0 + segDt * tSegment : seg.t1 - segDt * tSegment; + + t = math.bound(0, t, 1); + p = math.qbezierPtAt(cp.p0, cp.p1, cp.p2, t); + angle = bezierAngle(cp.p0, cp.p1, cp.p2, t, p); + + break; + + case 'straight': + case 'segments': + case 'haystack': + var d = 0, + di, + d0; + var p0, p1; + var l = rs.allpts.length; + + for (var i = 0; i + 3 < l; i += 2) { + if (isSrc) { + p0 = { x: rs.allpts[i], y: rs.allpts[i + 1] }; + p1 = { x: rs.allpts[i + 2], y: rs.allpts[i + 3] }; + } else { + p0 = { x: rs.allpts[l - 2 - i], y: rs.allpts[l - 1 - i] }; + p1 = { x: rs.allpts[l - 4 - i], y: rs.allpts[l - 3 - i] }; + } + + di = math.dist(p0, p1); + d0 = d; + d += di; + + if (d >= offset) { + break; + } + } + + var pD = offset - d0; + var t = pD / di; + + t = math.bound(0, t, 1); + p = math.lineAt(p0, p1, t); + angle = lineAngle(p0, p1); + + break; + } + + setRs('labelX', prefix, p.x); + setRs('labelY', prefix, p.y); + setRs('labelAutoAngle', prefix, angle); + }; + + calculateEndProjection('source'); + calculateEndProjection('target'); + + this.applyLabelDimensions(edge); +}; + +BRp.applyLabelDimensions = function (ele) { + this.applyPrefixedLabelDimensions(ele); + + if (ele.isEdge()) { + this.applyPrefixedLabelDimensions(ele, 'source'); + this.applyPrefixedLabelDimensions(ele, 'target'); + } +}; + +BRp.applyPrefixedLabelDimensions = function (ele, prefix) { + var _p = ele._private; + + var text = this.getLabelText(ele, prefix); + var labelDims = this.calculateLabelDimensions(ele, text); + + util.setPrefixedProperty(_p.rstyle, 'labelWidth', prefix, labelDims.width); + util.setPrefixedProperty(_p.rscratch, 'labelWidth', prefix, labelDims.width); + + util.setPrefixedProperty(_p.rstyle, 'labelHeight', prefix, labelDims.height); + util.setPrefixedProperty(_p.rscratch, 'labelHeight', prefix, labelDims.height); +}; + +BRp.getLabelText = function (ele, prefix) { + var _p = ele._private; + var pfd = prefix ? prefix + '-' : ''; + var text = ele.pstyle(pfd + 'label').strValue; + var textTransform = ele.pstyle('text-transform').value; + var rscratch = function rscratch(propName, value) { + if (value) { + util.setPrefixedProperty(_p.rscratch, propName, prefix, value); + return value; + } else { + return util.getPrefixedProperty(_p.rscratch, propName, prefix); + } + }; + + // for empty text, skip all processing + if (!text) { + return ''; + } + + if (textTransform == 'none') { + // passthrough + } else if (textTransform == 'uppercase') { + text = text.toUpperCase(); + } else if (textTransform == 'lowercase') { + text = text.toLowerCase(); + } + + var wrapStyle = ele.pstyle('text-wrap').value; + + if (wrapStyle === 'wrap') { + //console.log('wrap'); + + var labelKey = rscratch('labelKey'); + + // save recalc if the label is the same as before + if (labelKey && rscratch('labelWrapKey') === labelKey) { + // console.log('wrap cache hit'); + return rscratch('labelWrapCachedText'); + } + // console.log('wrap cache miss'); + + var lines = text.split('\n'); + var maxW = ele.pstyle('text-max-width').pfValue; + var wrappedLines = []; + + for (var l = 0; l < lines.length; l++) { + var line = lines[l]; + var lineDims = this.calculateLabelDimensions(ele, line, 'line=' + line); + var lineW = lineDims.width; + + if (lineW > maxW) { + // line is too long + var words = line.split(/\s+/); // NB: assume collapsed whitespace into single space + var subline = ''; + + for (var w = 0; w < words.length; w++) { + var word = words[w]; + var testLine = subline.length === 0 ? word : subline + ' ' + word; + var testDims = this.calculateLabelDimensions(ele, testLine, 'testLine=' + testLine); + var testW = testDims.width; + + if (testW <= maxW) { + // word fits on current line + subline += word + ' '; + } else { + // word starts new line + wrappedLines.push(subline); + subline = word + ' '; + } + } + + // if there's remaining text, put it in a wrapped line + if (!subline.match(/^\s+$/)) { + wrappedLines.push(subline); + } + } else { + // line is already short enough + wrappedLines.push(line); + } + } // for + + rscratch('labelWrapCachedLines', wrappedLines); + text = rscratch('labelWrapCachedText', wrappedLines.join('\n')); + rscratch('labelWrapKey', labelKey); + + // console.log(text) + } else if (wrapStyle === 'ellipsis') { + var maxW = ele.pstyle('text-max-width').pfValue; + var ellipsized = ''; + var ellipsis = '\u2026'; + var incLastCh = false; + + for (var i = 0; i < text.length; i++) { + var widthWithNextCh = this.calculateLabelDimensions(ele, ellipsized + text[i] + ellipsis).width; + + if (widthWithNextCh > maxW) { + break; + } + + ellipsized += text[i]; + + if (i === text.length - 1) { + incLastCh = true; + } + } + + if (!incLastCh) { + ellipsized += ellipsis; + } + + return ellipsized; + } // if ellipsize + + return text; +}; + +BRp.calculateLabelDimensions = function (ele, text, extraKey) { var r = this; - var on = function(){ - var args = arguments; + var cacheKey = ele._private.labelStyleKey + '$@$' + text; + + if (extraKey) { + cacheKey += '$@$' + extraKey; + } + + var cache = r.labelDimCache || (r.labelDimCache = {}); + + if (cache[cacheKey]) { + return cache[cacheKey]; + } + + var sizeMult = 1; // increase the scale to increase accuracy w.r.t. zoomed text + var fStyle = ele.pstyle('font-style').strValue; + var size = sizeMult * ele.pstyle('font-size').pfValue + 'px'; + var family = ele.pstyle('font-family').strValue; + var weight = ele.pstyle('font-weight').strValue; + + var div = this.labelCalcDiv; + + if (!div) { + div = this.labelCalcDiv = document.createElement('div'); // eslint-disable-line no-undef + document.body.appendChild(div); // eslint-disable-line no-undef + } + + var ds = div.style; + + // from ele style + ds.fontFamily = family; + ds.fontStyle = fStyle; + ds.fontSize = size; + ds.fontWeight = weight; + + // forced style + ds.position = 'absolute'; + ds.left = '-9999px'; + ds.top = '-9999px'; + ds.zIndex = '-1'; + ds.visibility = 'hidden'; + ds.pointerEvents = 'none'; + ds.padding = '0'; + ds.lineHeight = '1'; + + if (ele.pstyle('text-wrap').value === 'wrap') { + ds.whiteSpace = 'pre'; // so newlines are taken into account + } else { + ds.whiteSpace = 'normal'; + } + + // put label content in div + div.textContent = text; + + cache[cacheKey] = { + width: Math.ceil(div.clientWidth / sizeMult), + height: Math.ceil(div.clientHeight / sizeMult) + }; + + return cache[cacheKey]; +}; + +BRp.calculateLabelAngles = function (ele) { + var _p = ele._private; + var rs = _p.rscratch; + var isEdge = ele.isEdge(); + var rot = ele.pstyle('text-rotation'); + var rotStr = rot.strValue; + + if (rotStr === 'none') { + rs.labelAngle = rs.sourceLabelAngle = rs.targetLabelAngle = 0; + } else if (isEdge && rotStr === 'autorotate') { + rs.labelAngle = rs.labelAutoAngle; + rs.sourceLabelAngle = rs.sourceLabelAutoAngle; + rs.targetLabelAngle = rs.targetLabelAutoAngle; + } else if (rotStr === 'autorotate') { + rs.labelAngle = rs.sourceLabelAngle = rs.targetLabelAngle = 0; + } else { + rs.labelAngle = rs.sourceLabelAngle = rs.targetLabelAngle = rot.pfValue; + } +}; + +module.exports = BRp; + +/***/ }), +/* 117 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var BRp = {}; + +BRp.getNodeShape = function (node) { + var r = this; + var shape = node.pstyle('shape').value; + + if (node.isParent()) { + if (shape === 'rectangle' || shape === 'roundrectangle' || shape === 'cutrectangle' || shape === 'barrel') { + return shape; + } else { + return 'rectangle'; + } + } + + if (shape === 'polygon') { + var points = node.pstyle('shape-polygon-points').value; + + return r.nodeShapes.makePolygon(points).name; + } + + return shape; +}; + +module.exports = BRp; + +/***/ }), +/* 118 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var BRp = {}; + +BRp.registerCalculationListeners = function () { + var cy = this.cy; + var elesToUpdate = cy.collection(); + var r = this; + + var enqueue = function enqueue(eles, e) { + var dirtyStyleCaches = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; + + elesToUpdate.merge(eles); + + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; + var _p = ele._private; + var rstyle = _p.rstyle; + + if (dirtyStyleCaches) { + rstyle.clean = false; + _p.bbCache = null; + } + + var evts = rstyle.dirtyEvents = rstyle.dirtyEvents || { length: 0 }; + + if (!evts[e.type]) { + evts[e.type] = true; + evts.length++; + } + } + }; + + r.binder(cy) + // nodes + + .on('position.* style.* free.* bounds.*', 'node', function onDirtyModNode(e) { + var node = e.target; + + enqueue(node, e); + enqueue(node.connectedEdges(), e); + }).on('add.*', 'node', function onDirtyAddNode(e) { + var ele = e.target; + + enqueue(ele, e); + }).on('background.*', 'node', function onDirtyBgNode(e) { + var ele = e.target; + + enqueue(ele, e, false); + }) + + // edges + + .on('add.* style.*', 'edge', function onDirtyEdge(e) { + var edge = e.target; + + enqueue(edge, e); + enqueue(edge.parallelEdges(), e); + }).on('remove.*', 'edge', function onDirtyRemoveEdge(e) { + var edge = e.target; + var pEdges = edge.parallelEdges(); + + for (var i = 0; i < pEdges.length; i++) { + var pEdge = pEdges[i]; + + if (!pEdge.removed()) { + enqueue(pEdge, e); + } + } + }) + + // manual dirtying + + .on('dirty.*', 'node', function onDirtyEle(e) { + var ele = e.target; + + enqueue(ele, e); + }); + + var updateEleCalcs = function updateEleCalcs(willDraw) { + if (willDraw) { + var fns = r.onUpdateEleCalcsFns; + + if (fns) { + for (var i = 0; i < fns.length; i++) { + var fn = fns[i]; + + fn(willDraw, elesToUpdate); + } + } + + r.recalculateRenderedStyle(elesToUpdate, false); + + for (var i = 0; i < elesToUpdate.length; i++) { + elesToUpdate[i]._private.rstyle.dirtyEvents = null; + } + + elesToUpdate = cy.collection(); + } + }; + + r.beforeRender(updateEleCalcs, r.beforeRenderPriorities.eleCalcs); +}; + +BRp.onUpdateEleCalcs = function (fn) { + var fns = this.onUpdateEleCalcsFns = this.onUpdateEleCalcsFns || []; + + fns.push(fn); +}; + +BRp.recalculateRenderedStyle = function (eles, useCache) { + var edges = []; + var nodes = []; + + // the renderer can't be used for calcs when destroyed, e.g. ele.boundingBox() + if (this.destroyed) { + return; + } + + // use cache by default for perf + if (useCache === undefined) { + useCache = true; + } + + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; + var _p = ele._private; + var rstyle = _p.rstyle; + + // only update if dirty and in graph + if (useCache && rstyle.clean || ele.removed()) { + continue; + } + + // only update if not display: none + if (ele.pstyle('display').value === 'none') { + continue; + } + + if (_p.group === 'nodes') { + nodes.push(ele); + } else { + // edges + edges.push(ele); + } + + rstyle.clean = true; + // rstyle.dirtyEvents = null; + } + + // update node data from projections + for (var i = 0; i < nodes.length; i++) { + var ele = nodes[i]; + var _p = ele._private; + var rstyle = _p.rstyle; + var pos = ele.position(); + + this.recalculateNodeLabelProjection(ele); + + rstyle.nodeX = pos.x; + rstyle.nodeY = pos.y; + rstyle.nodeW = ele.pstyle('width').pfValue; + rstyle.nodeH = ele.pstyle('height').pfValue; + } + + this.recalculateEdgeProjections(edges); + + // update edge data from projections + for (var i = 0; i < edges.length; i++) { + var ele = edges[i]; + var _p = ele._private; + var rstyle = _p.rstyle; + var rs = _p.rscratch; + + this.recalculateEdgeLabelProjections(ele); + + // update rstyle positions + rstyle.srcX = rs.arrowStartX; + rstyle.srcY = rs.arrowStartY; + rstyle.tgtX = rs.arrowEndX; + rstyle.tgtY = rs.arrowEndY; + rstyle.midX = rs.midX; + rstyle.midY = rs.midY; + rstyle.labelAngle = rs.labelAngle; + rstyle.sourceLabelAngle = rs.sourceLabelAngle; + rstyle.targetLabelAngle = rs.targetLabelAngle; + } +}; + +module.exports = BRp; + +/***/ }), +/* 119 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var zIndexSort = __webpack_require__(17); + +var BRp = {}; + +BRp.updateCachedGrabbedEles = function () { + var eles = this.cachedZSortedEles; + + if (!eles) { + // just let this be recalculated on the next z sort tick + return; + } + + eles.drag = []; + eles.nondrag = []; + + var grabTargets = []; + + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; + var rs = ele._private.rscratch; + + if (ele.grabbed() && !ele.isParent()) { + grabTargets.push(ele); + } else if (rs.inDragLayer) { + eles.drag.push(ele); + } else { + eles.nondrag.push(ele); + } + } + + // put the grab target nodes last so it's on top of its neighbourhood + for (var i = 0; i < grabTargets.length; i++) { + var ele = grabTargets[i]; + + eles.drag.push(ele); + } +}; + +BRp.invalidateCachedZSortedEles = function () { + this.cachedZSortedEles = null; +}; + +BRp.getCachedZSortedEles = function (forceRecalc) { + if (forceRecalc || !this.cachedZSortedEles) { + //console.time('cachezorder') + + var eles = this.cy.mutableElements().toArray(); + + eles.sort(zIndexSort); + + eles.interactive = eles.filter(function (ele) { + return ele.interactive(); + }); + + this.cachedZSortedEles = eles; + + this.updateCachedGrabbedEles(); + } else { + eles = this.cachedZSortedEles; + } + + return eles; +}; + +module.exports = BRp; + +/***/ }), +/* 120 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var BRp = {}; + +BRp.getCachedImage = function (url, crossOrigin, onLoad) { + var r = this; + var imageCache = r.imageCache = r.imageCache || {}; + var cache = imageCache[url]; + + if (cache) { + if (!cache.image.complete) { + cache.image.addEventListener('load', onLoad); + } + + return cache.image; + } else { + cache = imageCache[url] = imageCache[url] || {}; + + var image = cache.image = new Image(); // eslint-disable-line no-undef + + image.addEventListener('load', onLoad); + image.addEventListener('error', function () { + image.error = true; + }); + + // #1582 safari doesn't load data uris with crossOrigin properly + // https://bugs.webkit.org/show_bug.cgi?id=123978 + var dataUriPrefix = 'data:'; + var isDataUri = url.substring(0, dataUriPrefix.length).toLowerCase() === dataUriPrefix; + if (!isDataUri) { + image.crossOrigin = crossOrigin; // prevent tainted canvas + } + + image.src = url; + + return image; + } +}; + +module.exports = BRp; + +/***/ }), +/* 121 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var is = __webpack_require__(0); +var util = __webpack_require__(1); +var math = __webpack_require__(2); +var Event = __webpack_require__(16); + +var BRp = {}; + +BRp.registerBinding = function (target, event, handler, useCapture) { + var args = Array.prototype.slice.apply(arguments, [1]); // copy + var b = this.binder(target); + + return b.on.apply(b, args); +}; + +BRp.binder = function (tgt) { + var r = this; + + var tgtIsDom = tgt === window || tgt === document || tgt === document.body || is.domElement(tgt); + + if (r.supportsPassiveEvents == null) { + + // from https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md#feature-detection + var supportsPassive = false; + try { + var opts = Object.defineProperty({}, 'passive', { + get: function get() { + supportsPassive = true; + } + }); + + window.addEventListener('test', null, opts); + } catch (err) {} + + r.supportsPassiveEvents = supportsPassive; + } + + var on = function on(event, handler, useCapture) { + var args = Array.prototype.slice.call(arguments); + + if (tgtIsDom && r.supportsPassiveEvents) { + // replace useCapture w/ opts obj + args[2] = { + capture: useCapture != null ? useCapture : false, + passive: false, + once: false + }; + } r.bindings.push({ target: tgt, args: args }); - ( tgt.addEventListener || tgt.on ).apply( tgt, args ); + (tgt.addEventListener || tgt.on).apply(tgt, args); return this; }; @@ -14300,53 +23450,42 @@ BRp.binder = function( tgt ){ }; }; -BRp.nodeIsDraggable = function( node ){ - return ( - node - && node.isNode() - && !node.locked() - && node.grabbable() - ); +BRp.nodeIsDraggable = function (node) { + return node && node.isNode() && !node.locked() && node.grabbable(); }; -BRp.nodeIsGrabbable = function( node ){ - return ( - this.nodeIsDraggable( node ) - && node.pstyle( 'opacity' ).value !== 0 - && node.pstyle( 'visibility' ).value === 'visible' - && node.pstyle( 'display' ).value === 'element' - ); +BRp.nodeIsGrabbable = function (node) { + return this.nodeIsDraggable(node) && node.interactive(); }; -BRp.load = function(){ +BRp.load = function () { var r = this; - var triggerEvents = function( target, names, e, props ){ - if( target == null ){ + var triggerEvents = function triggerEvents(target, names, e, props) { + if (target == null) { target = r.cy; } - for( var i = 0; i < names.length; i++ ){ - var name = names[ i ]; + for (var i = 0; i < names.length; i++) { + var name = names[i]; - var event = new Event( e, util.extend( { type: name }, props ) ); - target.trigger( event ); + target.emit(util.extend({ originalEvent: e, type: name }, props)); } }; - var isMultSelKeyDown = function( e ){ + var isMultSelKeyDown = function isMultSelKeyDown(e) { return e.shiftKey || e.metaKey || e.ctrlKey; // maybe e.altKey }; - var allowPanningPassthrough = function( down, downs ){ + var allowPanningPassthrough = function allowPanningPassthrough(down, downs) { var allowPassthrough = true; - if( r.cy.hasCompoundNodes() && down && down.isEdge() ){ + if (r.cy.hasCompoundNodes() && down && down.isEdge()) { // a compound node below the edge => no passthrough panning - for( var i = 0; downs && i < downs.length; i++ ){ + for (var i = 0; downs && i < downs.length; i++) { var down = downs[i]; - if( down.isNode() && down.isParent() ){ + if (down.isNode() && down.isParent()) { allowPassthrough = false; break; } @@ -14358,17 +23497,19 @@ BRp.load = function(){ return allowPassthrough; }; - var getDragListIds = function( opts ){ + var getDragListIds = function getDragListIds(opts) { var listHasId; - if( opts.addToList && r.cy.hasCompoundNodes() ){ // only needed for compound graphs - if( !opts.addToList.hasId ){ // build ids lookup if doesn't already exist + if (opts.addToList && r.cy.hasCompoundNodes()) { + // only needed for compound graphs + if (!opts.addToList.hasId) { + // build ids lookup if doesn't already exist opts.addToList.hasId = {}; - for( var i = 0; i < opts.addToList.length; i++ ){ - var ele = opts.addToList[ i ]; + for (var i = 0; i < opts.addToList.length; i++) { + var ele = opts.addToList[i]; - opts.addToList.hasId[ ele.id() ] = true; + opts.addToList.hasId[ele.id()] = true; } } @@ -14378,106 +23519,110 @@ BRp.load = function(){ return listHasId || {}; }; - var setGrabbed = function( ele ){ + var setGrabbed = function setGrabbed(ele) { ele[0]._private.grabbed = true; }; - var setFreed = function( ele ){ + var setFreed = function setFreed(ele) { ele[0]._private.grabbed = false; }; - var setInDragLayer = function( ele ){ + var setInDragLayer = function setInDragLayer(ele) { ele[0]._private.rscratch.inDragLayer = true; }; - var setOutDragLayer = function( ele ){ + var setOutDragLayer = function setOutDragLayer(ele) { ele[0]._private.rscratch.inDragLayer = false; }; - var setGrabTarget = function( ele ){ + var setGrabTarget = function setGrabTarget(ele) { ele[0]._private.rscratch.isGrabTarget = true; }; - var removeGrabTarget = function( ele ){ + var removeGrabTarget = function removeGrabTarget(ele) { ele[0]._private.rscratch.isGrabTarget = false; }; - var addToDragList = function( ele, opts ){ - var listHasId = getDragListIds( opts ); + var addToDragList = function addToDragList(ele, opts) { + var listHasId = getDragListIds(opts); - if( !listHasId[ ele.id() ] ){ - opts.addToList.push( ele ); - listHasId[ ele.id() ] = true; + if (!listHasId[ele.id()]) { + opts.addToList.push(ele); + listHasId[ele.id()] = true; - setGrabbed( ele ); + setGrabbed(ele); } }; // helper function to determine which child nodes and inner edges // of a compound node to be dragged as well as the grabbed and selected nodes - var addDescendantsToDrag = function( node, opts ){ - if( !node.cy().hasCompoundNodes() ){ + var addDescendantsToDrag = function addDescendantsToDrag(node, opts) { + if (!node.cy().hasCompoundNodes()) { return; } - if( opts.inDragLayer == null && opts.addToList == null ){ return; } // nothing to do + if (opts.inDragLayer == null && opts.addToList == null) { + return; + } // nothing to do var innerNodes = node.descendants(); - if( opts.inDragLayer ){ - innerNodes.forEach( setInDragLayer ); - innerNodes.connectedEdges().forEach( setInDragLayer ); + if (opts.inDragLayer) { + innerNodes.forEach(setInDragLayer); + innerNodes.connectedEdges().forEach(setInDragLayer); } - if( opts.addToList ){ - innerNodes.forEach(function( ele ){ - addToDragList( ele, opts ); + if (opts.addToList) { + innerNodes.forEach(function (ele) { + addToDragList(ele, opts); }); } }; // adds the given nodes and its neighbourhood to the drag layer - var addNodesToDrag = function( nodes, opts ){ + var addNodesToDrag = function addNodesToDrag(nodes, opts) { opts = opts || {}; var hasCompoundNodes = nodes.cy().hasCompoundNodes(); - if( opts.inDragLayer ){ - nodes.forEach( setInDragLayer ); + if (opts.inDragLayer) { + nodes.forEach(setInDragLayer); - nodes.neighborhood().stdFilter(function( ele ){ + nodes.neighborhood().stdFilter(function (ele) { return !hasCompoundNodes || ele.isEdge(); - }).forEach( setInDragLayer ); + }).forEach(setInDragLayer); } - if( opts.addToList ){ - nodes.forEach(function( ele ){ - addToDragList( ele, opts ); + if (opts.addToList) { + nodes.forEach(function (ele) { + addToDragList(ele, opts); }); } - addDescendantsToDrag( nodes, opts ); // always add to drag + addDescendantsToDrag(nodes, opts); // always add to drag // also add nodes and edges related to the topmost ancestor - updateAncestorsInDragLayer( nodes, { + updateAncestorsInDragLayer(nodes, { inDragLayer: opts.inDragLayer - } ); + }); r.updateCachedGrabbedEles(); }; var addNodeToDrag = addNodesToDrag; - var freeDraggedElements = function( grabbedEles ){ - if( !grabbedEles ){ return; } + var freeDraggedElements = function freeDraggedElements(grabbedEles) { + if (!grabbedEles) { + return; + } grabbedEles.hasId = {}; // clear the id list // just go over all elements rather than doing a bunch of (possibly expensive) traversals - r.getCachedZSortedEles().forEach(function( ele ){ - setFreed( ele ); - setOutDragLayer( ele ); - removeGrabTarget( ele ); + r.getCachedZSortedEles().forEach(function (ele) { + setFreed(ele); + setOutDragLayer(ele); + removeGrabTarget(ele); }); r.updateCachedGrabbedEles(); @@ -14485,11 +23630,13 @@ BRp.load = function(){ // helper function to determine which ancestor nodes and edges should go // to the drag layer (or should be removed from drag layer). - var updateAncestorsInDragLayer = function( node, opts ){ + var updateAncestorsInDragLayer = function updateAncestorsInDragLayer(node, opts) { - if( opts.inDragLayer == null && opts.addToList == null ){ return; } // nothing to do + if (opts.inDragLayer == null && opts.addToList == null) { + return; + } // nothing to do - if( !node.cy().hasCompoundNodes() ){ + if (!node.cy().hasCompoundNodes()) { return; } @@ -14497,229 +23644,288 @@ BRp.load = function(){ var parent = node.ancestors().orphans(); // no parent node: no nodes to add to the drag layer - if( parent.same( node ) ){ + if (parent.same(node)) { return; } - var nodes = parent.descendants().spawnSelf() - .merge( parent ) - .unmerge( node ) - .unmerge( node.descendants() ) - ; + var nodes = parent.descendants().spawnSelf().merge(parent).unmerge(node).unmerge(node.descendants()); var edges = nodes.connectedEdges(); - if( opts.inDragLayer ){ - edges.forEach( setInDragLayer ); - nodes.forEach( setInDragLayer ); + if (opts.inDragLayer) { + edges.forEach(setInDragLayer); + nodes.forEach(setInDragLayer); } - if( opts.addToList ){ - nodes.forEach(function( ele ){ - addToDragList( ele, opts ); + if (opts.addToList) { + nodes.forEach(function (ele) { + addToDragList(ele, opts); }); } }; + var blurActiveDomElement = function blurActiveDomElement() { + if (document.activeElement != null && document.activeElement.blur != null) { + document.activeElement.blur(); + } + }; + var haveMutationsApi = typeof MutationObserver !== 'undefined'; // watch for when the cy container is removed from the dom - if( haveMutationsApi ){ - r.removeObserver = new MutationObserver( function( mutns ){ // eslint-disable-line no-undef - for( var i = 0; i < mutns.length; i++ ){ - var mutn = mutns[ i ]; + if (haveMutationsApi) { + r.removeObserver = new MutationObserver(function (mutns) { + // eslint-disable-line no-undef + for (var i = 0; i < mutns.length; i++) { + var mutn = mutns[i]; var rNodes = mutn.removedNodes; - if( rNodes ){ for( var j = 0; j < rNodes.length; j++ ){ - var rNode = rNodes[ j ]; + if (rNodes) { + for (var j = 0; j < rNodes.length; j++) { + var rNode = rNodes[j]; - if( rNode === r.container ){ - r.destroy(); - break; + if (rNode === r.container) { + r.destroy(); + break; + } } - } } + } } - } ); + }); - if( r.container.parentNode ){ - r.removeObserver.observe( r.container.parentNode, { childList: true } ); + if (r.container.parentNode) { + r.removeObserver.observe(r.container.parentNode, { childList: true }); } } else { - r.registerBinding( r.container, 'DOMNodeRemoved', function( e ){ + r.registerBinding(r.container, 'DOMNodeRemoved', function (e) { r.destroy(); - } ); + }); } - var onResize = util.debounce( function(){ - r.cy.invalidateSize(); - r.invalidateContainerClientCoordsCache(); + var onResize = util.debounce(function () { + r.cy.resize(); + }, 100); - r.matchCanvasSize( r.container ); - r.redrawHint( 'eles', true ); - r.redrawHint( 'drag', true ); - r.redraw(); - }, 100 ); + if (haveMutationsApi) { + r.styleObserver = new MutationObserver(onResize); // eslint-disable-line no-undef - if( haveMutationsApi ){ - r.styleObserver = new MutationObserver( onResize ); // eslint-disable-line no-undef - - r.styleObserver.observe( r.container, { attributes: true } ); + r.styleObserver.observe(r.container, { attributes: true }); } // auto resize - r.registerBinding( window, 'resize', onResize ); // eslint-disable-line no-undef + r.registerBinding(window, 'resize', onResize); // eslint-disable-line no-undef - var invalCtnrBBOnScroll = function( domEle ){ - r.registerBinding( domEle, 'scroll', function( e ){ - r.invalidateContainerClientCoordsCache(); - } ); + var forEachUp = function forEachUp(domEle, fn) { + while (domEle != null) { + fn(domEle); + + domEle = domEle.parentNode; + } }; - var bbCtnr = r.cy.container(); + var invalidateCoords = function invalidateCoords() { + r.invalidateContainerClientCoordsCache(); + }; - for( ;; ){ - - invalCtnrBBOnScroll( bbCtnr ); - - if( bbCtnr.parentNode ){ - bbCtnr = bbCtnr.parentNode; - } else { - break; - } - - } + forEachUp(r.container, function (domEle) { + r.registerBinding(domEle, 'transitionend', invalidateCoords); + r.registerBinding(domEle, 'animationend', invalidateCoords); + r.registerBinding(domEle, 'scroll', invalidateCoords); + }); // stop right click menu from appearing on cy - r.registerBinding( r.container, 'contextmenu', function( e ){ + r.registerBinding(r.container, 'contextmenu', function (e) { e.preventDefault(); - } ); + }); - var inBoxSelection = function(){ + var inBoxSelection = function inBoxSelection() { return r.selection[4] !== 0; }; + var eventInContainer = function eventInContainer(e) { + // save cycles if mouse events aren't to be captured + var containerPageCoords = r.findContainerClientCoords(); + var x = containerPageCoords[0]; + var y = containerPageCoords[1]; + var width = containerPageCoords[2]; + var height = containerPageCoords[3]; + + var positions = e.touches ? e.touches : [e]; + var atLeastOnePosInside = false; + + for (var i = 0; i < positions.length; i++) { + var p = positions[i]; + + if (x <= p.clientX && p.clientX <= x + width && y <= p.clientY && p.clientY <= y + height) { + atLeastOnePosInside = true; + break; + } + } + + if (!atLeastOnePosInside) { + return false; + } + + var container = r.container; + var target = e.target; + var tParent = target.parentNode; + var containerIsTarget = false; + + while (tParent) { + if (tParent === container) { + containerIsTarget = true; + break; + } + + tParent = tParent.parentNode; + } + + if (!containerIsTarget) { + return false; + } // if target is outisde cy container, then this event is not for us + + return true; + }; + // Primary key - r.registerBinding( r.container, 'mousedown', function mousedownHandler( e ){ + r.registerBinding(r.container, 'mousedown', function mousedownHandler(e) { + if (!eventInContainer(e)) { + return; + } + e.preventDefault(); + + blurActiveDomElement(); + r.hoverData.capture = true; r.hoverData.which = e.which; var cy = r.cy; - var gpos = [ e.clientX, e.clientY ]; - var pos = r.projectIntoViewport( gpos[0], gpos[1] ); + var gpos = [e.clientX, e.clientY]; + var pos = r.projectIntoViewport(gpos[0], gpos[1]); var select = r.selection; - var nears = r.findNearestElements( pos[0], pos[1], true, false ); + var nears = r.findNearestElements(pos[0], pos[1], true, false); var near = nears[0]; var draggedElements = r.dragData.possibleDragElements; r.hoverData.mdownPos = pos; r.hoverData.mdownGPos = gpos; - var checkForTaphold = function(){ + var checkForTaphold = function checkForTaphold() { r.hoverData.tapholdCancelled = false; - clearTimeout( r.hoverData.tapholdTimeout ); + clearTimeout(r.hoverData.tapholdTimeout); - r.hoverData.tapholdTimeout = setTimeout( function(){ + r.hoverData.tapholdTimeout = setTimeout(function () { - if( r.hoverData.tapholdCancelled ){ + if (r.hoverData.tapholdCancelled) { return; } else { var ele = r.hoverData.down; - if( ele ){ - ele.trigger( new Event( e, { + if (ele) { + ele.emit({ + originalEvent: e, type: 'taphold', - cyPosition: { x: pos[0], y: pos[1] } - } ) ); + position: { x: pos[0], y: pos[1] } + }); } else { - cy.trigger( new Event( e, { + cy.emit({ + originalEvent: e, type: 'taphold', - cyPosition: { x: pos[0], y: pos[1] } - } ) ); + position: { x: pos[0], y: pos[1] } + }); } } - - }, r.tapholdDuration ); + }, r.tapholdDuration); }; // Right click button - if( e.which == 3 ){ + if (e.which == 3) { r.hoverData.cxtStarted = true; - var cxtEvt = new Event( e, { + var cxtEvt = { + originalEvent: e, type: 'cxttapstart', - cyPosition: { x: pos[0], y: pos[1] } - } ); + position: { x: pos[0], y: pos[1] } + }; - if( near ){ + if (near) { near.activate(); - near.trigger( cxtEvt ); + near.emit(cxtEvt); r.hoverData.down = near; } else { - cy.trigger( cxtEvt ); + cy.emit(cxtEvt); } - r.hoverData.downTime = (new Date()).getTime(); + r.hoverData.downTime = new Date().getTime(); r.hoverData.cxtDragged = false; - // Primary button - } else if( e.which == 1 ){ + // Primary button + } else if (e.which == 1) { - if( near ){ + if (near) { near.activate(); } // Element dragging { // If something is under the cursor and it is draggable, prepare to grab it - if( near != null ){ + if (near != null) { - if( r.nodeIsGrabbable( near ) ){ + if (r.nodeIsGrabbable(near)) { - var grabEvent = new Event( e, { - type: 'grab', - cyPosition: { x: pos[0], y: pos[1] } - } ); + var makeEvent = function makeEvent(type) { + return { + originalEvent: e, + type: type, + position: { x: pos[0], y: pos[1] } + }; + }; - setGrabTarget( near ); + var triggerGrab = function triggerGrab(ele) { + ele.emit(makeEvent('grab')); + }; - if( !near.selected() ){ + setGrabTarget(near); + + if (!near.selected()) { draggedElements = r.dragData.possibleDragElements = []; - addNodeToDrag( near, { addToList: draggedElements } ); + addNodeToDrag(near, { addToList: draggedElements }); - near.trigger( grabEvent ); + near.emit(makeEvent('grabon')).emit(makeEvent('grab')); + } else { + draggedElements = r.dragData.possibleDragElements = []; - } else if( near.selected() ){ - draggedElements = r.dragData.possibleDragElements = [ ]; + var selectedNodes = cy.$(function (ele) { + return ele.isNode() && ele.selected() && r.nodeIsGrabbable(ele); + }); - var selectedNodes = cy.$( function(){ return this.isNode() && this.selected() && r.nodeIsGrabbable( this ); } ); + addNodesToDrag(selectedNodes, { addToList: draggedElements }); - addNodesToDrag( selectedNodes, { addToList: draggedElements } ); + near.emit(makeEvent('grabon')); - near.trigger( grabEvent ); + selectedNodes.forEach(triggerGrab); } - r.redrawHint( 'eles', true ); - r.redrawHint( 'drag', true ); - + r.redrawHint('eles', true); + r.redrawHint('drag', true); } - } r.hoverData.down = near; r.hoverData.downs = nears; - r.hoverData.downTime = (new Date()).getTime(); + r.hoverData.downTime = new Date().getTime(); } - triggerEvents( near, [ 'mousedown', 'tapstart', 'vmousedown' ], e, { - cyPosition: { x: pos[0], y: pos[1] } - } ); + triggerEvents(near, ['mousedown', 'tapstart', 'vmousedown'], e, { + position: { x: pos[0], y: pos[1] } + }); - if( near == null ){ + if (near == null) { select[4] = 1; r.data.bgActivePosistion = { @@ -14727,301 +23933,286 @@ BRp.load = function(){ y: pos[1] }; - r.redrawHint( 'select', true ); + r.redrawHint('select', true); r.redraw(); - } else if( near.isEdge() ){ + } else if (near.isEdge()) { select[4] = 1; // for future pan } checkForTaphold(); - } // Initialize selection box coordinates select[0] = select[2] = pos[0]; select[1] = select[3] = pos[1]; + }, false); - }, false ); - - r.registerBinding( window, 'mousemove', function mousemoveHandler( e ){ // eslint-disable-line no-undef - var preventDefault = false; + r.registerBinding(window, 'mousemove', function mousemoveHandler(e) { + // eslint-disable-line no-undef var capture = r.hoverData.capture; - // save cycles if mouse events aren't to be captured - if( !capture ){ - var containerPageCoords = r.findContainerClientCoords(); - - if( e.clientX > containerPageCoords[0] && e.clientX < containerPageCoords[0] + r.canvasWidth - && e.clientY > containerPageCoords[1] && e.clientY < containerPageCoords[1] + r.canvasHeight - ){ - // inside container bounds so OK - } else { - return; - } - - var cyContainer = r.container; - var target = e.target; - var tParent = target.parentNode; - var containerIsTarget = false; - - while( tParent ){ - if( tParent === cyContainer ){ - containerIsTarget = true; - break; - } - - tParent = tParent.parentNode; - } - - if( !containerIsTarget ){ return; } // if target is outisde cy container, then this event is not for us + if (!capture && !eventInContainer(e)) { + return; } + var preventDefault = false; var cy = r.cy; var zoom = cy.zoom(); - var gpos = [ e.clientX, e.clientY ]; - var pos = r.projectIntoViewport( gpos[0], gpos[1] ); + var gpos = [e.clientX, e.clientY]; + var pos = r.projectIntoViewport(gpos[0], gpos[1]); var mdownPos = r.hoverData.mdownPos; var mdownGPos = r.hoverData.mdownGPos; var select = r.selection; var near = null; - if( !r.hoverData.draggingEles && !r.hoverData.dragging && !r.hoverData.selecting ){ - near = r.findNearestElement( pos[0], pos[1], true, false ); + if (!r.hoverData.draggingEles && !r.hoverData.dragging && !r.hoverData.selecting) { + near = r.findNearestElement(pos[0], pos[1], true, false); } var last = r.hoverData.last; var down = r.hoverData.down; - var disp = [ pos[0] - select[2], pos[1] - select[3] ]; + var disp = [pos[0] - select[2], pos[1] - select[3]]; var draggedElements = r.dragData.possibleDragElements; var isOverThresholdDrag; - if( mdownGPos ){ + if (mdownGPos) { var dx = gpos[0] - mdownGPos[0]; var dx2 = dx * dx; var dy = gpos[1] - mdownGPos[1]; var dy2 = dy * dy; var dist2 = dx2 + dy2; - isOverThresholdDrag = dist2 >= r.desktopTapThreshold2; + r.hoverData.isOverThresholdDrag = isOverThresholdDrag = dist2 >= r.desktopTapThreshold2; } - var multSelKeyDown = isMultSelKeyDown( e ); + var multSelKeyDown = isMultSelKeyDown(e); if (isOverThresholdDrag) { r.hoverData.tapholdCancelled = true; } - var updateDragDelta = function(){ + var updateDragDelta = function updateDragDelta() { var dragDelta = r.hoverData.dragDelta = r.hoverData.dragDelta || []; - if( dragDelta.length === 0 ){ - dragDelta.push( disp[0] ); - dragDelta.push( disp[1] ); + if (dragDelta.length === 0) { + dragDelta.push(disp[0]); + dragDelta.push(disp[1]); } else { dragDelta[0] += disp[0]; dragDelta[1] += disp[1]; } }; - preventDefault = true; - triggerEvents( near, [ 'mousemove', 'vmousemove', 'tapdrag' ], e, { - cyPosition: { x: pos[0], y: pos[1] } - } ); + triggerEvents(near, ['mousemove', 'vmousemove', 'tapdrag'], e, { + position: { x: pos[0], y: pos[1] } + }); + + var goIntoBoxMode = function goIntoBoxMode() { + r.data.bgActivePosistion = undefined; + + if (!r.hoverData.selecting) { + cy.emit('boxstart'); + } + + select[4] = 1; + r.hoverData.selecting = true; + + r.redrawHint('select', true); + r.redraw(); + }; // trigger context drag if rmouse down - if( r.hoverData.which === 3 ){ + if (r.hoverData.which === 3) { // but only if over threshold - if( isOverThresholdDrag ){ - var cxtEvt = new Event( e, { + if (isOverThresholdDrag) { + var cxtEvt = { + originalEvent: e, type: 'cxtdrag', - cyPosition: { x: pos[0], y: pos[1] } - } ); + position: { x: pos[0], y: pos[1] } + }; - if( down ){ - down.trigger( cxtEvt ); + if (down) { + down.emit(cxtEvt); } else { - cy.trigger( cxtEvt ); + cy.emit(cxtEvt); } r.hoverData.cxtDragged = true; - if( !r.hoverData.cxtOver || near !== r.hoverData.cxtOver ){ + if (!r.hoverData.cxtOver || near !== r.hoverData.cxtOver) { - if( r.hoverData.cxtOver ){ - r.hoverData.cxtOver.trigger( new Event( e, { + if (r.hoverData.cxtOver) { + r.hoverData.cxtOver.emit({ + originalEvent: e, type: 'cxtdragout', - cyPosition: { x: pos[0], y: pos[1] } - } ) ); + position: { x: pos[0], y: pos[1] } + }); } r.hoverData.cxtOver = near; - if( near ){ - near.trigger( new Event( e, { + if (near) { + near.emit({ + originalEvent: e, type: 'cxtdragover', - cyPosition: { x: pos[0], y: pos[1] } - } ) ); + position: { x: pos[0], y: pos[1] } + }); } - } } - // Check if we are drag panning the entire graph - } else if( r.hoverData.dragging ){ + // Check if we are drag panning the entire graph + } else if (r.hoverData.dragging) { preventDefault = true; - if( cy.panningEnabled() && cy.userPanningEnabled() ){ + if (cy.panningEnabled() && cy.userPanningEnabled()) { var deltaP; - if( r.hoverData.justStartedPan ){ + if (r.hoverData.justStartedPan) { var mdPos = r.hoverData.mdownPos; deltaP = { - x: ( pos[0] - mdPos[0] ) * zoom, - y: ( pos[1] - mdPos[1] ) * zoom + x: (pos[0] - mdPos[0]) * zoom, + y: (pos[1] - mdPos[1]) * zoom }; r.hoverData.justStartedPan = false; - } else { deltaP = { x: disp[0] * zoom, y: disp[1] * zoom }; - } - cy.panBy( deltaP ); + cy.panBy(deltaP); r.hoverData.dragged = true; } // Needs reproject due to pan changing viewport - pos = r.projectIntoViewport( e.clientX, e.clientY ); + pos = r.projectIntoViewport(e.clientX, e.clientY); - // Checks primary button down & out of time & mouse not moved much - } else if( - select[4] == 1 && (down == null || down.isEdge()) - ){ + // Checks primary button down & out of time & mouse not moved much + } else if (select[4] == 1 && (down == null || down.isEdge())) { - if( isOverThresholdDrag ){ + if (isOverThresholdDrag) { - if( !r.hoverData.dragging && cy.boxSelectionEnabled() && ( multSelKeyDown || !cy.panningEnabled() || !cy.userPanningEnabled() ) ){ - r.data.bgActivePosistion = undefined; + if (!r.hoverData.dragging && cy.boxSelectionEnabled() && (multSelKeyDown || !cy.panningEnabled() || !cy.userPanningEnabled())) { + goIntoBoxMode(); + } else if (!r.hoverData.selecting && cy.panningEnabled() && cy.userPanningEnabled()) { + var allowPassthrough = allowPanningPassthrough(down, r.hoverData.downs); - if( !r.hoverData.selecting ){ - cy.trigger('boxstart'); - } - - r.hoverData.selecting = true; - - r.redrawHint( 'select', true ); - r.redraw(); - - } else if( !r.hoverData.selecting && cy.panningEnabled() && cy.userPanningEnabled() ){ - var allowPassthrough = allowPanningPassthrough( down, r.hoverData.downs ); - - if( allowPassthrough ){ + if (allowPassthrough) { r.hoverData.dragging = true; r.hoverData.justStartedPan = true; select[4] = 0; - r.data.bgActivePosistion = math.array2point( mdownPos ); + r.data.bgActivePosistion = math.array2point(mdownPos); - r.redrawHint( 'select', true ); + r.redrawHint('select', true); r.redraw(); } } - if( down && down.isEdge() && down.active() ){ down.unactivate(); } - + if (down && down.isEdge() && down.active()) { + down.unactivate(); + } + } + } else { + if (down && down.isEdge() && down.active()) { + down.unactivate(); } - } else { - if( down && down.isEdge() && down.active() ){ down.unactivate(); } + if ((!down || !down.grabbed()) && near != last) { - if( ( !down || !down.grabbed() ) && near != last ){ - - if( last ){ - triggerEvents( last, [ 'mouseout', 'tapdragout' ], e, { - cyPosition: { x: pos[0], y: pos[1] } - } ); + if (last) { + triggerEvents(last, ['mouseout', 'tapdragout'], e, { + position: { x: pos[0], y: pos[1] } + }); } - if( near ){ - triggerEvents( near, [ 'mouseover', 'tapdragover' ], e, { - cyPosition: { x: pos[0], y: pos[1] } - } ); + if (near) { + triggerEvents(near, ['mouseover', 'tapdragover'], e, { + position: { x: pos[0], y: pos[1] } + }); } r.hoverData.last = near; } - if( down && r.nodeIsDraggable( down ) ){ + if (down) { - if( isOverThresholdDrag ){ // then drag + if (isOverThresholdDrag) { + // then we can take action - var justStartedDrag = !r.dragData.didDrag; + if (cy.boxSelectionEnabled() && multSelKeyDown) { + // then selection overrides + if (down && down.grabbed()) { + freeDraggedElements(draggedElements); - if( justStartedDrag ){ - r.redrawHint( 'eles', true ); - } + down.emit('free'); + } - r.dragData.didDrag = true; // indicate that we actually did drag the node + goIntoBoxMode(); + } else if (down && down.grabbed() && r.nodeIsDraggable(down)) { + // drag node + var justStartedDrag = !r.dragData.didDrag; - var toTrigger = []; + if (justStartedDrag) { + r.redrawHint('eles', true); + } - // now, add the elements to the drag layer if not done already - if( !r.hoverData.draggingEles ){ - addNodesToDrag( cy.collection( draggedElements ), { inDragLayer: true } ); - } + r.dragData.didDrag = true; // indicate that we actually did drag the node - for( var i = 0; i < draggedElements.length; i++ ){ - var dEle = draggedElements[ i ]; + var toTrigger = []; - // Locked nodes not draggable, as well as non-visible nodes - if( r.nodeIsDraggable( dEle ) && dEle.grabbed() ){ - var dPos = dEle._private.position; + // now, add the elements to the drag layer if not done already + if (!r.hoverData.draggingEles) { + addNodesToDrag(cy.collection(draggedElements), { inDragLayer: true }); + } - toTrigger.push( dEle ); + for (var i = 0; i < draggedElements.length; i++) { + var dEle = draggedElements[i]; - if( is.number( disp[0] ) && is.number( disp[1] ) ){ - var updatePos = !dEle.isParent(); + // Locked nodes not draggable, as well as non-visible nodes + if (r.nodeIsDraggable(dEle) && dEle.grabbed()) { + var dPos = dEle.position(); - if( updatePos ){ + toTrigger.push(dEle); + + if (is.number(disp[0]) && is.number(disp[1])) { dPos.x += disp[0]; dPos.y += disp[1]; - } - if( justStartedDrag ){ - var dragDelta = r.hoverData.dragDelta; + if (justStartedDrag) { + var dragDelta = r.hoverData.dragDelta; - if( updatePos && dragDelta && is.number( dragDelta[0] ) && is.number( dragDelta[1] ) ){ - dPos.x += dragDelta[0]; - dPos.y += dragDelta[1]; + if (dragDelta && is.number(dragDelta[0]) && is.number(dragDelta[1])) { + dPos.x += dragDelta[0]; + dPos.y += dragDelta[1]; + } } } } - } + + r.hoverData.draggingEles = true; + + var tcol = cy.collection(toTrigger); + + tcol.dirtyCompoundBoundsCache(); + tcol.emit('position drag'); + + r.redrawHint('drag', true); + r.redraw(); } - - r.hoverData.draggingEles = true; - - var tcol = cy.collection( toTrigger ); - - tcol.updateCompoundBounds(); - tcol.trigger( 'position drag' ); - - r.redrawHint( 'drag', true ); - r.redraw(); - - } else { // otherwise save drag delta for when we actually start dragging so the relative grab pos is constant + } else { + // otherwise save drag delta for when we actually start dragging so the relative grab pos is constant updateDragDelta(); } } @@ -15030,27 +24221,30 @@ BRp.load = function(){ preventDefault = true; } - select[2] = pos[0]; select[3] = pos[1]; + select[2] = pos[0];select[3] = pos[1]; - if( preventDefault ){ - if( e.stopPropagation ) e.stopPropagation(); - if( e.preventDefault ) e.preventDefault(); + if (preventDefault) { + if (e.stopPropagation) e.stopPropagation(); + if (e.preventDefault) e.preventDefault(); return false; } - }, false ); + }, false); - r.registerBinding( window, 'mouseup', function mouseupHandler( e ){ // eslint-disable-line no-undef + r.registerBinding(window, 'mouseup', function mouseupHandler(e) { + // eslint-disable-line no-undef var capture = r.hoverData.capture; - if( !capture ){ return; } + if (!capture) { + return; + } r.hoverData.capture = false; - var cy = r.cy; var pos = r.projectIntoViewport( e.clientX, e.clientY ); var select = r.selection; - var near = r.findNearestElement( pos[0], pos[1], true, false ); - var draggedElements = r.dragData.possibleDragElements; var down = r.hoverData.down; - var multSelKeyDown = isMultSelKeyDown( e ); + var cy = r.cy;var pos = r.projectIntoViewport(e.clientX, e.clientY);var select = r.selection; + var near = r.findNearestElement(pos[0], pos[1], true, false); + var draggedElements = r.dragData.possibleDragElements;var down = r.hoverData.down; + var multSelKeyDown = isMultSelKeyDown(e); - if( r.data.bgActivePosistion ){ - r.redrawHint( 'select', true ); + if (r.data.bgActivePosistion) { + r.redrawHint('select', true); r.redraw(); } @@ -15058,250 +24252,255 @@ BRp.load = function(){ r.data.bgActivePosistion = undefined; // not active bg now - if( down ){ + if (down) { down.unactivate(); } - if( r.hoverData.which === 3 ){ - var cxtEvt = new Event( e, { + if (r.hoverData.which === 3) { + var cxtEvt = { + originalEvent: e, type: 'cxttapend', - cyPosition: { x: pos[0], y: pos[1] } - } ); + position: { x: pos[0], y: pos[1] } + }; - if( down ){ - down.trigger( cxtEvt ); + if (down) { + down.emit(cxtEvt); } else { - cy.trigger( cxtEvt ); + cy.emit(cxtEvt); } - if( !r.hoverData.cxtDragged ){ - var cxtTap = new Event( e, { + if (!r.hoverData.cxtDragged) { + var cxtTap = { + originalEvent: e, type: 'cxttap', - cyPosition: { x: pos[0], y: pos[1] } - } ); + position: { x: pos[0], y: pos[1] } + }; - if( down ){ - down.trigger( cxtTap ); + if (down) { + down.emit(cxtTap); } else { - cy.trigger( cxtTap ); + cy.emit(cxtTap); } } r.hoverData.cxtDragged = false; r.hoverData.which = null; - - } else if( r.hoverData.which === 1 ){ + } else if (r.hoverData.which === 1) { // Deselect all elements if nothing is currently under the mouse cursor and we aren't dragging something - if( (down == null) // not mousedown on node - && !r.dragData.didDrag // didn't move the node around - && !r.hoverData.selecting // not box selection - && !r.hoverData.dragged // didn't pan - && !isMultSelKeyDown( e ) - ){ + if (down == null && // not mousedown on node + !r.dragData.didDrag // didn't move the node around + && !r.hoverData.selecting // not box selection + && !r.hoverData.dragged // didn't pan + && !isMultSelKeyDown(e)) { - cy.$( function(){ - return this.selected(); - } ).unselect(); + cy.$(function (ele) { + return ele.selected(); + }).unselect(); - if( draggedElements.length > 0 ){ - r.redrawHint( 'eles', true ); + if (draggedElements.length > 0) { + r.redrawHint('eles', true); } r.dragData.possibleDragElements = draggedElements = []; } - triggerEvents( near, [ 'mouseup', 'tapend', 'vmouseup' ], e, { - cyPosition: { x: pos[0], y: pos[1] } - } ); + triggerEvents(near, ['mouseup', 'tapend', 'vmouseup'], e, { + position: { x: pos[0], y: pos[1] } + }); - if( - !r.dragData.didDrag // didn't move a node around - && !r.hoverData.dragged // didn't pan - && !r.hoverData.selecting // not box selection - ){ - triggerEvents( down, ['click', 'tap', 'vclick'], e, { - cyPosition: { x: pos[0], y: pos[1] } - } ); - } + if (!r.dragData.didDrag // didn't move a node around + && !r.hoverData.dragged // didn't pan + && !r.hoverData.selecting // not box selection + && !r.hoverData.isOverThresholdDrag // didn't move too much + ) { + triggerEvents(down, ['click', 'tap', 'vclick'], e, { + position: { x: pos[0], y: pos[1] } + }); + } // Single selection - if( near == down && !r.dragData.didDrag && !r.hoverData.selecting ){ - if( near != null && near._private.selectable ){ + if (near == down && !r.dragData.didDrag && !r.hoverData.selecting) { + if (near != null && near._private.selectable) { - if( r.hoverData.dragging ){ + if (r.hoverData.dragging) { // if panning, don't change selection state - } else if( cy.selectionType() === 'additive' || multSelKeyDown ){ - if( near.selected() ){ + } else if (cy.selectionType() === 'additive' || multSelKeyDown) { + if (near.selected()) { near.unselect(); } else { near.select(); } } else { - if( !multSelKeyDown ){ - cy.$( ':selected' ).unmerge( near ).unselect(); + if (!multSelKeyDown) { + cy.$(':selected').unmerge(near).unselect(); near.select(); } } - r.redrawHint( 'eles', true ); + r.redrawHint('eles', true); } } - if( r.hoverData.selecting ){ - var box = cy.collection( r.getAllInBox( select[0], select[1], select[2], select[3] ) ); + if (r.hoverData.selecting) { + var box = cy.collection(r.getAllInBox(select[0], select[1], select[2], select[3])); - r.redrawHint( 'select', true ); + r.redrawHint('select', true); - if( box.length > 0 ){ - r.redrawHint( 'eles', true ); + if (box.length > 0) { + r.redrawHint('eles', true); } - cy.trigger('boxend'); + cy.emit('boxend'); - var eleWouldBeSelected = function( ele ){ return ele.selectable() && !ele.selected(); }; + var eleWouldBeSelected = function eleWouldBeSelected(ele) { + return ele.selectable() && !ele.selected(); + }; - if( cy.selectionType() === 'additive' ){ - box - .trigger('box') - .stdFilter( eleWouldBeSelected ) - .select() - .trigger('boxselect') - ; + if (cy.selectionType() === 'additive') { + box.emit('box').stdFilter(eleWouldBeSelected).select().emit('boxselect'); } else { - if( !multSelKeyDown ){ - cy.$( ':selected' ).unmerge( box ).unselect(); + if (!multSelKeyDown) { + cy.$(':selected').unmerge(box).unselect(); } - box - .trigger('box') - .stdFilter( eleWouldBeSelected ) - .select() - .trigger('boxselect') - ; + box.emit('box').stdFilter(eleWouldBeSelected).select().emit('boxselect'); } // always need redraw in case eles unselectable r.redraw(); - } // Cancel drag pan - if( r.hoverData.dragging ){ + if (r.hoverData.dragging) { r.hoverData.dragging = false; - r.redrawHint( 'select', true ); - r.redrawHint( 'eles', true ); + r.redrawHint('select', true); + r.redrawHint('eles', true); r.redraw(); } - if( !select[4] ) { + if (!select[4]) { r.redrawHint('drag', true); r.redrawHint('eles', true); var downWasGrabbed = down && down.grabbed(); - freeDraggedElements( draggedElements ); + freeDraggedElements(draggedElements); - if( downWasGrabbed ){ down.trigger('free'); } + if (downWasGrabbed) { + down.emit('free'); + } } - } // else not right mouse - select[4] = 0; r.hoverData.down = null; + select[4] = 0;r.hoverData.down = null; r.hoverData.cxtStarted = false; r.hoverData.draggingEles = false; r.hoverData.selecting = false; + r.hoverData.isOverThresholdDrag = false; r.dragData.didDrag = false; r.hoverData.dragged = false; r.hoverData.dragDelta = []; r.hoverData.mdownPos = null; r.hoverData.mdownGPos = null; + }, false); - }, false ); + var wheelHandler = function wheelHandler(e) { - var wheelHandler = function( e ){ - - - if( r.scrollingPage ){ return; } // while scrolling, ignore wheel-to-zoom + if (r.scrollingPage) { + return; + } // while scrolling, ignore wheel-to-zoom var cy = r.cy; - var pos = r.projectIntoViewport( e.clientX, e.clientY ); - var rpos = [ pos[0] * cy.zoom() + cy.pan().x, - pos[1] * cy.zoom() + cy.pan().y ]; + var pos = r.projectIntoViewport(e.clientX, e.clientY); + var rpos = [pos[0] * cy.zoom() + cy.pan().x, pos[1] * cy.zoom() + cy.pan().y]; - if( r.hoverData.draggingEles || r.hoverData.dragging || r.hoverData.cxtStarted || inBoxSelection() ){ // if pan dragging or cxt dragging, wheel movements make no zoom + if (r.hoverData.draggingEles || r.hoverData.dragging || r.hoverData.cxtStarted || inBoxSelection()) { + // if pan dragging or cxt dragging, wheel movements make no zoom e.preventDefault(); return; } - if( cy.panningEnabled() && cy.userPanningEnabled() && cy.zoomingEnabled() && cy.userZoomingEnabled() ){ + if (cy.panningEnabled() && cy.userPanningEnabled() && cy.zoomingEnabled() && cy.userZoomingEnabled()) { e.preventDefault(); r.data.wheelZooming = true; - clearTimeout( r.data.wheelTimeout ); - r.data.wheelTimeout = setTimeout( function(){ + clearTimeout(r.data.wheelTimeout); + r.data.wheelTimeout = setTimeout(function () { r.data.wheelZooming = false; - r.redrawHint( 'eles', true ); + r.redrawHint('eles', true); r.redraw(); - }, 150 ); + }, 150); + + var diff; + + if (e.deltaY != null) { + diff = e.deltaY / -250; + } else if (e.wheelDeltaY != null) { + diff = e.wheelDeltaY / 1000; + } else { + diff = e.wheelDelta / 1000; + } - var diff = e.deltaY / -250 || e.wheelDeltaY / 1000 || e.wheelDelta / 1000; diff = diff * r.wheelSensitivity; var needsWheelFix = e.deltaMode === 1; - if( needsWheelFix ){ // fixes slow wheel events on ff/linux and ff/windows + if (needsWheelFix) { + // fixes slow wheel events on ff/linux and ff/windows diff *= 33; } - cy.zoom( { - level: cy.zoom() * Math.pow( 10, diff ), + cy.zoom({ + level: cy.zoom() * Math.pow(10, diff), renderedPosition: { x: rpos[0], y: rpos[1] } - } ); + }); } - }; // Functions to help with whether mouse wheel should trigger zooming // -- - r.registerBinding( r.container, 'wheel', wheelHandler, true ); + r.registerBinding(r.container, 'wheel', wheelHandler, true); // disable nonstandard wheel events // r.registerBinding(r.container, 'mousewheel', wheelHandler, true); // r.registerBinding(r.container, 'DOMMouseScroll', wheelHandler, true); // r.registerBinding(r.container, 'MozMousePixelScroll', wheelHandler, true); // older firefox - r.registerBinding( window, 'scroll', function scrollHandler( e ){ // eslint-disable-line no-undef + r.registerBinding(window, 'scroll', function scrollHandler(e) { + // eslint-disable-line no-undef r.scrollingPage = true; - clearTimeout( r.scrollingPageTimeout ); - r.scrollingPageTimeout = setTimeout( function(){ + clearTimeout(r.scrollingPageTimeout); + r.scrollingPageTimeout = setTimeout(function () { r.scrollingPage = false; - }, 250 ); - }, true ); + }, 250); + }, true); // Functions to help with handling mouseout/mouseover on the Cytoscape container // Handle mouseout on Cytoscape container - r.registerBinding( r.container, 'mouseout', function mouseOutHandler( e ){ - var pos = r.projectIntoViewport( e.clientX, e.clientY ); + r.registerBinding(r.container, 'mouseout', function mouseOutHandler(e) { + var pos = r.projectIntoViewport(e.clientX, e.clientY); - r.cy.trigger( new Event( e, { + r.cy.emit({ + originalEvent: e, type: 'mouseout', - cyPosition: { x: pos[0], y: pos[1] } - } ) ); - }, false ); + position: { x: pos[0], y: pos[1] } + }); + }, false); - r.registerBinding( r.container, 'mouseover', function mouseOverHandler( e ){ - var pos = r.projectIntoViewport( e.clientX, e.clientY ); + r.registerBinding(r.container, 'mouseover', function mouseOverHandler(e) { + var pos = r.projectIntoViewport(e.clientX, e.clientY); - r.cy.trigger( new Event( e, { + r.cy.emit({ + originalEvent: e, type: 'mouseover', - cyPosition: { x: pos[0], y: pos[1] } - } ) ); - }, false ); + position: { x: pos[0], y: pos[1] } + }); + }, false); var f1x1, f1y1, f2x1, f2y1; // starting points for pinch-to-zoom var distance1, distance1Sq; // initial distance between finger 1 and finger 2 for pinch-to-zoom @@ -15310,16 +24509,22 @@ BRp.load = function(){ var containerWidth, containerHeight; var twoFingersStartInside; - var distance = function( x1, y1, x2, y2 ){ - return Math.sqrt( (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) ); + var distance = function distance(x1, y1, x2, y2) { + return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); }; - var distanceSq = function( x1, y1, x2, y2 ){ + var distanceSq = function distanceSq(x1, y1, x2, y2) { return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1); }; var touchstartHandler; - r.registerBinding( r.container, 'touchstart', touchstartHandler = function( e ){ + r.registerBinding(r.container, 'touchstart', touchstartHandler = function touchstartHandler(e) { + if (!eventInContainer(e)) { + return; + } + + blurActiveDomElement(); + r.touchData.capture = true; r.data.bgActivePosistion = undefined; @@ -15327,14 +24532,20 @@ BRp.load = function(){ var now = r.touchData.now; var earlier = r.touchData.earlier; - if( e.touches[0] ){ var pos = r.projectIntoViewport( e.touches[0].clientX, e.touches[0].clientY ); now[0] = pos[0]; now[1] = pos[1]; } - if( e.touches[1] ){ var pos = r.projectIntoViewport( e.touches[1].clientX, e.touches[1].clientY ); now[2] = pos[0]; now[3] = pos[1]; } - if( e.touches[2] ){ var pos = r.projectIntoViewport( e.touches[2].clientX, e.touches[2].clientY ); now[4] = pos[0]; now[5] = pos[1]; } + if (e.touches[0]) { + var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY);now[0] = pos[0];now[1] = pos[1]; + } + if (e.touches[1]) { + var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY);now[2] = pos[0];now[3] = pos[1]; + } + if (e.touches[2]) { + var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY);now[4] = pos[0];now[5] = pos[1]; + } // record starting points for pinch-to-zoom - if( e.touches[1] ){ + if (e.touches[1]) { - freeDraggedElements( r.dragData.touchDragEles ); + freeDraggedElements(r.dragData.touchDragEles); var offsets = r.findContainerClientCoords(); offsetLeft = offsets[0]; @@ -15348,176 +24559,195 @@ BRp.load = function(){ f2x1 = e.touches[1].clientX - offsetLeft; f2y1 = e.touches[1].clientY - offsetTop; - twoFingersStartInside = - 0 <= f1x1 && f1x1 <= containerWidth - && 0 <= f2x1 && f2x1 <= containerWidth - && 0 <= f1y1 && f1y1 <= containerHeight - && 0 <= f2y1 && f2y1 <= containerHeight - ; + twoFingersStartInside = 0 <= f1x1 && f1x1 <= containerWidth && 0 <= f2x1 && f2x1 <= containerWidth && 0 <= f1y1 && f1y1 <= containerHeight && 0 <= f2y1 && f2y1 <= containerHeight; var pan = cy.pan(); var zoom = cy.zoom(); - distance1 = distance( f1x1, f1y1, f2x1, f2y1 ); - distance1Sq = distanceSq( f1x1, f1y1, f2x1, f2y1 ); - center1 = [ (f1x1 + f2x1) / 2, (f1y1 + f2y1) / 2 ]; - modelCenter1 = [ - (center1[0] - pan.x) / zoom, - (center1[1] - pan.y) / zoom - ]; + distance1 = distance(f1x1, f1y1, f2x1, f2y1); + distance1Sq = distanceSq(f1x1, f1y1, f2x1, f2y1); + center1 = [(f1x1 + f2x1) / 2, (f1y1 + f2y1) / 2]; + modelCenter1 = [(center1[0] - pan.x) / zoom, (center1[1] - pan.y) / zoom]; // consider context tap var cxtDistThreshold = 200; var cxtDistThresholdSq = cxtDistThreshold * cxtDistThreshold; - if( distance1Sq < cxtDistThresholdSq && !e.touches[2] ){ + if (distance1Sq < cxtDistThresholdSq && !e.touches[2]) { - var near1 = r.findNearestElement( now[0], now[1], true, true ); - var near2 = r.findNearestElement( now[2], now[3], true, true ); + var near1 = r.findNearestElement(now[0], now[1], true, true); + var near2 = r.findNearestElement(now[2], now[3], true, true); - if( near1 && near1.isNode() ){ - near1.activate().trigger( new Event( e, { + if (near1 && near1.isNode()) { + near1.activate().emit({ + originalEvent: e, type: 'cxttapstart', - cyPosition: { x: now[0], y: now[1] } - } ) ); + position: { x: now[0], y: now[1] } + }); r.touchData.start = near1; - - } else if( near2 && near2.isNode() ){ - near2.activate().trigger( new Event( e, { + } else if (near2 && near2.isNode()) { + near2.activate().emit({ + originalEvent: e, type: 'cxttapstart', - cyPosition: { x: now[0], y: now[1] } - } ) ); + position: { x: now[0], y: now[1] } + }); r.touchData.start = near2; - } else { - cy.trigger( new Event( e, { + cy.emit({ + originalEvent: e, type: 'cxttapstart', - cyPosition: { x: now[0], y: now[1] } - } ) ); - r.touchData.start = null; + position: { x: now[0], y: now[1] } + }); } - if( r.touchData.start ){ r.touchData.start._private.grabbed = false; } + if (r.touchData.start) { + r.touchData.start._private.grabbed = false; + } r.touchData.cxt = true; r.touchData.cxtDragged = false; r.data.bgActivePosistion = undefined; r.redraw(); return; - } - } - if( e.touches[2] ){ + if (e.touches[2]) { // ignore - } else if( e.touches[1] ){ + } else if (e.touches[1]) { // ignore - } else if( e.touches[0] ){ - var nears = r.findNearestElements( now[0], now[1], true, true ); + } else if (e.touches[0]) { + var nears = r.findNearestElements(now[0], now[1], true, true); var near = nears[0]; - if( near != null ){ + if (near != null) { near.activate(); r.touchData.start = near; r.touchData.starts = nears; - if( r.nodeIsGrabbable( near ) ){ + if (r.nodeIsGrabbable(near)) { var draggedEles = r.dragData.touchDragEles = []; + var selectedNodes = null; - r.redrawHint( 'eles', true ); - r.redrawHint( 'drag', true ); + r.redrawHint('eles', true); + r.redrawHint('drag', true); - if( near.selected() ){ + if (near.selected()) { // reset drag elements, since near will be added again - var selectedNodes = cy.$( function(){ - return this.selected() && r.nodeIsGrabbable( this ); - } ); + selectedNodes = cy.$(function (ele) { + return ele.selected() && r.nodeIsGrabbable(ele); + }); - addNodesToDrag( selectedNodes, { addToList: draggedEles } ); + addNodesToDrag(selectedNodes, { addToList: draggedEles }); } else { - addNodeToDrag( near, { addToList: draggedEles } ); + addNodeToDrag(near, { addToList: draggedEles }); } - setGrabTarget( near ); + setGrabTarget(near); - near.trigger( new Event( e, { - type: 'grab', - cyPosition: { x: now[0], y: now[1] } - } ) ); + var makeEvent = function makeEvent(type) { + return { + originalEvent: e, + type: type, + position: { x: now[0], y: now[1] } + }; + }; + + near.emit(makeEvent('grabon')); + + if (selectedNodes) { + selectedNodes.forEach(function (n) { + n.emit(makeEvent('grab')); + }); + } else { + near.emit(makeEvent('grab')); + } } } - triggerEvents( near, [ 'touchstart', 'tapstart', 'vmousedown' ], e, { - cyPosition: { x: now[0], y: now[1] } - } ); + triggerEvents(near, ['touchstart', 'tapstart', 'vmousedown'], e, { + position: { x: now[0], y: now[1] } + }); - if( near == null ){ + if (near == null) { r.data.bgActivePosistion = { x: pos[0], y: pos[1] }; - r.redrawHint( 'select', true ); + r.redrawHint('select', true); r.redraw(); } - // Tap, taphold // ----- - r.touchData.startPosition = []; - for (var i=0; i= 1) { + var sPos = r.touchData.startPosition = []; + + for (var i = 0; i < now.length; i++) { + sPos[i] = earlier[i] = now[i]; + } + + var touch0 = e.touches[0]; + + r.touchData.startGPosition = [touch0.clientX, touch0.clientY]; + } + }, false); var touchmoveHandler; - r.registerBinding(window, 'touchmove', touchmoveHandler = function(e) { // eslint-disable-line no-undef - var select = r.selection; + r.registerBinding(window, 'touchmove', touchmoveHandler = function touchmoveHandler(e) { + // eslint-disable-line no-undef var capture = r.touchData.capture; + + if (!capture && !eventInContainer(e)) { + return; + } + + var select = r.selection; var cy = r.cy; var now = r.touchData.now; var earlier = r.touchData.earlier; var zoom = cy.zoom(); - if( e.touches[0] ){ var pos = r.projectIntoViewport( e.touches[0].clientX, e.touches[0].clientY ); now[0] = pos[0]; now[1] = pos[1]; } - if( e.touches[1] ){ var pos = r.projectIntoViewport( e.touches[1].clientX, e.touches[1].clientY ); now[2] = pos[0]; now[3] = pos[1]; } - if( e.touches[2] ){ var pos = r.projectIntoViewport( e.touches[2].clientX, e.touches[2].clientY ); now[4] = pos[0]; now[5] = pos[1]; } + if (e.touches[0]) { + var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY);now[0] = pos[0];now[1] = pos[1]; + } + if (e.touches[1]) { + var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY);now[2] = pos[0];now[3] = pos[1]; + } + if (e.touches[2]) { + var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY);now[4] = pos[0];now[5] = pos[1]; + } + var startGPos = r.touchData.startGPosition; var isOverThresholdDrag; - if( capture && e.touches[0] ){ - var disp = []; for (var j=0;j= factorThresholdSq || distance2Sq >= distThresholdSq ){ + if (factorSq >= factorThresholdSq || distance2Sq >= distThresholdSq) { r.touchData.cxt = false; - if( r.touchData.start ){ r.touchData.start.unactivate(); r.touchData.start = null; } - r.data.bgActivePosistion = undefined; - r.redrawHint( 'select', true ); - var cxtEvt = new Event( e, { + r.data.bgActivePosistion = undefined; + + r.redrawHint('select', true); + + var cxtEvt = { + originalEvent: e, type: 'cxttapend', - cyPosition: { x: now[0], y: now[1] } - } ); - if( r.touchData.start ){ - r.touchData.start.trigger( cxtEvt ); + position: { x: now[0], y: now[1] } + }; + + if (r.touchData.start) { + r.touchData.start.unactivate().emit(cxtEvt); + + r.touchData.start = null; } else { - cy.trigger( cxtEvt ); + cy.emit(cxtEvt); } } - } // context swipe - if( capture && r.touchData.cxt ){ - var cxtEvt = new Event( e, { + if (capture && r.touchData.cxt) { + var cxtEvt = { + originalEvent: e, type: 'cxtdrag', - cyPosition: { x: now[0], y: now[1] } - } ); + position: { x: now[0], y: now[1] } + }; r.data.bgActivePosistion = undefined; - r.redrawHint( 'select', true ); + r.redrawHint('select', true); - if( r.touchData.start ){ - r.touchData.start.trigger( cxtEvt ); + if (r.touchData.start) { + r.touchData.start.emit(cxtEvt); } else { - cy.trigger( cxtEvt ); + cy.emit(cxtEvt); } - if( r.touchData.start ){ r.touchData.start._private.grabbed = false; } + if (r.touchData.start) { + r.touchData.start._private.grabbed = false; + } r.touchData.cxtDragged = true; - var near = r.findNearestElement( now[0], now[1], true, true ); + var near = r.findNearestElement(now[0], now[1], true, true); - if( !r.touchData.cxtOver || near !== r.touchData.cxtOver ){ + if (!r.touchData.cxtOver || near !== r.touchData.cxtOver) { - if( r.touchData.cxtOver ){ - r.touchData.cxtOver.trigger( new Event( e, { + if (r.touchData.cxtOver) { + r.touchData.cxtOver.emit({ + originalEvent: e, type: 'cxtdragout', - cyPosition: { x: now[0], y: now[1] } - } ) ); + position: { x: now[0], y: now[1] } + }); } r.touchData.cxtOver = near; - if( near ){ - near.trigger( new Event( e, { + if (near) { + near.emit({ + originalEvent: e, type: 'cxtdragover', - cyPosition: { x: now[0], y: now[1] } - } ) ); - + position: { x: now[0], y: now[1] } + }); } - } - // box selection - } else if( capture && e.touches[2] && cy.boxSelectionEnabled() ){ + // box selection + } else if (capture && e.touches[2] && cy.boxSelectionEnabled()) { e.preventDefault(); r.data.bgActivePosistion = undefined; this.lastThreeTouch = +new Date(); - if( !r.touchData.selecting ){ - cy.trigger('boxstart'); + if (!r.touchData.selecting) { + cy.emit('boxstart'); } r.touchData.selecting = true; - r.redrawHint( 'select', true ); + r.redrawHint('select', true); - if( !select || select.length === 0 || select[0] === undefined ){ + if (!select || select.length === 0 || select[0] === undefined) { select[0] = (now[0] + now[2] + now[4]) / 3; select[1] = (now[1] + now[3] + now[5]) / 3; select[2] = (now[0] + now[2] + now[4]) / 3 + 1; @@ -15634,34 +24873,38 @@ BRp.load = function(){ r.redraw(); - // pinch to zoom - } else if( capture && e.touches[1] && cy.zoomingEnabled() && cy.panningEnabled() && cy.userZoomingEnabled() && cy.userPanningEnabled() ){ // two fingers => pinch to zoom + // pinch to zoom + } else if (capture && e.touches[1] && cy.zoomingEnabled() && cy.panningEnabled() && cy.userZoomingEnabled() && cy.userPanningEnabled()) { + // two fingers => pinch to zoom e.preventDefault(); r.data.bgActivePosistion = undefined; - r.redrawHint( 'select', true ); + r.redrawHint('select', true); var draggedEles = r.dragData.touchDragEles; - if( draggedEles ){ - r.redrawHint( 'drag', true ); + if (draggedEles) { + r.redrawHint('drag', true); - for( var i = 0; i < draggedEles.length; i++ ){ - draggedEles[ i ]._private.grabbed = false; - draggedEles[ i ]._private.rscratch.inDragLayer = false; + for (var i = 0; i < draggedEles.length; i++) { + var de_p = draggedEles[i]._private; + + de_p.grabbed = false; + de_p.rscratch.inDragLayer = false; } } // (x2, y2) for fingers 1 and 2 - var f1x2 = e.touches[0].clientX - offsetLeft, f1y2 = e.touches[0].clientY - offsetTop; - var f2x2 = e.touches[1].clientX - offsetLeft, f2y2 = e.touches[1].clientY - offsetTop; + var f1x2 = e.touches[0].clientX - offsetLeft, + f1y2 = e.touches[0].clientY - offsetTop; + var f2x2 = e.touches[1].clientX - offsetLeft, + f2y2 = e.touches[1].clientY - offsetTop; - - var distance2 = distance( f1x2, f1y2, f2x2, f2y2 ); + var distance2 = distance(f1x2, f1y2, f2x2, f2y2); // var distance2Sq = distanceSq( f1x2, f1y2, f2x2, f2y2 ); // var factor = Math.sqrt( distance2Sq ) / Math.sqrt( distance1Sq ); var factor = distance2 / distance1; - if( factor != 1 && twoFingersStartInside ){ + if (twoFingersStartInside) { // delta finger1 var df1x = f1x2 - f1x1; var df1y = f1y2 - f1y1; @@ -15698,25 +24941,22 @@ BRp.load = function(){ }; // remove dragged eles - if( r.touchData.start ){ + if (r.touchData.start && r.touchData.start.active()) { var draggedEles = r.dragData.touchDragEles; - freeDraggedElements( draggedEles ); + freeDraggedElements(draggedEles); - r.redrawHint( 'drag', true ); - r.redrawHint( 'eles', true ); + r.redrawHint('drag', true); + r.redrawHint('eles', true); - r.touchData.start - .trigger( 'free' ) - .unactivate() - ; + r.touchData.start.unactivate().emit('free'); } - cy.viewport( { + cy.viewport({ zoom: zoom2, pan: pan2, cancelOnFailedZoom: true - } ); + }); distance1 = distance2; f1x1 = f1x2; @@ -15728,85 +24968,87 @@ BRp.load = function(){ } // Re-project - if( e.touches[0] ){ var pos = r.projectIntoViewport( e.touches[0].clientX, e.touches[0].clientY ); now[0] = pos[0]; now[1] = pos[1]; } - if( e.touches[1] ){ var pos = r.projectIntoViewport( e.touches[1].clientX, e.touches[1].clientY ); now[2] = pos[0]; now[3] = pos[1]; } - if( e.touches[2] ){ var pos = r.projectIntoViewport( e.touches[2].clientX, e.touches[2].clientY ); now[4] = pos[0]; now[5] = pos[1]; } - - } else if( e.touches[0] ){ + if (e.touches[0]) { + var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY);now[0] = pos[0];now[1] = pos[1]; + } + if (e.touches[1]) { + var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY);now[2] = pos[0];now[3] = pos[1]; + } + if (e.touches[2]) { + var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY);now[4] = pos[0];now[5] = pos[1]; + } + } else if (e.touches[0]) { var start = r.touchData.start; var last = r.touchData.last; var near; - if( !r.hoverData.draggingEles && !r.swipePanning ){ - near = r.findNearestElement( now[0], now[1], true, true ); + if (!r.hoverData.draggingEles && !r.swipePanning) { + near = r.findNearestElement(now[0], now[1], true, true); } - if( capture && start != null ){ + if (capture && start != null) { e.preventDefault(); } // dragging nodes - if( capture && start != null && r.nodeIsDraggable( start ) ){ + if (capture && start != null && r.nodeIsDraggable(start)) { - if( isOverThresholdDrag ){ // then dragging can happen + if (isOverThresholdDrag) { + // then dragging can happen var draggedEles = r.dragData.touchDragEles; var justStartedDrag = !r.dragData.didDrag; - if( justStartedDrag ){ - addNodesToDrag( cy.collection( draggedEles ), { inDragLayer: true } ); + if (justStartedDrag) { + addNodesToDrag(cy.collection(draggedEles), { inDragLayer: true }); } - for( var k = 0; k < draggedEles.length; k++ ){ - var draggedEle = draggedEles[ k ]; + for (var k = 0; k < draggedEles.length; k++) { + var draggedEle = draggedEles[k]; - if( r.nodeIsDraggable( draggedEle ) && draggedEle.grabbed() ){ + if (r.nodeIsDraggable(draggedEle) && draggedEle.grabbed()) { r.dragData.didDrag = true; - var dPos = draggedEle._private.position; - var updatePos = !draggedEle.isParent(); + var dPos = draggedEle.position(); - if( updatePos && is.number( disp[0] ) && is.number( disp[1] ) ){ + if (is.number(disp[0]) && is.number(disp[1])) { dPos.x += disp[0]; dPos.y += disp[1]; } - if( justStartedDrag ){ - r.redrawHint( 'eles', true ); + if (justStartedDrag) { + r.redrawHint('eles', true); var dragDelta = r.touchData.dragDelta; - if( updatePos && dragDelta && is.number( dragDelta[0] ) && is.number( dragDelta[1] ) ){ + if (dragDelta && is.number(dragDelta[0]) && is.number(dragDelta[1])) { dPos.x += dragDelta[0]; dPos.y += dragDelta[1]; } - } } } - var tcol = cy.collection( draggedEles ); + var tcol = cy.collection(draggedEles); - tcol.updateCompoundBounds(); - tcol.trigger( 'position drag' ); + tcol.dirtyCompoundBoundsCache(); + tcol.emit('position drag'); r.hoverData.draggingEles = true; - r.redrawHint( 'drag', true ); + r.redrawHint('drag', true); - if( - r.touchData.startPosition[0] == earlier[0] - && r.touchData.startPosition[1] == earlier[1] - ){ + if (r.touchData.startPosition[0] == earlier[0] && r.touchData.startPosition[1] == earlier[1]) { - r.redrawHint( 'eles', true ); + r.redrawHint('eles', true); } r.redraw(); - } else { // otherise keep track of drag delta for later + } else { + // otherise keep track of drag delta for later var dragDelta = r.touchData.dragDelta = r.touchData.dragDelta || []; - if( dragDelta.length === 0 ){ - dragDelta.push( disp[0] ); - dragDelta.push( disp[1] ); + if (dragDelta.length === 0) { + dragDelta.push(disp[0]); + dragDelta.push(disp[1]); } else { dragDelta[0] += disp[0]; dragDelta[1] += disp[1]; @@ -15816,24 +25058,26 @@ BRp.load = function(){ // touchmove { - triggerEvents( (start || near), [ 'touchmove', 'tapdrag', 'vmousemove' ], e, { - cyPosition: { x: now[0], y: now[1] } - } ); + triggerEvents(start || near, ['touchmove', 'tapdrag', 'vmousemove'], e, { + position: { x: now[0], y: now[1] } + }); - if( ( !start || !start.grabbed() ) && near != last ){ - if( last ){ last.trigger( new Event( e, { type: 'tapdragout', cyPosition: { x: now[0], y: now[1] } } ) ); } - if( near ){ near.trigger( new Event( e, { type: 'tapdragover', cyPosition: { x: now[0], y: now[1] } } ) ); } + if ((!start || !start.grabbed()) && near != last) { + if (last) { + last.emit({ originalEvent: e, type: 'tapdragout', position: { x: now[0], y: now[1] } }); + } + if (near) { + near.emit({ originalEvent: e, type: 'tapdragover', position: { x: now[0], y: now[1] } }); + } } r.touchData.last = near; } // check to cancel taphold - if( capture ){ - for( var i = 0; i < now.length; i++ ){ - if( now[ i ] - && r.touchData.startPosition[ i ] - && isOverThresholdDrag ){ + if (capture) { + for (var i = 0; i < now.length; i++) { + if (now[i] && r.touchData.startPosition[i] && isOverThresholdDrag) { r.touchData.singleTouchMoved = true; } @@ -15841,76 +25085,81 @@ BRp.load = function(){ } // panning - if( - capture - && ( start == null || start.isEdge() ) - && cy.panningEnabled() && cy.userPanningEnabled() - ){ + if (capture && (start == null || start.isEdge()) && cy.panningEnabled() && cy.userPanningEnabled()) { - var allowPassthrough = allowPanningPassthrough( start, r.touchData.starts ); + var allowPassthrough = allowPanningPassthrough(start, r.touchData.starts); - if( allowPassthrough ){ + if (allowPassthrough) { e.preventDefault(); - if( r.swipePanning ){ - cy.panBy( { + if (r.swipePanning) { + cy.panBy({ x: disp[0] * zoom, y: disp[1] * zoom - } ); - - } else if( isOverThresholdDrag ){ + }); + } else if (isOverThresholdDrag) { r.swipePanning = true; - cy.panBy( { + cy.panBy({ x: dx * zoom, y: dy * zoom - } ); + }); - if( start ){ + if (start) { start.unactivate(); - if( !r.data.bgActivePosistion ){ - r.data.bgActivePosistion = math.array2point( r.touchData.startPosition ); + if (!r.data.bgActivePosistion) { + r.data.bgActivePosistion = math.array2point(r.touchData.startPosition); } - r.redrawHint( 'select', true ); + r.redrawHint('select', true); r.touchData.start = null; } } - } // Re-project - var pos = r.projectIntoViewport( e.touches[0].clientX, e.touches[0].clientY ); - now[0] = pos[0]; now[1] = pos[1]; + var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY); + now[0] = pos[0];now[1] = pos[1]; } } - for( var j = 0; j < now.length; j++ ){ earlier[ j ] = now[ j ]; } + for (var j = 0; j < now.length; j++) { + earlier[j] = now[j]; + } //r.redraw(); - }, false ); - + // the active bg indicator should be removed when making a swipe that is neither for dragging nodes or panning + if (capture && e.touches.length > 0 && !r.hoverData.draggingEles && !r.swipePanning && r.data.bgActivePosistion != null) { + r.data.bgActivePosistion = undefined; + r.redrawHint('select', true); + r.redraw(); + } + }, false); var touchcancelHandler; - r.registerBinding( window, 'touchcancel', touchcancelHandler = function( e ){ // eslint-disable-line no-undef + r.registerBinding(window, 'touchcancel', touchcancelHandler = function touchcancelHandler(e) { + // eslint-disable-line no-undef var start = r.touchData.start; r.touchData.capture = false; - if( start ){ + if (start) { start.unactivate(); } - } ); + }); var touchendHandler; - r.registerBinding( window, 'touchend', touchendHandler = function( e ){ // eslint-disable-line no-undef + r.registerBinding(window, 'touchend', touchendHandler = function touchendHandler(e) { + // eslint-disable-line no-undef var start = r.touchData.start; var capture = r.touchData.capture; - if( capture ){ - r.touchData.capture = false; + if (capture) { + if (e.touches.length === 0) { + r.touchData.capture = false; + } e.preventDefault(); } else { @@ -15927,42 +25176,51 @@ BRp.load = function(){ var now = r.touchData.now; var earlier = r.touchData.earlier; - if( e.touches[0] ){ var pos = r.projectIntoViewport( e.touches[0].clientX, e.touches[0].clientY ); now[0] = pos[0]; now[1] = pos[1]; } - if( e.touches[1] ){ var pos = r.projectIntoViewport( e.touches[1].clientX, e.touches[1].clientY ); now[2] = pos[0]; now[3] = pos[1]; } - if( e.touches[2] ){ var pos = r.projectIntoViewport( e.touches[2].clientX, e.touches[2].clientY ); now[4] = pos[0]; now[5] = pos[1]; } + if (e.touches[0]) { + var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY);now[0] = pos[0];now[1] = pos[1]; + } + if (e.touches[1]) { + var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY);now[2] = pos[0];now[3] = pos[1]; + } + if (e.touches[2]) { + var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY);now[4] = pos[0];now[5] = pos[1]; + } - if( start ){ + if (start) { start.unactivate(); } var ctxTapend; - if( r.touchData.cxt ){ - ctxTapend = new Event( e, { + if (r.touchData.cxt) { + ctxTapend = { + originalEvent: e, type: 'cxttapend', - cyPosition: { x: now[0], y: now[1] } - } ); + position: { x: now[0], y: now[1] } + }; - if( start ){ - start.trigger( ctxTapend ); + if (start) { + start.emit(ctxTapend); } else { - cy.trigger( ctxTapend ); + cy.emit(ctxTapend); } - if( !r.touchData.cxtDragged ){ - var ctxTap = new Event( e, { + if (!r.touchData.cxtDragged) { + var ctxTap = { + originalEvent: e, type: 'cxttap', - cyPosition: { x: now[0], y: now[1] } - } ); + position: { x: now[0], y: now[1] } + }; - if( start ){ - start.trigger( ctxTap ); + if (start) { + start.emit(ctxTap); } else { - cy.trigger( ctxTap ); + cy.emit(ctxTap); } - } - if( r.touchData.start ){ r.touchData.start._private.grabbed = false; } + if (r.touchData.start) { + r.touchData.start._private.grabbed = false; + } r.touchData.cxt = false; r.touchData.start = null; @@ -15971,10 +25229,10 @@ BRp.load = function(){ } // no more box selection if we don't have three fingers - if( !e.touches[2] && cy.boxSelectionEnabled() && r.touchData.selecting ){ + if (!e.touches[2] && cy.boxSelectionEnabled() && r.touchData.selecting) { r.touchData.selecting = false; - var box = cy.collection( r.getAllInBox( select[0], select[1], select[2], select[3] ) ); + var box = cy.collection(r.getAllInBox(select[0], select[1], select[2], select[3])); select[0] = undefined; select[1] = undefined; @@ -15982,74 +25240,69 @@ BRp.load = function(){ select[3] = undefined; select[4] = 0; - r.redrawHint( 'select', true ); + r.redrawHint('select', true); - cy.trigger('boxend'); + cy.emit('boxend'); - var eleWouldBeSelected = function( ele ){ return ele.selectable() && !ele.selected(); }; + var eleWouldBeSelected = function eleWouldBeSelected(ele) { + return ele.selectable() && !ele.selected(); + }; - box - .trigger('box') - .stdFilter( eleWouldBeSelected ) - .select() - .trigger('boxselect') - ; + box.emit('box').stdFilter(eleWouldBeSelected).select().emit('boxselect'); - if( box.nonempty() ){ - r.redrawHint( 'eles', true ); + if (box.nonempty()) { + r.redrawHint('eles', true); } r.redraw(); } - if( start != null ){ + if (start != null) { start.unactivate(); } - if( e.touches[2] ){ + if (e.touches[2]) { r.data.bgActivePosistion = undefined; - r.redrawHint( 'select', true ); - } else if( e.touches[1] ){ + r.redrawHint('select', true); + } else if (e.touches[1]) { // ignore - } else if( e.touches[0] ){ + } else if (e.touches[0]) { // ignore - // Last touch released - } else if( !e.touches[0] ){ + // Last touch released + } else if (!e.touches[0]) { r.data.bgActivePosistion = undefined; - r.redrawHint( 'select', true ); + r.redrawHint('select', true); var draggedEles = r.dragData.touchDragEles; - if( start != null ){ + if (start != null) { var startWasGrabbed = start._private.grabbed; - freeDraggedElements( draggedEles ); + freeDraggedElements(draggedEles); - r.redrawHint( 'drag', true ); - r.redrawHint( 'eles', true ); + r.redrawHint('drag', true); + r.redrawHint('eles', true); - if( startWasGrabbed ){ - start.trigger( 'free' ); + if (startWasGrabbed) { + start.emit('free'); } - triggerEvents( start, [ 'touchend', 'tapend', 'vmouseup', 'tapdragout' ], e, { - cyPosition: { x: now[0], y: now[1] } - } ); + triggerEvents(start, ['touchend', 'tapend', 'vmouseup', 'tapdragout'], e, { + position: { x: now[0], y: now[1] } + }); start.unactivate(); r.touchData.start = null; - } else { - var near = r.findNearestElement( now[0], now[1], true, true ); - - triggerEvents( near, [ 'touchend', 'tapend', 'vmouseup', 'tapdragout' ], e, { - cyPosition: { x: now[0], y: now[1] } - } ); + var near = r.findNearestElement(now[0], now[1], true, true); + triggerEvents(near, ['touchend', 'tapend', 'vmouseup', 'tapdragout'], e, { + position: { x: now[0], y: now[1] } + }); } var dx = r.touchData.startPosition[0] - now[0]; @@ -16060,63 +25313,61 @@ BRp.load = function(){ var rdist2 = dist2 * zoom * zoom; // Prepare to select the currently touched node, only if it hasn't been dragged past a certain distance - if( start != null - && !r.dragData.didDrag // didn't drag nodes around - && start._private.selectable - && rdist2 < r.touchTapThreshold2 - && !r.pinching // pinch to zoom should not affect selection - ){ + if (start != null && !r.dragData.didDrag // didn't drag nodes around + && start._private.selectable && rdist2 < r.touchTapThreshold2 && !r.pinching // pinch to zoom should not affect selection + ) { - if( cy.selectionType() === 'single' ){ - cy.$( ':selected' ).unmerge( start ).unselect(); - start.select(); - } else { - if( start.selected() ){ - start.unselect(); - } else { + if (cy.selectionType() === 'single') { + cy.$(':selected').unmerge(start).unselect(); start.select(); + } else { + if (start.selected()) { + start.unselect(); + } else { + start.select(); + } } + + r.redrawHint('eles', true); } - r.redrawHint( 'eles', true ); - } - // Tap event, roughly same as mouse click event for touch - if( !r.touchData.singleTouchMoved ){ - triggerEvents( start, [ 'tap', 'vclick' ], e, { - cyPosition: { x: now[0], y: now[1] } - } ); + if (!r.touchData.singleTouchMoved) { + triggerEvents(start, ['tap', 'vclick'], e, { + position: { x: now[0], y: now[1] } + }); } r.touchData.singleTouchMoved = true; } - for( var j = 0; j < now.length; j++ ){ earlier[ j ] = now[ j ]; } + for (var j = 0; j < now.length; j++) { + earlier[j] = now[j]; + } r.dragData.didDrag = false; // reset for next mousedown - if( e.touches.length === 0 ){ + if (e.touches.length === 0) { r.touchData.dragDelta = []; r.touchData.startPosition = null; r.touchData.startGPosition = null; } - if( e.touches.length < 2 ){ + if (e.touches.length < 2) { r.pinching = false; - r.redrawHint( 'eles', true ); + r.redrawHint('eles', true); r.redraw(); } //r.redraw(); - - }, false ); + }, false); // fallback compatibility layer for ms pointer events - if( typeof TouchEvent === 'undefined' ){ + if (typeof TouchEvent === 'undefined') { var pointers = []; - var makeTouch = function( e ){ + var makeTouch = function makeTouch(e) { return { clientX: e.clientX, clientY: e.clientY, @@ -16132,364 +25383,595 @@ BRp.load = function(){ }; }; - var makePointer = function( e ){ + var makePointer = function makePointer(e) { return { event: e, - touch: makeTouch( e ) + touch: makeTouch(e) }; }; - var addPointer = function( e ){ - pointers.push( makePointer( e ) ); + var addPointer = function addPointer(e) { + pointers.push(makePointer(e)); }; - var removePointer = function( e ){ - for( var i = 0; i < pointers.length; i++ ){ - var p = pointers[ i ]; + var removePointer = function removePointer(e) { + for (var i = 0; i < pointers.length; i++) { + var p = pointers[i]; - if( p.event.pointerId === e.pointerId ){ - pointers.splice( i, 1 ); + if (p.event.pointerId === e.pointerId) { + pointers.splice(i, 1); return; } } }; - var updatePointer = function( e ){ - var p = pointers.filter( function( p ){ + var updatePointer = function updatePointer(e) { + var p = pointers.filter(function (p) { return p.event.pointerId === e.pointerId; - } )[0]; + })[0]; p.event = e; - p.touch = makeTouch( e ); + p.touch = makeTouch(e); }; - var addTouchesToEvent = function( e ){ - e.touches = pointers.map( function( p ){ + var addTouchesToEvent = function addTouchesToEvent(e) { + e.touches = pointers.map(function (p) { return p.touch; - } ); + }); }; - r.registerBinding( r.container, 'pointerdown', function( e ){ - if( e.pointerType === 'mouse' ){ return; } // mouse already handled + var pointerIsMouse = function pointerIsMouse(e) { + return e.pointerType === 'mouse' || e.pointerType === 4; + }; + + r.registerBinding(r.container, 'pointerdown', function (e) { + if (pointerIsMouse(e)) { + return; + } // mouse already handled e.preventDefault(); - addPointer( e ); + addPointer(e); - addTouchesToEvent( e ); - touchstartHandler( e ); - } ); + addTouchesToEvent(e); + touchstartHandler(e); + }); - r.registerBinding( r.container, 'pointerup', function( e ){ - if( e.pointerType === 'mouse' ){ return; } // mouse already handled + r.registerBinding(r.container, 'pointerup', function (e) { + if (pointerIsMouse(e)) { + return; + } // mouse already handled - removePointer( e ); + removePointer(e); - addTouchesToEvent( e ); - touchendHandler( e ); - } ); + addTouchesToEvent(e); + touchendHandler(e); + }); - r.registerBinding( r.container, 'pointercancel', function( e ){ - if( e.pointerType === 'mouse' ){ return; } // mouse already handled + r.registerBinding(r.container, 'pointercancel', function (e) { + if (pointerIsMouse(e)) { + return; + } // mouse already handled - removePointer( e ); + removePointer(e); - addTouchesToEvent( e ); - touchcancelHandler( e ); - } ); + addTouchesToEvent(e); + touchcancelHandler(e); + }); - r.registerBinding( r.container, 'pointermove', function( e ){ - if( e.pointerType === 'mouse' ){ return; } // mouse already handled + r.registerBinding(r.container, 'pointermove', function (e) { + if (pointerIsMouse(e)) { + return; + } // mouse already handled e.preventDefault(); - updatePointer( e ); - - addTouchesToEvent( e ); - touchmoveHandler( e ); - } ); + updatePointer(e); + addTouchesToEvent(e); + touchmoveHandler(e); + }); } }; module.exports = BRp; -},{"../../../event":45,"../../../is":83,"../../../math":85,"../../../util":100}],62:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 122 */ +/***/ (function(module, exports, __webpack_require__) { -var math = _dereq_( '../../../math' ); +"use strict"; + + +var math = __webpack_require__(2); var BRp = {}; -BRp.generatePolygon = function( name, points ){ - return ( this.nodeShapes[ name ] = { +BRp.generatePolygon = function (name, points) { + return this.nodeShapes[name] = { renderer: this, name: name, points: points, - draw: function( context, centerX, centerY, width, height ){ - this.renderer.nodeShapeImpl( 'polygon', context, centerX, centerY, width, height, this.points ); + draw: function draw(context, centerX, centerY, width, height) { + this.renderer.nodeShapeImpl('polygon', context, centerX, centerY, width, height, this.points); }, - intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){ - return math.polygonIntersectLine( - x, y, - this.points, - nodeX, - nodeY, - width / 2, height / 2, - padding ) - ; + intersectLine: function intersectLine(nodeX, nodeY, width, height, x, y, padding) { + return math.polygonIntersectLine(x, y, this.points, nodeX, nodeY, width / 2, height / 2, padding); }, - checkPoint: function( x, y, padding, width, height, centerX, centerY ){ - return math.pointInsidePolygon( x, y, this.points, - centerX, centerY, width, height, [0, -1], padding ) - ; + checkPoint: function checkPoint(x, y, padding, width, height, centerX, centerY) { + return math.pointInsidePolygon(x, y, this.points, centerX, centerY, width, height, [0, -1], padding); } - } ); + }; }; -BRp.generateEllipse = function(){ - return ( this.nodeShapes['ellipse'] = { +BRp.generateEllipse = function () { + return this.nodeShapes['ellipse'] = { renderer: this, name: 'ellipse', - draw: function( context, centerX, centerY, width, height ){ - this.renderer.nodeShapeImpl( this.name, context, centerX, centerY, width, height ); + draw: function draw(context, centerX, centerY, width, height) { + this.renderer.nodeShapeImpl(this.name, context, centerX, centerY, width, height); }, - intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){ - return math.intersectLineEllipse( - x, y, - nodeX, - nodeY, - width / 2 + padding, - height / 2 + padding ) - ; + intersectLine: function intersectLine(nodeX, nodeY, width, height, x, y, padding) { + return math.intersectLineEllipse(x, y, nodeX, nodeY, width / 2 + padding, height / 2 + padding); }, - checkPoint: function( x, y, padding, width, height, centerX, centerY ){ - x -= centerX; - y -= centerY; - - x /= (width / 2 + padding); - y /= (height / 2 + padding); - - return x * x + y * y <= 1; + checkPoint: function checkPoint(x, y, padding, width, height, centerX, centerY) { + return math.checkInEllipse(x, y, width, height, centerX, centerY, padding); } - } ); + }; }; -BRp.generateRoundRectangle = function(){ - return ( this.nodeShapes['roundrectangle'] = { +BRp.generateRoundRectangle = function () { + return this.nodeShapes['roundrectangle'] = { renderer: this, name: 'roundrectangle', - points: math.generateUnitNgonPointsFitToSquare( 4, 0 ), + points: math.generateUnitNgonPointsFitToSquare(4, 0), - draw: function( context, centerX, centerY, width, height ){ - this.renderer.nodeShapeImpl( this.name, context, centerX, centerY, width, height ); + draw: function draw(context, centerX, centerY, width, height) { + this.renderer.nodeShapeImpl(this.name, context, centerX, centerY, width, height); }, - intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){ - return math.roundRectangleIntersectLine( - x, y, - nodeX, - nodeY, - width, height, - padding ) - ; + intersectLine: function intersectLine(nodeX, nodeY, width, height, x, y, padding) { + return math.roundRectangleIntersectLine(x, y, nodeX, nodeY, width, height, padding); }, - // Looks like the width passed into this function is actually the total width / 2 - checkPoint: function( - x, y, padding, width, height, centerX, centerY ){ + checkPoint: function checkPoint(x, y, padding, width, height, centerX, centerY) { - var cornerRadius = math.getRoundRectangleRadius( width, height ); + var cornerRadius = math.getRoundRectangleRadius(width, height); + var diam = cornerRadius * 2; // Check hBox - if( math.pointInsidePolygon( x, y, this.points, - centerX, centerY, width, height - 2 * cornerRadius, [0, -1], padding ) ){ + if (math.pointInsidePolygon(x, y, this.points, centerX, centerY, width, height - diam, [0, -1], padding)) { return true; } // Check vBox - if( math.pointInsidePolygon( x, y, this.points, - centerX, centerY, width - 2 * cornerRadius, height, [0, -1], padding ) ){ + if (math.pointInsidePolygon(x, y, this.points, centerX, centerY, width - diam, height, [0, -1], padding)) { return true; } - var checkInEllipse = function( x, y, centerX, centerY, width, height, padding ){ - x -= centerX; - y -= centerY; - - x /= (width / 2 + padding); - y /= (height / 2 + padding); - - return (x * x + y * y <= 1); - }; - - // Check top left quarter circle - if( checkInEllipse( x, y, - centerX - width / 2 + cornerRadius, - centerY - height / 2 + cornerRadius, - cornerRadius * 2, cornerRadius * 2, padding ) ){ + if (math.checkInEllipse(x, y, diam, diam, centerX - width / 2 + cornerRadius, centerY - height / 2 + cornerRadius, padding)) { return true; } // Check top right quarter circle - if( checkInEllipse( x, y, - centerX + width / 2 - cornerRadius, - centerY - height / 2 + cornerRadius, - cornerRadius * 2, cornerRadius * 2, padding ) ){ + if (math.checkInEllipse(x, y, diam, diam, centerX + width / 2 - cornerRadius, centerY - height / 2 + cornerRadius, padding)) { return true; } // Check bottom right quarter circle - if( checkInEllipse( x, y, - centerX + width / 2 - cornerRadius, - centerY + height / 2 - cornerRadius, - cornerRadius * 2, cornerRadius * 2, padding ) ){ + if (math.checkInEllipse(x, y, diam, diam, centerX + width / 2 - cornerRadius, centerY + height / 2 - cornerRadius, padding)) { return true; } // Check bottom left quarter circle - if( checkInEllipse( x, y, - centerX - width / 2 + cornerRadius, - centerY + height / 2 - cornerRadius, - cornerRadius * 2, cornerRadius * 2, padding ) ){ + if (math.checkInEllipse(x, y, diam, diam, centerX - width / 2 + cornerRadius, centerY + height / 2 - cornerRadius, padding)) { return true; } return false; } - } ); + }; }; -BRp.registerNodeShapes = function(){ +BRp.generateCutRectangle = function () { + return this.nodeShapes['cutrectangle'] = { + renderer: this, + + name: 'cutrectangle', + + cornerLength: math.getCutRectangleCornerLength(), + + points: math.generateUnitNgonPointsFitToSquare(4, 0), + + draw: function draw(context, centerX, centerY, width, height) { + this.renderer.nodeShapeImpl(this.name, context, centerX, centerY, width, height); + }, + + generateCutTrianglePts: function generateCutTrianglePts(width, height, centerX, centerY) { + var cl = this.cornerLength; + var hh = height / 2; + var hw = width / 2; + var xBegin = centerX - hw; + var xEnd = centerX + hw; + var yBegin = centerY - hh; + var yEnd = centerY + hh; + + // points are in clockwise order, inner (imaginary) triangle pt on [4, 5] + return { + topLeft: [xBegin, yBegin + cl, xBegin + cl, yBegin, xBegin + cl, yBegin + cl], + topRight: [xEnd - cl, yBegin, xEnd, yBegin + cl, xEnd - cl, yBegin + cl], + bottomRight: [xEnd, yEnd - cl, xEnd - cl, yEnd, xEnd - cl, yEnd - cl], + bottomLeft: [xBegin + cl, yEnd, xBegin, yEnd - cl, xBegin + cl, yEnd - cl] + }; + }, + + intersectLine: function intersectLine(nodeX, nodeY, width, height, x, y, padding) { + var cPts = this.generateCutTrianglePts(width + 2 * padding, height + 2 * padding, nodeX, nodeY); + var pts = [].concat.apply([], [cPts.topLeft.splice(0, 4), cPts.topRight.splice(0, 4), cPts.bottomRight.splice(0, 4), cPts.bottomLeft.splice(0, 4)]); + + return math.polygonIntersectLine(x, y, pts, nodeX, nodeY); + }, + + checkPoint: function checkPoint(x, y, padding, width, height, centerX, centerY) { + // Check hBox + if (math.pointInsidePolygon(x, y, this.points, centerX, centerY, width, height - 2 * this.cornerLength, [0, -1], padding)) { + return true; + } + + // Check vBox + if (math.pointInsidePolygon(x, y, this.points, centerX, centerY, width - 2 * this.cornerLength, height, [0, -1], padding)) { + return true; + } + var cutTrianglePts = this.generateCutTrianglePts(width, height, centerX, centerY); + return math.pointInsidePolygonPoints(x, y, cutTrianglePts.topLeft) || math.pointInsidePolygonPoints(x, y, cutTrianglePts.topRight) || math.pointInsidePolygonPoints(x, y, cutTrianglePts.bottomRight) || math.pointInsidePolygonPoints(x, y, cutTrianglePts.bottomLeft); + } + + }; +}; + +BRp.generateBarrel = function () { + return this.nodeShapes['barrel'] = { + renderer: this, + + name: 'barrel', + + points: math.generateUnitNgonPointsFitToSquare(4, 0), + + draw: function draw(context, centerX, centerY, width, height) { + this.renderer.nodeShapeImpl(this.name, context, centerX, centerY, width, height); + }, + + intersectLine: function intersectLine(nodeX, nodeY, width, height, x, y, padding) { + // use two fixed t values for the bezier curve approximation + + var t0 = 0.15; + var t1 = 0.5; + var t2 = 0.85; + + var bPts = this.generateBarrelBezierPts(width + 2 * padding, height + 2 * padding, nodeX, nodeY); + + var approximateBarrelCurvePts = function approximateBarrelCurvePts(pts) { + // approximate curve pts based on the two t values + var m0 = math.qbezierPtAt({ x: pts[0], y: pts[1] }, { x: pts[2], y: pts[3] }, { x: pts[4], y: pts[5] }, t0); + var m1 = math.qbezierPtAt({ x: pts[0], y: pts[1] }, { x: pts[2], y: pts[3] }, { x: pts[4], y: pts[5] }, t1); + var m2 = math.qbezierPtAt({ x: pts[0], y: pts[1] }, { x: pts[2], y: pts[3] }, { x: pts[4], y: pts[5] }, t2); + + return [pts[0], pts[1], m0.x, m0.y, m1.x, m1.y, m2.x, m2.y, pts[4], pts[5]]; + }; + + var pts = [].concat(approximateBarrelCurvePts(bPts.topLeft), approximateBarrelCurvePts(bPts.topRight), approximateBarrelCurvePts(bPts.bottomRight), approximateBarrelCurvePts(bPts.bottomLeft)); + + return math.polygonIntersectLine(x, y, pts, nodeX, nodeY); + }, + + generateBarrelBezierPts: function generateBarrelBezierPts(width, height, centerX, centerY) { + var hh = height / 2; + var hw = width / 2; + var xBegin = centerX - hw; + var xEnd = centerX + hw; + var yBegin = centerY - hh; + var yEnd = centerY + hh; + + var curveConstants = math.getBarrelCurveConstants(width, height); + var hOffset = curveConstants.heightOffset; + var wOffset = curveConstants.widthOffset; + var ctrlPtXOffset = curveConstants.ctrlPtOffsetPct * width; + + // points are in clockwise order, inner (imaginary) control pt on [4, 5] + var pts = { + topLeft: [xBegin, yBegin + hOffset, xBegin + ctrlPtXOffset, yBegin, xBegin + wOffset, yBegin], + topRight: [xEnd - wOffset, yBegin, xEnd - ctrlPtXOffset, yBegin, xEnd, yBegin + hOffset], + bottomRight: [xEnd, yEnd - hOffset, xEnd - ctrlPtXOffset, yEnd, xEnd - wOffset, yEnd], + bottomLeft: [xBegin + wOffset, yEnd, xBegin + ctrlPtXOffset, yEnd, xBegin, yEnd - hOffset] + }; + + pts.topLeft.isTop = true; + pts.topRight.isTop = true; + pts.bottomLeft.isBottom = true; + pts.bottomRight.isBottom = true; + + return pts; + }, + + checkPoint: function checkPoint(x, y, padding, width, height, centerX, centerY) { + + var curveConstants = math.getBarrelCurveConstants(width, height); + var hOffset = curveConstants.heightOffset; + var wOffset = curveConstants.widthOffset; + + // Check hBox + if (math.pointInsidePolygon(x, y, this.points, centerX, centerY, width, height - 2 * hOffset, [0, -1], padding)) { + return true; + } + + // Check vBox + if (math.pointInsidePolygon(x, y, this.points, centerX, centerY, width - 2 * wOffset, height, [0, -1], padding)) { + return true; + } + + var barrelCurvePts = this.generateBarrelBezierPts(width, height, centerX, centerY); + + var getCurveT = function getCurveT(x, y, curvePts) { + var x0 = curvePts[4]; + var x1 = curvePts[2]; + var x2 = curvePts[0]; + var y0 = curvePts[5]; + // var y1 = curvePts[ 3 ]; + var y2 = curvePts[1]; + + var xMin = Math.min(x0, x2); + var xMax = Math.max(x0, x2); + var yMin = Math.min(y0, y2); + var yMax = Math.max(y0, y2); + + if (xMin <= x && x <= xMax && yMin <= y && y <= yMax) { + var coeff = math.bezierPtsToQuadCoeff(x0, x1, x2); + var roots = math.solveQuadratic(coeff[0], coeff[1], coeff[2], x); + + var validRoots = roots.filter(function (r) { + return 0 <= r && r <= 1; + }); + + if (validRoots.length > 0) { + return validRoots[0]; + } + } + return null; + }; + + var curveRegions = Object.keys(barrelCurvePts); + for (var i = 0; i < curveRegions.length; i++) { + var corner = curveRegions[i]; + var cornerPts = barrelCurvePts[corner]; + var t = getCurveT(x, y, cornerPts); + + if (t == null) { + continue; + } + + var y0 = cornerPts[5]; + var y1 = cornerPts[3]; + var y2 = cornerPts[1]; + var bezY = math.qbezierAt(y0, y1, y2, t); + + if (cornerPts.isTop && bezY <= y) { + return true; + } + if (cornerPts.isBottom && y <= bezY) { + return true; + } + } + return false; + } + }; +}; + +BRp.generateBottomRoundrectangle = function () { + return this.nodeShapes['bottomroundrectangle'] = { + renderer: this, + + name: 'bottomroundrectangle', + + points: math.generateUnitNgonPointsFitToSquare(4, 0), + + draw: function draw(context, centerX, centerY, width, height) { + this.renderer.nodeShapeImpl(this.name, context, centerX, centerY, width, height); + }, + + intersectLine: function intersectLine(nodeX, nodeY, width, height, x, y, padding) { + var topStartX = nodeX - (width / 2 + padding); + var topStartY = nodeY - (height / 2 + padding); + var topEndY = topStartY; + var topEndX = nodeX + (width / 2 + padding); + + var topIntersections = math.finiteLinesIntersect(x, y, nodeX, nodeY, topStartX, topStartY, topEndX, topEndY, false); + if (topIntersections.length > 0) { + return topIntersections; + } + + return math.roundRectangleIntersectLine(x, y, nodeX, nodeY, width, height, padding); + }, + + checkPoint: function checkPoint(x, y, padding, width, height, centerX, centerY) { + + var cornerRadius = math.getRoundRectangleRadius(width, height); + var diam = 2 * cornerRadius; + + // Check hBox + if (math.pointInsidePolygon(x, y, this.points, centerX, centerY, width, height - diam, [0, -1], padding)) { + return true; + } + + // Check vBox + if (math.pointInsidePolygon(x, y, this.points, centerX, centerY, width - diam, height, [0, -1], padding)) { + return true; + } + + // check non-rounded top side + var outerWidth = width / 2 + 2 * padding; + var outerHeight = height / 2 + 2 * padding; + var points = [centerX - outerWidth, centerY - outerHeight, centerX - outerWidth, centerY, centerX + outerWidth, centerY, centerX + outerWidth, centerY - outerHeight]; + if (math.pointInsidePolygonPoints(x, y, points)) { + return true; + } + + // Check bottom right quarter circle + if (math.checkInEllipse(x, y, diam, diam, centerX + width / 2 - cornerRadius, centerY + height / 2 - cornerRadius, padding)) { + + return true; + } + + // Check bottom left quarter circle + if (math.checkInEllipse(x, y, diam, diam, centerX - width / 2 + cornerRadius, centerY + height / 2 - cornerRadius, padding)) { + + return true; + } + + return false; + } + }; +}; + +BRp.registerNodeShapes = function () { var nodeShapes = this.nodeShapes = {}; var renderer = this; this.generateEllipse(); - this.generatePolygon( 'triangle', math.generateUnitNgonPointsFitToSquare( 3, 0 ) ); + this.generatePolygon('triangle', math.generateUnitNgonPointsFitToSquare(3, 0)); - this.generatePolygon( 'rectangle', math.generateUnitNgonPointsFitToSquare( 4, 0 ) ); - nodeShapes[ 'square' ] = nodeShapes[ 'rectangle' ]; + this.generatePolygon('rectangle', math.generateUnitNgonPointsFitToSquare(4, 0)); + nodeShapes['square'] = nodeShapes['rectangle']; this.generateRoundRectangle(); - this.generatePolygon( 'diamond', [ - 0, 1, - 1, 0, - 0, -1, - -1, 0 - ] ); + this.generateCutRectangle(); - this.generatePolygon( 'pentagon', math.generateUnitNgonPointsFitToSquare( 5, 0 ) ); + this.generateBarrel(); - this.generatePolygon( 'hexagon', math.generateUnitNgonPointsFitToSquare( 6, 0 ) ); + this.generateBottomRoundrectangle(); - this.generatePolygon( 'heptagon', math.generateUnitNgonPointsFitToSquare( 7, 0 ) ); + this.generatePolygon('diamond', [0, 1, 1, 0, 0, -1, -1, 0]); - this.generatePolygon( 'octagon', math.generateUnitNgonPointsFitToSquare( 8, 0 ) ); + this.generatePolygon('pentagon', math.generateUnitNgonPointsFitToSquare(5, 0)); - var star5Points = new Array( 20 ); + this.generatePolygon('hexagon', math.generateUnitNgonPointsFitToSquare(6, 0)); + + this.generatePolygon('heptagon', math.generateUnitNgonPointsFitToSquare(7, 0)); + + this.generatePolygon('octagon', math.generateUnitNgonPointsFitToSquare(8, 0)); + + var star5Points = new Array(20); { - var outerPoints = math.generateUnitNgonPoints( 5, 0 ); - var innerPoints = math.generateUnitNgonPoints( 5, Math.PI / 5 ); + var outerPoints = math.generateUnitNgonPoints(5, 0); + var innerPoints = math.generateUnitNgonPoints(5, Math.PI / 5); // Outer radius is 1; inner radius of star is smaller - var innerRadius = 0.5 * (3 - Math.sqrt( 5 )); + var innerRadius = 0.5 * (3 - Math.sqrt(5)); innerRadius *= 1.57; - for( var i = 0;i < innerPoints.length / 2;i++ ){ - innerPoints[ i * 2] *= innerRadius; - innerPoints[ i * 2 + 1] *= innerRadius; + for (var i = 0; i < innerPoints.length / 2; i++) { + innerPoints[i * 2] *= innerRadius; + innerPoints[i * 2 + 1] *= innerRadius; } - for( var i = 0;i < 20 / 4;i++ ){ - star5Points[ i * 4] = outerPoints[ i * 2]; - star5Points[ i * 4 + 1] = outerPoints[ i * 2 + 1]; + for (var i = 0; i < 20 / 4; i++) { + star5Points[i * 4] = outerPoints[i * 2]; + star5Points[i * 4 + 1] = outerPoints[i * 2 + 1]; - star5Points[ i * 4 + 2] = innerPoints[ i * 2]; - star5Points[ i * 4 + 3] = innerPoints[ i * 2 + 1]; + star5Points[i * 4 + 2] = innerPoints[i * 2]; + star5Points[i * 4 + 3] = innerPoints[i * 2 + 1]; } } - star5Points = math.fitPolygonToSquare( star5Points ); + star5Points = math.fitPolygonToSquare(star5Points); - this.generatePolygon( 'star', star5Points ); + this.generatePolygon('star', star5Points); - this.generatePolygon( 'vee', [ - -1, -1, - 0, -0.333, - 1, -1, - 0, 1 - ] ); + this.generatePolygon('vee', [-1, -1, 0, -0.333, 1, -1, 0, 1]); - this.generatePolygon( 'rhomboid', [ - -1, -1, - 0.333, -1, - 1, 1, - -0.333, 1 - ] ); + this.generatePolygon('rhomboid', [-1, -1, 0.333, -1, 1, 1, -0.333, 1]); - nodeShapes.makePolygon = function( points ){ + this.generatePolygon('concavehexagon', [-1, -0.95, -0.75, 0, -1, 0.95, 1, 0.95, 0.75, 0, 1, -0.95]); + + this.generatePolygon('tag', [-1, -1, 0.25, -1, 1, 0, 0.25, 1, -1, 1]); + + nodeShapes.makePolygon = function (points) { // use caching on user-specified polygons so they are as fast as native shapes - var key = points.join( '$' ); + var key = points.join('$'); var name = 'polygon-' + key; var shape; - if( (shape = this[ name ]) ){ // got cached shape + if (shape = this[name]) { + // got cached shape return shape; } // create and cache new shape - return renderer.generatePolygon( name, points ); + return renderer.generatePolygon(name, points); }; - }; module.exports = BRp; -},{"../../../math":85}],63:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 123 */ +/***/ (function(module, exports, __webpack_require__) { -var util = _dereq_( '../../../util' ); +"use strict"; + + +var util = __webpack_require__(1); var BRp = {}; -BRp.timeToRender = function(){ +BRp.timeToRender = function () { return this.redrawTotalTime / this.redrawCount; }; -BRp.redraw = function( options ){ +BRp.redraw = function (options) { options = options || util.staticEmptyObject(); var r = this; - if( r.averageRedrawTime === undefined ){ r.averageRedrawTime = 0; } - if( r.lastRedrawTime === undefined ){ r.lastRedrawTime = 0; } - if( r.lastDrawTime === undefined ){ r.lastDrawTime = 0; } + if (r.averageRedrawTime === undefined) { + r.averageRedrawTime = 0; + } + if (r.lastRedrawTime === undefined) { + r.lastRedrawTime = 0; + } + if (r.lastDrawTime === undefined) { + r.lastDrawTime = 0; + } r.requestedFrame = true; r.renderOptions = options; }; -BRp.beforeRender = function( fn, priority ){ +BRp.beforeRender = function (fn, priority) { + // the renderer can't add tick callbacks when destroyed + if (this.destroyed) { + return; + } + priority = priority || 0; var cbs = this.beforeRenderCallbacks; @@ -16497,49 +25979,53 @@ BRp.beforeRender = function( fn, priority ){ cbs.push({ fn: fn, priority: priority }); // higher priority callbacks executed first - cbs.sort(function( a, b ){ return b.priority - a.priority; }); + cbs.sort(function (a, b) { + return b.priority - a.priority; + }); }; -var beforeRenderCallbacks = function( r, willDraw, startTime ){ +var beforeRenderCallbacks = function beforeRenderCallbacks(r, willDraw, startTime) { var cbs = r.beforeRenderCallbacks; - for( var i = 0; i < cbs.length; i++ ){ - cbs[i].fn( willDraw, startTime ); + for (var i = 0; i < cbs.length; i++) { + cbs[i].fn(willDraw, startTime); } }; -BRp.startRenderLoop = function(){ +BRp.startRenderLoop = function () { var r = this; - if( r.renderLoopStarted ){ + if (r.renderLoopStarted) { return; } else { r.renderLoopStarted = true; } - var renderFn = function( requestTime ){ - if( r.destroyed ){ return; } + var renderFn = function renderFn(requestTime) { + if (r.destroyed) { + return; + } - if( r.requestedFrame && !r.skipFrame ){ - beforeRenderCallbacks( r, true, requestTime ); + if (r.requestedFrame && !r.skipFrame) { + beforeRenderCallbacks(r, true, requestTime); var startTime = util.performanceNow(); - r.render( r.renderOptions ); + r.render(r.renderOptions); var endTime = r.lastDrawTime = util.performanceNow(); - if( r.averageRedrawTime === undefined ){ + if (r.averageRedrawTime === undefined) { r.averageRedrawTime = endTime - startTime; } - if( r.redrawCount === undefined ){ + if (r.redrawCount === undefined) { r.redrawCount = 0; } r.redrawCount++; - if( r.redrawTotalTime === undefined ){ + if (r.redrawTotalTime === undefined) { r.redrawTotalTime = 0; } @@ -16553,190 +26039,1776 @@ BRp.startRenderLoop = function(){ r.requestedFrame = false; } else { - beforeRenderCallbacks( r, false, requestTime ); + beforeRenderCallbacks(r, false, requestTime); } r.skipFrame = false; - util.requestAnimationFrame( renderFn ); + util.requestAnimationFrame(renderFn); }; - util.requestAnimationFrame( renderFn ); - + util.requestAnimationFrame(renderFn); }; module.exports = BRp; -},{"../../../util":100}],64:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 124 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/* +The canvas renderer was written by Yue Dong. + +Modifications tracked on Github. +*/ + +var util = __webpack_require__(1); +var is = __webpack_require__(0); +var ElementTextureCache = __webpack_require__(125); +var LayeredTextureCache = __webpack_require__(126); + +var CR = CanvasRenderer; +var CRp = CanvasRenderer.prototype; + +CRp.CANVAS_LAYERS = 3; +// +CRp.SELECT_BOX = 0; +CRp.DRAG = 1; +CRp.NODE = 2; + +CRp.BUFFER_COUNT = 3; +// +CRp.TEXTURE_BUFFER = 0; +CRp.MOTIONBLUR_BUFFER_NODE = 1; +CRp.MOTIONBLUR_BUFFER_DRAG = 2; + +function CanvasRenderer(options) { + var r = this; + + r.data = { + canvases: new Array(CRp.CANVAS_LAYERS), + contexts: new Array(CRp.CANVAS_LAYERS), + canvasNeedsRedraw: new Array(CRp.CANVAS_LAYERS), + + bufferCanvases: new Array(CRp.BUFFER_COUNT), + bufferContexts: new Array(CRp.CANVAS_LAYERS) + }; + + var tapHlOff = '-webkit-tap-highlight-color: rgba(0,0,0,0);'; + + r.data.canvasContainer = document.createElement('div'); // eslint-disable-line no-undef + var containerStyle = r.data.canvasContainer.style; + r.data.canvasContainer.setAttribute('style', tapHlOff); + containerStyle.position = 'relative'; + containerStyle.zIndex = '0'; + containerStyle.overflow = 'hidden'; + + var container = options.cy.container(); + container.appendChild(r.data.canvasContainer); + + if ((container.getAttribute('style') || '').indexOf(tapHlOff) < 0) { + container.setAttribute('style', (container.getAttribute('style') || '') + tapHlOff); + } + + for (var i = 0; i < CRp.CANVAS_LAYERS; i++) { + var canvas = r.data.canvases[i] = document.createElement('canvas'); // eslint-disable-line no-undef + r.data.contexts[i] = canvas.getContext('2d'); + canvas.setAttribute('style', '-webkit-user-select: none; -moz-user-select: -moz-none; user-select: none; -webkit-tap-highlight-color: rgba(0,0,0,0); outline-style: none;' + (is.ms() ? ' -ms-touch-action: none; touch-action: none; ' : '')); + canvas.style.position = 'absolute'; + canvas.setAttribute('data-id', 'layer' + i); + canvas.style.zIndex = String(CRp.CANVAS_LAYERS - i); + r.data.canvasContainer.appendChild(canvas); + + r.data.canvasNeedsRedraw[i] = false; + } + r.data.topCanvas = r.data.canvases[0]; + + r.data.canvases[CRp.NODE].setAttribute('data-id', 'layer' + CRp.NODE + '-node'); + r.data.canvases[CRp.SELECT_BOX].setAttribute('data-id', 'layer' + CRp.SELECT_BOX + '-selectbox'); + r.data.canvases[CRp.DRAG].setAttribute('data-id', 'layer' + CRp.DRAG + '-drag'); + + for (var i = 0; i < CRp.BUFFER_COUNT; i++) { + r.data.bufferCanvases[i] = document.createElement('canvas'); // eslint-disable-line no-undef + r.data.bufferContexts[i] = r.data.bufferCanvases[i].getContext('2d'); + r.data.bufferCanvases[i].style.position = 'absolute'; + r.data.bufferCanvases[i].setAttribute('data-id', 'buffer' + i); + r.data.bufferCanvases[i].style.zIndex = String(-i - 1); + r.data.bufferCanvases[i].style.visibility = 'hidden'; + //r.data.canvasContainer.appendChild(r.data.bufferCanvases[i]); + } + + r.pathsEnabled = true; + + r.data.eleTxrCache = new ElementTextureCache(r); + r.data.lyrTxrCache = new LayeredTextureCache(r, r.data.eleTxrCache); + + r.onUpdateEleCalcs(function invalidateTextureCaches(willDraw, eles) { + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; + var rs = ele._private.rstyle; + var de = rs.dirtyEvents; + + if (ele.isNode() && de && de.length === 1 && de['position']) { + // then keep cached ele texture + } else { + r.data.eleTxrCache.invalidateElement(ele); + + // NB this block of code should not be ported to 3.3 (unstable branch). + // - This check is unneccesary in 3.3 as caches will be stored without respect to opacity. + // - This fix may result in lowered performance for compound graphs. + // - Ref : Opacity of child node is not updated for certain zoom levels after parent opacity is overriden #2078 + if (ele.isParent() && de['style']) { + var op1 = rs.prevParentOpacity; + var op2 = ele.pstyle('opacity').pfValue; + + rs.prevParentOpacity = op2; + + if (op1 !== op2) { + var descs = ele.descendants(); + + for (var j = 0; j < descs.length; j++) { + r.data.eleTxrCache.invalidateElement(descs[j]); + } + } + } + } + } + + if (eles.length > 0) { + r.data.lyrTxrCache.invalidateElements(eles); + } + }); +} + +CRp.redrawHint = function (group, bool) { + var r = this; + + switch (group) { + case 'eles': + r.data.canvasNeedsRedraw[CRp.NODE] = bool; + break; + case 'drag': + r.data.canvasNeedsRedraw[CRp.DRAG] = bool; + break; + case 'select': + r.data.canvasNeedsRedraw[CRp.SELECT_BOX] = bool; + break; + } +}; + +// whether to use Path2D caching for drawing +var pathsImpld = typeof Path2D !== 'undefined'; + +CRp.path2dEnabled = function (on) { + if (on === undefined) { + return this.pathsEnabled; + } + + this.pathsEnabled = on ? true : false; +}; + +CRp.usePaths = function () { + return pathsImpld && this.pathsEnabled; +}; + +[__webpack_require__(127), __webpack_require__(128), __webpack_require__(129), __webpack_require__(130), __webpack_require__(131), __webpack_require__(132), __webpack_require__(133), __webpack_require__(134), __webpack_require__(135), __webpack_require__(136)].forEach(function (props) { + util.extend(CRp, props); +}); + +module.exports = CR; + +/***/ }), +/* 125 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var math = __webpack_require__(2); +var util = __webpack_require__(1); +var Heap = __webpack_require__(9); +var defs = __webpack_require__(19); + +var minTxrH = 25; // the size of the texture cache for small height eles (special case) +var txrStepH = 50; // the min size of the regular cache, and the size it increases with each step up +var minLvl = -4; // when scaling smaller than that we don't need to re-render +var maxLvl = 2; // when larger than this scale just render directly (caching is not helpful) +var maxZoom = 3.99; // beyond this zoom level, layered textures are not used +var eleTxrSpacing = 8; // spacing between elements on textures to avoid blitting overlaps +var defTxrWidth = 1024; // default/minimum texture width +var maxTxrW = 1024; // the maximum width of a texture +var maxTxrH = 1024; // the maximum height of a texture +var minUtility = 0.5; // if usage of texture is less than this, it is retired +var maxFullness = 0.8; // fullness of texture after which queue removal is checked +var maxFullnessChecks = 10; // dequeued after this many checks +var allowEdgeTxrCaching = false; // whether edges can be cached as textures (TODO maybe better on if webgl supported?) +var allowParentTxrCaching = false; // whether parent nodes can be cached as textures (TODO maybe better on if webgl supported?) +var deqCost = 0.15; // % of add'l rendering cost allowed for dequeuing ele caches each frame +var deqAvgCost = 0.1; // % of add'l rendering cost compared to average overall redraw time +var deqNoDrawCost = 0.9; // % of avg frame time that can be used for dequeueing when not drawing +var deqFastCost = 0.9; // % of frame time to be used when >60fps +var deqRedrawThreshold = 100; // time to batch redraws together from dequeueing to allow more dequeueing calcs to happen in the meanwhile +var maxDeqSize = 1; // number of eles to dequeue and render at higher texture in each batch + +var getTxrReasons = { + dequeue: 'dequeue', + downscale: 'downscale', + highQuality: 'highQuality' +}; + +var ElementTextureCache = function ElementTextureCache(renderer) { + var self = this; + + self.renderer = renderer; + self.onDequeues = []; + + self.setupDequeueing(); +}; + +var ETCp = ElementTextureCache.prototype; + +ETCp.reasons = getTxrReasons; + +// the list of textures in which new subtextures for elements can be placed +ETCp.getTextureQueue = function (txrH) { + var self = this; + self.eleImgCaches = self.eleImgCaches || {}; + + return self.eleImgCaches[txrH] = self.eleImgCaches[txrH] || []; +}; + +// the list of usused textures which can be recycled (in use in texture queue) +ETCp.getRetiredTextureQueue = function (txrH) { + var self = this; + + var rtxtrQs = self.eleImgCaches.retired = self.eleImgCaches.retired || {}; + var rtxtrQ = rtxtrQs[txrH] = rtxtrQs[txrH] || []; + + return rtxtrQ; +}; + +// queue of element draw requests at different scale levels +ETCp.getElementQueue = function () { + var self = this; + + var q = self.eleCacheQueue = self.eleCacheQueue || new Heap(function (a, b) { + return b.reqs - a.reqs; + }); + + return q; +}; + +// queue of element draw requests at different scale levels (element id lookup) +ETCp.getElementIdToQueue = function () { + var self = this; + + var id2q = self.eleIdToCacheQueue = self.eleIdToCacheQueue || {}; + + return id2q; +}; + +ETCp.getElement = function (ele, bb, pxRatio, lvl, reason) { + var self = this; + var r = this.renderer; + var rs = ele._private.rscratch; + var zoom = r.cy.zoom(); + + if (bb.w === 0 || bb.h === 0 || !ele.visible()) { + return null; + } + + if (lvl == null) { + lvl = Math.ceil(math.log2(zoom * pxRatio)); + } + + if (lvl < minLvl) { + lvl = minLvl; + } else if (zoom >= maxZoom || lvl > maxLvl) { + return null; + } + + var scale = Math.pow(2, lvl); + var eleScaledH = bb.h * scale; + var eleScaledW = bb.w * scale; + var caches = rs.imgCaches = rs.imgCaches || {}; + var eleCache = caches[lvl]; + + if (eleCache) { + return eleCache; + } + + var txrH; // which texture height this ele belongs to + + if (eleScaledH <= minTxrH) { + txrH = minTxrH; + } else if (eleScaledH <= txrStepH) { + txrH = txrStepH; + } else { + txrH = Math.ceil(eleScaledH / txrStepH) * txrStepH; + } + + if (eleScaledH > maxTxrH || eleScaledW > maxTxrW || !allowEdgeTxrCaching && ele.isEdge() || !allowParentTxrCaching && ele.isParent()) { + return null; // caching large elements is not efficient + } + + var txrQ = self.getTextureQueue(txrH); + + // first try the second last one in case it has space at the end + var txr = txrQ[txrQ.length - 2]; + + var addNewTxr = function addNewTxr() { + return self.recycleTexture(txrH, eleScaledW) || self.addTexture(txrH, eleScaledW); + }; + + // try the last one if there is no second last one + if (!txr) { + txr = txrQ[txrQ.length - 1]; + } + + // if the last one doesn't exist, we need a first one + if (!txr) { + txr = addNewTxr(); + } + + // if there's no room in the current texture, we need a new one + if (txr.width - txr.usedWidth < eleScaledW) { + txr = addNewTxr(); + } + + var scaledLabelShown = r.eleTextBiggerThanMin(ele, scale); + var scalableFrom = function scalableFrom(otherCache) { + return otherCache && otherCache.scaledLabelShown === scaledLabelShown; + }; + + var deqing = reason && reason === getTxrReasons.dequeue; + var highQualityReq = reason && reason === getTxrReasons.highQuality; + var downscaleReq = reason && reason === getTxrReasons.downscale; + + var higherCache; // the nearest cache with a higher level + for (var l = lvl + 1; l <= maxLvl; l++) { + var c = caches[l]; + + if (c) { + higherCache = c;break; + } + } + + var oneUpCache = higherCache && higherCache.level === lvl + 1 ? higherCache : null; + + var downscale = function downscale() { + txr.context.drawImage(oneUpCache.texture.canvas, oneUpCache.x, 0, oneUpCache.width, oneUpCache.height, txr.usedWidth, 0, eleScaledW, eleScaledH); + }; + + // reset ele area in texture + txr.context.setTransform(1, 0, 0, 1, 0, 0); + txr.context.clearRect(txr.usedWidth, 0, eleScaledW, txrH); + + if (scalableFrom(oneUpCache)) { + // then we can relatively cheaply rescale the existing image w/o rerendering + downscale(); + } else if (scalableFrom(higherCache)) { + // then use the higher cache for now and queue the next level down + // to cheaply scale towards the smaller level + + if (highQualityReq) { + for (var l = higherCache.level; l > lvl; l--) { + oneUpCache = self.getElement(ele, bb, pxRatio, l, getTxrReasons.downscale); + } + + downscale(); + } else { + self.queueElement(ele, higherCache.level - 1); + + return higherCache; + } + } else { + + var lowerCache; // the nearest cache with a lower level + if (!deqing && !highQualityReq && !downscaleReq) { + for (var l = lvl - 1; l >= minLvl; l--) { + var c = caches[l]; + + if (c) { + lowerCache = c;break; + } + } + } + + if (scalableFrom(lowerCache)) { + // then use the lower quality cache for now and queue the better one for later + + self.queueElement(ele, lvl); + + return lowerCache; + } + + txr.context.translate(txr.usedWidth, 0); + txr.context.scale(scale, scale); + + r.drawElement(txr.context, ele, bb, scaledLabelShown); + + txr.context.scale(1 / scale, 1 / scale); + txr.context.translate(-txr.usedWidth, 0); + } + + eleCache = caches[lvl] = { + ele: ele, + x: txr.usedWidth, + texture: txr, + level: lvl, + scale: scale, + width: eleScaledW, + height: eleScaledH, + scaledLabelShown: scaledLabelShown + }; + + txr.usedWidth += Math.ceil(eleScaledW + eleTxrSpacing); + + txr.eleCaches.push(eleCache); + + self.checkTextureFullness(txr); + + return eleCache; +}; + +ETCp.invalidateElement = function (ele) { + var self = this; + var caches = ele._private.rscratch.imgCaches; + + if (caches) { + for (var lvl = minLvl; lvl <= maxLvl; lvl++) { + var cache = caches[lvl]; + + if (cache) { + var txr = cache.texture; + + // remove space from the texture it belongs to + txr.invalidatedWidth += cache.width; + + // remove refs with the element + caches[lvl] = null; + util.removeFromArray(txr.eleCaches, cache); + + // remove from queue since the old req was for the old state + self.removeFromQueue(ele); + + // might have to remove the entire texture if it's not efficiently using its space + self.checkTextureUtility(txr); + } + } + } +}; + +ETCp.checkTextureUtility = function (txr) { + // invalidate all entries in the cache if the cache size is small + if (txr.invalidatedWidth >= minUtility * txr.width) { + this.retireTexture(txr); + } +}; + +ETCp.checkTextureFullness = function (txr) { + // if texture has been mostly filled and passed over several times, remove + // it from the queue so we don't need to waste time looking at it to put new things + + var self = this; + var txrQ = self.getTextureQueue(txr.height); + + if (txr.usedWidth / txr.width > maxFullness && txr.fullnessChecks >= maxFullnessChecks) { + util.removeFromArray(txrQ, txr); + } else { + txr.fullnessChecks++; + } +}; + +ETCp.retireTexture = function (txr) { + var self = this; + var txrH = txr.height; + var txrQ = self.getTextureQueue(txrH); + + // retire the texture from the active / searchable queue: + + util.removeFromArray(txrQ, txr); + + txr.retired = true; + + // remove the refs from the eles to the caches: + + var eleCaches = txr.eleCaches; + + for (var i = 0; i < eleCaches.length; i++) { + var eleCache = eleCaches[i]; + var ele = eleCache.ele; + var lvl = eleCache.level; + var imgCaches = ele._private.rscratch.imgCaches; + + if (imgCaches) { + imgCaches[lvl] = null; + } + } + + util.clearArray(eleCaches); + + // add the texture to a retired queue so it can be recycled in future: + + var rtxtrQ = self.getRetiredTextureQueue(txrH); + + rtxtrQ.push(txr); +}; + +ETCp.addTexture = function (txrH, minW) { + var self = this; + var txrQ = self.getTextureQueue(txrH); + var txr = {}; + + txrQ.push(txr); + + txr.eleCaches = []; + + txr.height = txrH; + txr.width = Math.max(defTxrWidth, minW); + txr.usedWidth = 0; + txr.invalidatedWidth = 0; + txr.fullnessChecks = 0; + + txr.canvas = document.createElement('canvas'); // eslint-disable-line no-undef + txr.canvas.width = txr.width; + txr.canvas.height = txr.height; + + txr.context = txr.canvas.getContext('2d'); + + return txr; +}; + +ETCp.recycleTexture = function (txrH, minW) { + var self = this; + var txrQ = self.getTextureQueue(txrH); + var rtxtrQ = self.getRetiredTextureQueue(txrH); + + for (var i = 0; i < rtxtrQ.length; i++) { + var txr = rtxtrQ[i]; + + if (txr.width >= minW) { + txr.retired = false; + + txr.usedWidth = 0; + txr.invalidatedWidth = 0; + txr.fullnessChecks = 0; + + util.clearArray(txr.eleCaches); + + txr.context.setTransform(1, 0, 0, 1, 0, 0); + txr.context.clearRect(0, 0, txr.width, txr.height); + + util.removeFromArray(rtxtrQ, txr); + txrQ.push(txr); + + return txr; + } + } +}; + +ETCp.queueElement = function (ele, lvl) { + var self = this; + var q = self.getElementQueue(); + var id2q = self.getElementIdToQueue(); + var id = ele.id(); + var existingReq = id2q[id]; + + if (existingReq) { + // use the max lvl b/c in between lvls are cheap to make + existingReq.level = Math.max(existingReq.level, lvl); + existingReq.reqs++; + + q.updateItem(existingReq); + } else { + var req = { + ele: ele, + level: lvl, + reqs: 1 + }; + + q.push(req); + + id2q[id] = req; + } +}; + +ETCp.dequeue = function (pxRatio /*, extent*/) { + var self = this; + var q = self.getElementQueue(); + var id2q = self.getElementIdToQueue(); + var dequeued = []; + + for (var i = 0; i < maxDeqSize; i++) { + if (q.size() > 0) { + var req = q.pop(); + var ele = req.ele; + var caches = ele._private.rscratch.imgCaches; + + // dequeueing isn't necessary when an existing cache exists + if (caches[req.level] != null) { + continue; + } + + id2q[ele.id()] = null; + + dequeued.push(req); + + var bb = ele.boundingBox(); + + self.getElement(ele, bb, pxRatio, req.level, getTxrReasons.dequeue); + } else { + break; + } + } + + return dequeued; +}; + +ETCp.removeFromQueue = function (ele) { + var self = this; + var q = self.getElementQueue(); + var id2q = self.getElementIdToQueue(); + var req = id2q[ele.id()]; + + if (req != null) { + // bring to front of queue + req.reqs = util.MAX_INT; + q.updateItem(req); + + q.pop(); // remove from queue + + id2q[ele.id()] = null; // remove from lookup map + } +}; + +ETCp.onDequeue = function (fn) { + this.onDequeues.push(fn); +}; +ETCp.offDequeue = function (fn) { + util.removeFromArray(this.onDequeues, fn); +}; + +ETCp.setupDequeueing = defs.setupDequeueing({ + deqRedrawThreshold: deqRedrawThreshold, + deqCost: deqCost, + deqAvgCost: deqAvgCost, + deqNoDrawCost: deqNoDrawCost, + deqFastCost: deqFastCost, + deq: function deq(self, pxRatio, extent) { + return self.dequeue(pxRatio, extent); + }, + onDeqd: function onDeqd(self, deqd) { + for (var i = 0; i < self.onDequeues.length; i++) { + var fn = self.onDequeues[i]; + + fn(deqd); + } + }, + shouldRedraw: function shouldRedraw(self, deqd, pxRatio, extent) { + for (var i = 0; i < deqd.length; i++) { + var bb = deqd[i].ele.boundingBox(); + + if (math.boundingBoxesIntersect(bb, extent)) { + return true; + } + } + + return false; + }, + priority: function priority(self) { + return self.renderer.beforeRenderPriorities.eleTxrDeq; + } +}); + +module.exports = ElementTextureCache; + +/***/ }), +/* 126 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var util = __webpack_require__(1); +var math = __webpack_require__(2); +var Heap = __webpack_require__(9); +var is = __webpack_require__(0); +var defs = __webpack_require__(19); + +var defNumLayers = 1; // default number of layers to use +var minLvl = -4; // when scaling smaller than that we don't need to re-render +var maxLvl = 2; // when larger than this scale just render directly (caching is not helpful) +var maxZoom = 3.99; // beyond this zoom level, layered textures are not used +var deqRedrawThreshold = 50; // time to batch redraws together from dequeueing to allow more dequeueing calcs to happen in the meanwhile +var refineEleDebounceTime = 50; // time to debounce sharper ele texture updates +var disableEleImgSmoothing = true; // when drawing eles on layers from an ele cache ; crisper and more performant when true +var deqCost = 0.15; // % of add'l rendering cost allowed for dequeuing ele caches each frame +var deqAvgCost = 0.1; // % of add'l rendering cost compared to average overall redraw time +var deqNoDrawCost = 0.9; // % of avg frame time that can be used for dequeueing when not drawing +var deqFastCost = 0.9; // % of frame time to be used when >60fps +var maxDeqSize = 1; // number of eles to dequeue and render at higher texture in each batch +var invalidThreshold = 250; // time threshold for disabling b/c of invalidations +var maxLayerArea = 4000 * 4000; // layers can't be bigger than this +var alwaysQueue = true; // never draw all the layers in a level on a frame; draw directly until all dequeued +var useHighQualityEleTxrReqs = true; // whether to use high quality ele txr requests (generally faster and cheaper in the longterm) + +var useEleTxrCaching = true; // whether to use individual ele texture caching underneath this cache + +// var log = function(){ console.log.apply( console, arguments ); }; + +var LayeredTextureCache = function LayeredTextureCache(renderer, eleTxrCache) { + var self = this; + + var r = self.renderer = renderer; + + self.layersByLevel = {}; // e.g. 2 => [ layer1, layer2, ..., layerN ] + + self.firstGet = true; + + self.lastInvalidationTime = util.performanceNow() - 2 * invalidThreshold; + + self.skipping = false; + + r.beforeRender(function (willDraw, now) { + if (now - self.lastInvalidationTime <= invalidThreshold) { + self.skipping = true; + } else { + self.skipping = false; + } + }); + + var qSort = function qSort(a, b) { + return b.reqs - a.reqs; + }; + + self.layersQueue = new Heap(qSort); + + self.eleTxrCache = eleTxrCache; + + self.setupEleCacheInvalidation(); + + self.setupDequeueing(); +}; + +var LTCp = LayeredTextureCache.prototype; + +var layerIdPool = 0; +var MAX_INT = Math.pow(2, 53) - 1; + +LTCp.makeLayer = function (bb, lvl) { + var scale = Math.pow(2, lvl); + + var w = Math.ceil(bb.w * scale); + var h = Math.ceil(bb.h * scale); + + var canvas = document.createElement('canvas'); // eslint-disable-line no-undef + + canvas.width = w; + canvas.height = h; + + var layer = { + id: layerIdPool = ++layerIdPool % MAX_INT, + bb: bb, + level: lvl, + width: w, + height: h, + canvas: canvas, + context: canvas.getContext('2d'), + eles: [], + elesQueue: [], + reqs: 0 + }; + + // log('make layer %s with w %s and h %s and lvl %s', layer.id, layer.width, layer.height, layer.level); + + var cxt = layer.context; + var dx = -layer.bb.x1; + var dy = -layer.bb.y1; + + // do the transform on creation to save cycles (it's the same for all eles) + cxt.scale(scale, scale); + cxt.translate(dx, dy); + + return layer; +}; + +LTCp.getLayers = function (eles, pxRatio, lvl) { + var self = this; + var r = self.renderer; + var cy = r.cy; + var zoom = cy.zoom(); + var firstGet = self.firstGet; + + self.firstGet = false; + + // log('--\nget layers with %s eles', eles.length); + //log eles.map(function(ele){ return ele.id() }) ); + + if (lvl == null) { + lvl = Math.ceil(math.log2(zoom * pxRatio)); + + if (lvl < minLvl) { + lvl = minLvl; + } else if (zoom >= maxZoom || lvl > maxLvl) { + return null; + } + } + + self.validateLayersElesOrdering(lvl, eles); + + var layersByLvl = self.layersByLevel; + var scale = Math.pow(2, lvl); + var layers = layersByLvl[lvl] = layersByLvl[lvl] || []; + var bb; + + var lvlComplete = self.levelIsComplete(lvl, eles); + var tmpLayers; + + var checkTempLevels = function checkTempLevels() { + var canUseAsTmpLvl = function canUseAsTmpLvl(l) { + self.validateLayersElesOrdering(l, eles); + + if (self.levelIsComplete(l, eles)) { + tmpLayers = layersByLvl[l]; + return true; + } + }; + + var checkLvls = function checkLvls(dir) { + if (tmpLayers) { + return; + } + + for (var l = lvl + dir; minLvl <= l && l <= maxLvl; l += dir) { + if (canUseAsTmpLvl(l)) { + break; + } + } + }; + + checkLvls(+1); + checkLvls(-1); + + // remove the invalid layers; they will be replaced as needed later in this function + for (var i = layers.length - 1; i >= 0; i--) { + var layer = layers[i]; + + if (layer.invalid) { + util.removeFromArray(layers, layer); + } + } + }; + + if (!lvlComplete) { + // if the current level is incomplete, then use the closest, best quality layerset temporarily + // and later queue the current layerset so we can get the proper quality level soon + + checkTempLevels(); + } else { + // log('level complete, using existing layers\n--'); + return layers; + } + + var getBb = function getBb() { + if (!bb) { + bb = math.makeBoundingBox(); + + for (var i = 0; i < eles.length; i++) { + math.updateBoundingBox(bb, eles[i].boundingBox()); + } + } + + return bb; + }; + + var makeLayer = function makeLayer(opts) { + opts = opts || {}; + + var after = opts.after; + + getBb(); + + var area = bb.w * scale * (bb.h * scale); + + if (area > maxLayerArea) { + return null; + } + + var layer = self.makeLayer(bb, lvl); + + if (after != null) { + var index = layers.indexOf(after) + 1; + + layers.splice(index, 0, layer); + } else if (opts.insert === undefined || opts.insert) { + // no after specified => first layer made so put at start + layers.unshift(layer); + } + + // if( tmpLayers ){ + //self.queueLayer( layer ); + // } + + return layer; + }; + + if (self.skipping && !firstGet) { + // log('skip layers'); + return null; + } + + // log('do layers'); + + var layer = null; + var maxElesPerLayer = eles.length / defNumLayers; + var allowLazyQueueing = alwaysQueue && !firstGet; + + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; + var rs = ele._private.rscratch; + var caches = rs.imgLayerCaches = rs.imgLayerCaches || {}; + + // log('look at ele', ele.id()); + + var existingLayer = caches[lvl]; + + if (existingLayer) { + // reuse layer for later eles + // log('reuse layer for', ele.id()); + layer = existingLayer; + continue; + } + + if (!layer || layer.eles.length >= maxElesPerLayer || !math.boundingBoxInBoundingBox(layer.bb, ele.boundingBox())) { + // log('make new layer for ele %s', ele.id()); + + layer = makeLayer({ insert: true, after: layer }); + + // if now layer can be built then we can't use layers at this level + if (!layer) { + return null; + } + + // log('new layer with id %s', layer.id); + } + + if (tmpLayers || allowLazyQueueing) { + // log('queue ele %s in layer %s', ele.id(), layer.id); + self.queueLayer(layer, ele); + } else { + // log('draw ele %s in layer %s', ele.id(), layer.id); + self.drawEleInLayer(layer, ele, lvl, pxRatio); + } + + layer.eles.push(ele); + + caches[lvl] = layer; + } + + // log('--'); + + if (tmpLayers) { + // then we only queued the current layerset and can't draw it yet + return tmpLayers; + } + + if (allowLazyQueueing) { + // log('lazy queue level', lvl); + return null; + } + + return layers; +}; + +// a layer may want to use an ele cache of a higher level to avoid blurriness +// so the layer level might not equal the ele level +LTCp.getEleLevelForLayerLevel = function (lvl, pxRatio) { + return lvl; +}; + +function imgSmoothing(context, bool) { + if (context.imageSmoothingEnabled != null) { + context.imageSmoothingEnabled = bool; + } else { + context.webkitImageSmoothingEnabled = bool; + context.mozImageSmoothingEnabled = bool; + context.msImageSmoothingEnabled = bool; + } +} + +LTCp.drawEleInLayer = function (layer, ele, lvl, pxRatio) { + var self = this; + var r = this.renderer; + var context = layer.context; + var bb = ele.boundingBox(); + + if (bb.w === 0 || bb.h === 0 || !ele.visible()) { + return; + } + + var eleCache = self.eleTxrCache; + var reason = useHighQualityEleTxrReqs ? eleCache.reasons.highQuality : undefined; + + lvl = self.getEleLevelForLayerLevel(lvl, pxRatio); + + var cache = useEleTxrCaching ? eleCache.getElement(ele, bb, null, lvl, reason) : null; + + if (cache) { + if (disableEleImgSmoothing) { + imgSmoothing(context, false); + } + + context.drawImage(cache.texture.canvas, cache.x, 0, cache.width, cache.height, bb.x1, bb.y1, bb.w, bb.h); + + if (disableEleImgSmoothing) { + imgSmoothing(context, true); + } + } else { + // if the element is not cacheable, then draw directly + r.drawElement(context, ele); + } +}; + +LTCp.levelIsComplete = function (lvl, eles) { + var self = this; + var layers = self.layersByLevel[lvl]; + + if (!layers || layers.length === 0) { + return false; + } + + var numElesInLayers = 0; + + for (var i = 0; i < layers.length; i++) { + var layer = layers[i]; + + // if there are any eles needed to be drawn yet, the level is not complete + if (layer.reqs > 0) { + return false; + } + + // if the layer is invalid, the level is not complete + if (layer.invalid) { + return false; + } + + numElesInLayers += layer.eles.length; + } + + // we should have exactly the number of eles passed in to be complete + if (numElesInLayers !== eles.length) { + return false; + } + + return true; +}; + +LTCp.validateLayersElesOrdering = function (lvl, eles) { + var layers = this.layersByLevel[lvl]; + + if (!layers) { + return; + } + + // if in a layer the eles are not in the same order, then the layer is invalid + // (i.e. there is an ele in between the eles in the layer) + + for (var i = 0; i < layers.length; i++) { + var layer = layers[i]; + var offset = -1; + + // find the offset + for (var j = 0; j < eles.length; j++) { + if (layer.eles[0] === eles[j]) { + offset = j; + break; + } + } + + if (offset < 0) { + // then the layer has nonexistant elements and is invalid + this.invalidateLayer(layer); + continue; + } + + // the eles in the layer must be in the same continuous order, else the layer is invalid + + var o = offset; + + for (var j = 0; j < layer.eles.length; j++) { + if (layer.eles[j] !== eles[o + j]) { + // log('invalidate based on ordering', layer.id); + + this.invalidateLayer(layer); + break; + } + } + } +}; + +LTCp.updateElementsInLayers = function (eles, update) { + var self = this; + var isEles = is.element(eles[0]); + + // collect udpated elements (cascaded from the layers) and update each + // layer itself along the way + for (var i = 0; i < eles.length; i++) { + var req = isEles ? null : eles[i]; + var ele = isEles ? eles[i] : eles[i].ele; + var rs = ele._private.rscratch; + var caches = rs.imgLayerCaches = rs.imgLayerCaches || {}; + + for (var l = minLvl; l <= maxLvl; l++) { + var layer = caches[l]; + + if (!layer) { + continue; + } + + // if update is a request from the ele cache, then it affects only + // the matching level + if (req && self.getEleLevelForLayerLevel(layer.level) !== req.level) { + continue; + } + + update(layer, ele, req); + } + } +}; + +LTCp.haveLayers = function () { + var self = this; + var haveLayers = false; + + for (var l = minLvl; l <= maxLvl; l++) { + var layers = self.layersByLevel[l]; + + if (layers && layers.length > 0) { + haveLayers = true; + break; + } + } + + return haveLayers; +}; + +LTCp.invalidateElements = function (eles) { + var self = this; + + self.lastInvalidationTime = util.performanceNow(); + + // log('update invalidate layer time from eles'); + + if (eles.length === 0 || !self.haveLayers()) { + return; + } + + self.updateElementsInLayers(eles, function invalAssocLayers(layer, ele, req) { + self.invalidateLayer(layer); + }); +}; + +LTCp.invalidateLayer = function (layer) { + // log('update invalidate layer time'); + + this.lastInvalidationTime = util.performanceNow(); + + if (layer.invalid) { + return; + } // save cycles + + var lvl = layer.level; + var eles = layer.eles; + var layers = this.layersByLevel[lvl]; + + // log('invalidate layer', layer.id ); + + util.removeFromArray(layers, layer); + // layer.eles = []; + + layer.elesQueue = []; + + layer.invalid = true; + + if (layer.replacement) { + layer.replacement.invalid = true; + } + + for (var i = 0; i < eles.length; i++) { + var caches = eles[i]._private.rscratch.imgLayerCaches; + + if (caches) { + caches[lvl] = null; + } + } +}; + +LTCp.refineElementTextures = function (eles) { + var self = this; + + // log('refine', eles.length); + + self.updateElementsInLayers(eles, function refineEachEle(layer, ele, req) { + var rLyr = layer.replacement; + + if (!rLyr) { + rLyr = layer.replacement = self.makeLayer(layer.bb, layer.level); + rLyr.replaces = layer; + rLyr.eles = layer.eles; + + // log('make replacement layer %s for %s with level %s', rLyr.id, layer.id, rLyr.level); + } + + if (!rLyr.reqs) { + for (var i = 0; i < rLyr.eles.length; i++) { + self.queueLayer(rLyr, rLyr.eles[i]); + } + + // log('queue replacement layer refinement', rLyr.id); + } + }); +}; + +LTCp.setupEleCacheInvalidation = function () { + var self = this; + var eleDeqs = []; + + if (!useEleTxrCaching) { + return; + } + + var updatedElesInLayers = util.debounce(function () { + self.refineElementTextures(eleDeqs); + + eleDeqs = []; + }, refineEleDebounceTime); + + self.eleTxrCache.onDequeue(function (reqs) { + for (var i = 0; i < reqs.length; i++) { + eleDeqs.push(reqs[i]); + } + + updatedElesInLayers(); + }); +}; + +LTCp.queueLayer = function (layer, ele) { + var self = this; + var q = self.layersQueue; + var elesQ = layer.elesQueue; + var hasId = elesQ.hasId = elesQ.hasId || {}; + + // if a layer is going to be replaced, queuing is a waste of time + if (layer.replacement) { + return; + } + + if (ele) { + if (hasId[ele.id()]) { + return; + } + + elesQ.push(ele); + hasId[ele.id()] = true; + } + + if (layer.reqs) { + layer.reqs++; + + q.updateItem(layer); + } else { + layer.reqs = 1; + + q.push(layer); + } +}; + +LTCp.dequeue = function (pxRatio) { + var self = this; + var q = self.layersQueue; + var deqd = []; + var eleDeqs = 0; + + while (eleDeqs < maxDeqSize) { + if (q.size() === 0) { + break; + } + + var layer = q.peek(); + + // if a layer has been or will be replaced, then don't waste time with it + if (layer.replacement) { + // log('layer %s in queue skipped b/c it already has a replacement', layer.id); + q.pop(); + continue; + } + + // if this is a replacement layer that has been superceded, then forget it + if (layer.replaces && layer !== layer.replaces.replacement) { + // log('layer is no longer the most uptodate replacement; dequeued', layer.id) + q.pop(); + continue; + } + + if (layer.invalid) { + // log('replacement layer %s is invalid; dequeued', layer.id); + q.pop(); + continue; + } + + var ele = layer.elesQueue.shift(); + + if (ele) { + // log('dequeue layer %s', layer.id); + + self.drawEleInLayer(layer, ele, layer.level, pxRatio); + + eleDeqs++; + } + + if (deqd.length === 0) { + // we need only one entry in deqd to queue redrawing etc + deqd.push(true); + } + + // if the layer has all its eles done, then remove from the queue + if (layer.elesQueue.length === 0) { + q.pop(); + + layer.reqs = 0; + + // log('dequeue of layer %s complete', layer.id); + + // when a replacement layer is dequeued, it replaces the old layer in the level + if (layer.replaces) { + self.applyLayerReplacement(layer); + } + + self.requestRedraw(); + } + } + + return deqd; +}; + +LTCp.applyLayerReplacement = function (layer) { + var self = this; + var layersInLevel = self.layersByLevel[layer.level]; + var replaced = layer.replaces; + var index = layersInLevel.indexOf(replaced); + + // if the replaced layer is not in the active list for the level, then replacing + // refs would be a mistake (i.e. overwriting the true active layer) + if (index < 0 || replaced.invalid) { + // log('replacement layer would have no effect', layer.id); + return; + } + + layersInLevel[index] = layer; // replace level ref + + // replace refs in eles + for (var i = 0; i < layer.eles.length; i++) { + var _p = layer.eles[i]._private; + var cache = _p.imgLayerCaches = _p.imgLayerCaches || {}; + + if (cache) { + cache[layer.level] = layer; + } + } + + // log('apply replacement layer %s over %s', layer.id, replaced.id); + + self.requestRedraw(); +}; + +LTCp.requestRedraw = util.debounce(function () { + var r = this.renderer; + + r.redrawHint('eles', true); + r.redrawHint('drag', true); + r.redraw(); +}, 100); + +LTCp.setupDequeueing = defs.setupDequeueing({ + deqRedrawThreshold: deqRedrawThreshold, + deqCost: deqCost, + deqAvgCost: deqAvgCost, + deqNoDrawCost: deqNoDrawCost, + deqFastCost: deqFastCost, + deq: function deq(self, pxRatio) { + return self.dequeue(pxRatio); + }, + onDeqd: util.noop, + shouldRedraw: util.trueify, + priority: function priority(self) { + return self.renderer.beforeRenderPriorities.lyrTxrDeq; + } +}); + +module.exports = LayeredTextureCache; + +/***/ }), +/* 127 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + var CRp = {}; var impl; -CRp.arrowShapeImpl = function( name ){ - return ( impl || (impl = { - 'polygon': function( context, points ){ - for( var i = 0; i < points.length; i++ ){ - var pt = points[ i ]; +CRp.arrowShapeImpl = function (name) { + return (impl || (impl = { + 'polygon': function polygon(context, points) { + for (var i = 0; i < points.length; i++) { + var pt = points[i]; - context.lineTo( pt.x, pt.y ); + context.lineTo(pt.x, pt.y); } }, - 'triangle-backcurve': function( context, points, controlPoint ){ + 'triangle-backcurve': function triangleBackcurve(context, points, controlPoint) { var firstPt; - for( var i = 0; i < points.length; i++ ){ - var pt = points[ i ]; + for (var i = 0; i < points.length; i++) { + var pt = points[i]; - if( i === 0 ){ + if (i === 0) { firstPt = pt; } - context.lineTo( pt.x, pt.y ); + context.lineTo(pt.x, pt.y); } - context.quadraticCurveTo( controlPoint.x, controlPoint.y, firstPt.x, firstPt.y ); + context.quadraticCurveTo(controlPoint.x, controlPoint.y, firstPt.x, firstPt.y); }, - 'triangle-tee': function( context, trianglePoints, teePoints ){ - if( context.beginPath ){ context.beginPath(); } + 'triangle-tee': function triangleTee(context, trianglePoints, teePoints) { + if (context.beginPath) { + context.beginPath(); + } - var triPts = trianglePoints; - for( var i = 0; i < triPts.length; i++ ){ - var pt = triPts[ i ]; + var triPts = trianglePoints; + for (var i = 0; i < triPts.length; i++) { + var pt = triPts[i]; - context.lineTo( pt.x, pt.y ); - } + context.lineTo(pt.x, pt.y); + } - if( context.closePath ){ context.closePath(); } + if (context.closePath) { + context.closePath(); + } - if( context.beginPath ){ context.beginPath(); } + if (context.beginPath) { + context.beginPath(); + } - var teePts = teePoints; - var firstTeePt = teePoints[0]; - context.moveTo( firstTeePt.x, firstTeePt.y ); + var teePts = teePoints; + var firstTeePt = teePoints[0]; + context.moveTo(firstTeePt.x, firstTeePt.y); - for( var i = 0; i < teePts.length; i++ ){ - var pt = teePts[ i ]; + for (var i = 0; i < teePts.length; i++) { + var pt = teePts[i]; - context.lineTo( pt.x, pt.y ); - } - - if( context.closePath ){ context.closePath(); } + context.lineTo(pt.x, pt.y); + } + if (context.closePath) { + context.closePath(); + } }, - 'circle': function( context, rx, ry, r ){ - context.arc( rx, ry, r, 0, Math.PI * 2, false ); + 'triangle-cross': function triangleCross(context, trianglePoints, crossLinePoints) { + if (context.beginPath) { + context.beginPath(); + } + + var triPts = trianglePoints; + for (var i = 0; i < triPts.length; i++) { + var pt = triPts[i]; + + context.lineTo(pt.x, pt.y); + } + + if (context.closePath) { + context.closePath(); + } + + if (context.beginPath) { + context.beginPath(); + } + + var teePts = crossLinePoints; + var firstTeePt = crossLinePoints[0]; + context.moveTo(firstTeePt.x, firstTeePt.y); + + for (var i = 0; i < teePts.length; i++) { + var pt = teePts[i]; + + context.lineTo(pt.x, pt.y); + } + if (context.closePath) { + context.closePath(); + } + }, + + 'circle': function circle(context, rx, ry, r) { + context.arc(rx, ry, r, 0, Math.PI * 2, false); } - }) )[ name ]; + }))[name]; }; module.exports = CRp; -},{}],65:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 128 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var math = __webpack_require__(2); var CRp = {}; -CRp.drawEdge = function( context, edge, shiftToOriginWithBb, drawLabel, drawOverlayInstead ){ - var rs = edge._private.rscratch; - var usePaths = this.usePaths(); - - // if bezier ctrl pts can not be calculated, then die - if( rs.badLine || isNaN(rs.allpts[0]) ){ // isNaN in case edge is impossible and browser bugs (e.g. safari) - return; - } - - // Edge line width - if( edge.pstyle( 'width' ).pfValue <= 0 ){ - return; - } - - var bb; - if( shiftToOriginWithBb ){ - bb = shiftToOriginWithBb; - - context.translate( -bb.x1, -bb.y1 ); - } - - var overlayPadding = edge.pstyle( 'overlay-padding' ).pfValue; - var overlayOpacity = edge.pstyle( 'overlay-opacity' ).value; - var overlayColor = edge.pstyle( 'overlay-color' ).value; - - // Edge color & opacity - if( drawOverlayInstead ){ - - if( overlayOpacity === 0 ){ // exit early if no overlay - return; - } - - this.strokeStyle( context, overlayColor[0], overlayColor[1], overlayColor[2], overlayOpacity ); - context.lineCap = 'round'; - - if( rs.edgeType == 'self' && !usePaths ){ - context.lineCap = 'butt'; - } +CRp.drawElement = function (context, ele, shiftToOriginWithBb, showLabel) { + var r = this; + if (ele.isNode()) { + r.drawNode(context, ele, shiftToOriginWithBb, showLabel); } else { - var lineColor = edge.pstyle( 'line-color' ).value; - - this.strokeStyle( context, lineColor[0], lineColor[1], lineColor[2], edge.pstyle( 'opacity' ).value ); - - context.lineCap = 'butt'; - } - - context.lineJoin = 'round'; - - var edgeWidth = edge.pstyle( 'width' ).pfValue + (drawOverlayInstead ? 2 * overlayPadding : 0); - var lineStyle = drawOverlayInstead ? 'solid' : edge.pstyle( 'line-style' ).value; - context.lineWidth = edgeWidth; - - var shadowBlur = edge.pstyle( 'shadow-blur' ).pfValue; - var shadowOpacity = edge.pstyle( 'shadow-opacity' ).value; - var shadowColor = edge.pstyle( 'shadow-color' ).value; - var shadowOffsetX = edge.pstyle( 'shadow-offset-x' ).pfValue; - var shadowOffsetY = edge.pstyle( 'shadow-offset-y' ).pfValue; - - this.shadowStyle( context, shadowColor, drawOverlayInstead ? 0 : shadowOpacity, shadowBlur, shadowOffsetX, shadowOffsetY ); - - this.drawEdgePath( - edge, - context, - rs.allpts, - lineStyle, - edgeWidth - ); - - this.drawArrowheads( context, edge, drawOverlayInstead ); - - this.shadowStyle( context, 'transparent', 0 ); // reset for next guy - - if( !drawOverlayInstead ){ - this.drawEdge( context, edge, false, drawLabel, true ); - } - - this.drawElementText( context, edge, drawLabel ); - - if( shiftToOriginWithBb ){ - context.translate( bb.x1, bb.y1 ); + r.drawEdge(context, ele, shiftToOriginWithBb, showLabel); } }; +CRp.drawCachedElement = function (context, ele, pxRatio, extent) { + var r = this; + var bb = ele.boundingBox(); -CRp.drawEdgePath = function( edge, context, pts, type, width ){ + if (bb.w === 0 || bb.h === 0) { + return; + } + + if (!extent || math.boundingBoxesIntersect(bb, extent)) { + var cache = r.data.eleTxrCache.getElement(ele, bb, pxRatio); + + if (cache != null) { + context.drawImage(cache.texture.canvas, cache.x, 0, cache.width, cache.height, bb.x1, bb.y1, bb.w, bb.h); + } else { + // if the element is not cacheable, then draw directly + r.drawElement(context, ele); + } + } +}; + +CRp.drawElements = function (context, eles) { + var r = this; + + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; + + r.drawElement(context, ele); + } +}; + +CRp.drawCachedElements = function (context, eles, pxRatio, extent) { + var r = this; + + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; + + r.drawCachedElement(context, ele, pxRatio, extent); + } +}; + +CRp.drawCachedNodes = function (context, eles, pxRatio, extent) { + var r = this; + + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; + + if (!ele.isNode()) { + continue; + } + + r.drawCachedElement(context, ele, pxRatio, extent); + } +}; + +CRp.drawLayeredElements = function (context, eles, pxRatio, extent) { + var r = this; + + var layers = r.data.lyrTxrCache.getLayers(eles, pxRatio); + + if (layers) { + for (var i = 0; i < layers.length; i++) { + var layer = layers[i]; + var bb = layer.bb; + + if (bb.w === 0 || bb.h === 0) { + continue; + } + + context.drawImage(layer.canvas, bb.x1, bb.y1, bb.w, bb.h); + } + } else { + // fall back on plain caching if no layers + r.drawCachedElements(context, eles, pxRatio, extent); + } +}; + +CRp.drawDebugPoints = function (context, eles) { + var draw = function draw(x, y, color) { + context.fillStyle = color; + context.fillRect(x - 1, y - 1, 3, 3); + }; + + for (var i = 0; i < eles.length; i++) { + var ele = eles[i]; + var rs = ele._private.rscratch; + + if (ele.isNode()) { + var p = ele.position(); + + draw(p.x, p.y, 'magenta'); + } else { + var pts = rs.allpts; + + for (var j = 0; j + 1 < pts.length; j += 2) { + var x = pts[j]; + var y = pts[j + 1]; + + draw(x, y, 'cyan'); + } + + draw(rs.midX, rs.midY, 'yellow'); + } + } +}; + +module.exports = CRp; + +/***/ }), +/* 129 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var CRp = {}; + +CRp.drawEdge = function (context, edge, shiftToOriginWithBb, drawLabel) { + var r = this; + var rs = edge._private.rscratch; + var usePaths = r.usePaths(); + + if (!edge.visible()) { + return; + } + + // if bezier ctrl pts can not be calculated, then die + if (rs.badLine || rs.allpts == null || isNaN(rs.allpts[0])) { + // isNaN in case edge is impossible and browser bugs (e.g. safari) + return; + } + + var bb = void 0; + if (shiftToOriginWithBb) { + bb = shiftToOriginWithBb; + + context.translate(-bb.x1, -bb.y1); + } + + var overlayPadding = edge.pstyle('overlay-padding').pfValue; + var overlayWidth = 2 * overlayPadding; + var overlayOpacity = edge.pstyle('overlay-opacity').value; + var overlayColor = edge.pstyle('overlay-color').value; + var lineColor = edge.pstyle('line-color').value; + var opacity = edge.pstyle('opacity').value; + var lineStyle = edge.pstyle('line-style').value; + var edgeWidth = edge.pstyle('width').pfValue; + + var drawLine = function drawLine() { + var strokeOpacity = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : opacity; + + context.lineWidth = edgeWidth; + context.lineCap = 'butt'; + + r.strokeStyle(context, lineColor[0], lineColor[1], lineColor[2], strokeOpacity); + + r.drawEdgePath(edge, context, rs.allpts, lineStyle); + }; + + var drawOverlay = function drawOverlay() { + var strokeOpacity = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : overlayOpacity; + + context.lineWidth = overlayWidth; + + if (rs.edgeType === 'self' && !usePaths) { + context.lineCap = 'butt'; + } else { + context.lineCap = 'round'; + } + + r.strokeStyle(context, overlayColor[0], overlayColor[1], overlayColor[2], strokeOpacity); + + r.drawEdgePath(edge, context, rs.allpts, 'solid'); + }; + + var drawArrows = function drawArrows() { + var arrowOpacity = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : opacity; + + r.drawArrowheads(context, edge, arrowOpacity); + }; + + var drawText = function drawText() { + r.drawElementText(context, edge, drawLabel); + }; + + context.lineJoin = 'round'; + + var ghost = edge.pstyle('ghost').value === 'yes'; + + if (ghost) { + var gx = edge.pstyle('ghost-offset-x').pfValue; + var gy = edge.pstyle('ghost-offset-y').pfValue; + var ghostOpacity = edge.pstyle('ghost-opacity').value; + var effectiveGhostOpacity = opacity * ghostOpacity; + + context.translate(gx, gy); + + drawLine(effectiveGhostOpacity); + drawArrows(effectiveGhostOpacity); + + context.translate(-gx, -gy); + } + + drawLine(); + drawArrows(); + drawOverlay(); + drawText(); + + if (shiftToOriginWithBb) { + context.translate(bb.x1, bb.y1); + } +}; + +CRp.drawEdgePath = function (edge, context, pts, type) { var rs = edge._private.rscratch; var canvasCxt = context; - var path; + var path = void 0; var pathCacheHit = false; var usePaths = this.usePaths(); - if( usePaths ){ - var pathCacheKey = pts.join( '$' ); + if (usePaths) { + var pathCacheKey = pts.join('$'); var keyMatches = rs.pathCacheKey && rs.pathCacheKey === pathCacheKey; - if( keyMatches ){ + if (keyMatches) { path = context = rs.pathCache; pathCacheHit = true; } else { @@ -16746,370 +27818,287 @@ CRp.drawEdgePath = function( edge, context, pts, type, width ){ } } - if( canvasCxt.setLineDash ){ // for very outofdate browsers - switch( type ){ + if (canvasCxt.setLineDash) { + // for very outofdate browsers + switch (type) { case 'dotted': - canvasCxt.setLineDash( [ 1, 1 ] ); + canvasCxt.setLineDash([1, 1]); break; case 'dashed': - canvasCxt.setLineDash( [ 6, 3 ] ); + canvasCxt.setLineDash([6, 3]); break; case 'solid': - canvasCxt.setLineDash( [ ] ); + canvasCxt.setLineDash([]); break; } } - if( !pathCacheHit && !rs.badLine ){ - if( context.beginPath ){ context.beginPath(); } - context.moveTo( pts[0], pts[1] ); + if (!pathCacheHit && !rs.badLine) { + if (context.beginPath) { + context.beginPath(); + } + context.moveTo(pts[0], pts[1]); - switch( rs.edgeType ){ + switch (rs.edgeType) { case 'bezier': case 'self': case 'compound': case 'multibezier': - for( var i = 2; i + 3 < pts.length; i += 4 ){ - context.quadraticCurveTo( pts[ i ], pts[ i + 1], pts[ i + 2], pts[ i + 3] ); + for (var i = 2; i + 3 < pts.length; i += 4) { + context.quadraticCurveTo(pts[i], pts[i + 1], pts[i + 2], pts[i + 3]); } break; case 'straight': case 'segments': case 'haystack': - for( var i = 2; i + 1 < pts.length; i += 2 ){ - context.lineTo( pts[ i ], pts[ i + 1] ); + for (var _i = 2; _i + 1 < pts.length; _i += 2) { + context.lineTo(pts[_i], pts[_i + 1]); } break; } } context = canvasCxt; - if( usePaths ){ - context.stroke( path ); + if (usePaths) { + context.stroke(path); } else { context.stroke(); } // reset any line dashes - if( context.setLineDash ){ // for very outofdate browsers - context.setLineDash( [ ] ); + if (context.setLineDash) { + // for very outofdate browsers + context.setLineDash([]); } - }; -CRp.drawArrowheads = function( context, edge, drawOverlayInstead ){ - if( drawOverlayInstead ){ return; } // don't do anything for overlays - +CRp.drawArrowheads = function (context, edge, opacity) { var rs = edge._private.rscratch; var isHaystack = rs.edgeType === 'haystack'; - if( !isHaystack ){ - this.drawArrowhead( context, edge, 'source', rs.arrowStartX, rs.arrowStartY, rs.srcArrowAngle ); + if (!isHaystack) { + this.drawArrowhead(context, edge, 'source', rs.arrowStartX, rs.arrowStartY, rs.srcArrowAngle, opacity); } - this.drawArrowhead( context, edge, 'mid-target', rs.midX, rs.midY, rs.midtgtArrowAngle ); + this.drawArrowhead(context, edge, 'mid-target', rs.midX, rs.midY, rs.midtgtArrowAngle, opacity); - this.drawArrowhead( context, edge, 'mid-source', rs.midX, rs.midY, rs.midsrcArrowAngle ); + this.drawArrowhead(context, edge, 'mid-source', rs.midX, rs.midY, rs.midsrcArrowAngle, opacity); - if( !isHaystack ){ - this.drawArrowhead( context, edge, 'target', rs.arrowEndX, rs.arrowEndY, rs.tgtArrowAngle ); + if (!isHaystack) { + this.drawArrowhead(context, edge, 'target', rs.arrowEndX, rs.arrowEndY, rs.tgtArrowAngle, opacity); } }; -CRp.drawArrowhead = function( context, edge, prefix, x, y, angle ){ - if( isNaN( x ) || x == null || isNaN( y ) || y == null || isNaN( angle ) || angle == null ){ return; } +CRp.drawArrowhead = function (context, edge, prefix, x, y, angle, opacity) { + if (isNaN(x) || x == null || isNaN(y) || y == null || isNaN(angle) || angle == null) { + return; + } var self = this; - var arrowShape = edge.pstyle( prefix + '-arrow-shape' ).value; - - if( arrowShape === 'none' ){ + var arrowShape = edge.pstyle(prefix + '-arrow-shape').value; + if (arrowShape === 'none') { return; } + var arrowClearFill = edge.pstyle(prefix + '-arrow-fill').value === 'hollow' ? 'both' : 'filled'; + var arrowFill = edge.pstyle(prefix + '-arrow-fill').value; + var edgeWidth = edge.pstyle('width').pfValue; + var edgeOpacity = edge.pstyle('opacity').value; + + if (opacity === undefined) { + opacity = edgeOpacity; + } + var gco = context.globalCompositeOperation; - var arrowClearFill = edge.pstyle( prefix + '-arrow-fill' ).value === 'hollow' ? 'both' : 'filled'; - var arrowFill = edge.pstyle( prefix + '-arrow-fill' ).value; - var opacity = edge.pstyle( 'opacity' ).value; - - if( arrowShape === 'half-triangle-overshot' ){ - arrowFill = 'hollow'; - arrowClearFill = 'hollow'; - } - - if( opacity !== 1 || arrowFill === 'hollow' ){ // then extra clear is needed + if (opacity !== 1 || arrowFill === 'hollow') { + // then extra clear is needed context.globalCompositeOperation = 'destination-out'; - self.fillStyle( context, 255, 255, 255, 1 ); - self.strokeStyle( context, 255, 255, 255, 1 ); + self.fillStyle(context, 255, 255, 255, 1); + self.strokeStyle(context, 255, 255, 255, 1); - self.drawArrowShape( edge, prefix, context, - arrowClearFill, edge.pstyle( 'width' ).pfValue, edge.pstyle( prefix + '-arrow-shape' ).value, - x, y, angle - ); + self.drawArrowShape(edge, prefix, context, arrowClearFill, edgeWidth, arrowShape, x, y, angle); context.globalCompositeOperation = gco; } // otherwise, the opaque arrow clears it for free :) - var color = edge.pstyle( prefix + '-arrow-color' ).value; - self.fillStyle( context, color[0], color[1], color[2], opacity ); - self.strokeStyle( context, color[0], color[1], color[2], opacity ); + var color = edge.pstyle(prefix + '-arrow-color').value; + self.fillStyle(context, color[0], color[1], color[2], opacity); + self.strokeStyle(context, color[0], color[1], color[2], opacity); - self.drawArrowShape( edge, prefix, context, - arrowFill, edge.pstyle( 'width' ).pfValue, edge.pstyle( prefix + '-arrow-shape' ).value, - x, y, angle - ); + self.drawArrowShape(edge, prefix, context, arrowFill, edgeWidth, arrowShape, x, y, angle); }; -CRp.drawArrowShape = function( edge, arrowType, context, fill, edgeWidth, shape, x, y, angle ){ +CRp.drawArrowShape = function (edge, arrowType, context, fill, edgeWidth, shape, x, y, angle) { var r = this; var usePaths = this.usePaths(); var rs = edge._private.rscratch; var pathCacheHit = false; - var path; + var path = void 0; var canvasContext = context; var translation = { x: x, y: y }; - var size = this.getArrowWidth( edgeWidth ); - var shapeImpl = r.arrowShapes[ shape ]; + var scale = edge.pstyle('arrow-scale').value; + var size = this.getArrowWidth(edgeWidth, scale); + var shapeImpl = r.arrowShapes[shape]; - if( usePaths ){ + if (usePaths) { var pathCacheKey = size + '$' + shape + '$' + angle + '$' + x + '$' + y; rs.arrowPathCacheKey = rs.arrowPathCacheKey || {}; rs.arrowPathCache = rs.arrowPathCache || {}; - var alreadyCached = rs.arrowPathCacheKey[ arrowType ] === pathCacheKey; - if( alreadyCached ){ - path = context = rs.arrowPathCache[ arrowType ]; + var alreadyCached = rs.arrowPathCacheKey[arrowType] === pathCacheKey; + if (alreadyCached) { + path = context = rs.arrowPathCache[arrowType]; pathCacheHit = true; } else { path = context = new Path2D(); // eslint-disable-line no-undef - rs.arrowPathCacheKey[ arrowType ] = pathCacheKey; - rs.arrowPathCache[ arrowType ] = path; + rs.arrowPathCacheKey[arrowType] = pathCacheKey; + rs.arrowPathCache[arrowType] = path; } } - if( context.beginPath ){ context.beginPath(); } - - if( !pathCacheHit ){ - shapeImpl.draw( context, size, angle, translation ); + if (context.beginPath) { + context.beginPath(); } - if( !shapeImpl.leavePathOpen && context.closePath ){ + if (!pathCacheHit) { + shapeImpl.draw(context, size, angle, translation, edgeWidth); + } + + if (!shapeImpl.leavePathOpen && context.closePath) { context.closePath(); } context = canvasContext; - if( fill === 'filled' || fill === 'both' ){ - if( usePaths ){ - context.fill( path ); + if (fill === 'filled' || fill === 'both') { + if (usePaths) { + context.fill(path); } else { context.fill(); } } - if( fill === 'hollow' || fill === 'both' ){ - context.lineWidth = ( shapeImpl.matchEdgeWidth ? edgeWidth : 1 ); + if (fill === 'hollow' || fill === 'both') { + context.lineWidth = shapeImpl.matchEdgeWidth ? edgeWidth : 1; context.lineJoin = 'miter'; - if( usePaths ){ - context.stroke( path ); + if (usePaths) { + context.stroke(path); } else { context.stroke(); } - } }; module.exports = CRp; -},{}],66:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 130 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; -var math = _dereq_( '../../../math' ); var CRp = {}; -CRp.drawElement = function( context, ele, shiftToOriginWithBb, showLabel ){ +CRp.safeDrawImage = function (context, img, ix, iy, iw, ih, x, y, w, h) { var r = this; - if( ele.isNode() ){ - r.drawNode( context, ele, shiftToOriginWithBb, showLabel ); - } else { - r.drawEdge( context, ele, shiftToOriginWithBb, showLabel ); + // detect problematic cases for old browsers with bad images (cheaper than try-catch) + if (iw <= 0 || ih <= 0 || w <= 0 || h <= 0) { + return; } + + context.drawImage(img, ix, iy, iw, ih, x, y, w, h); }; -CRp.drawCachedElement = function( context, ele, pxRatio, extent ){ +CRp.drawInscribedImage = function (context, img, node, index, nodeOpacity) { var r = this; - var bb = ele.boundingBox(); - - if( !extent || math.boundingBoxesIntersect( bb, extent ) ){ - var cache = r.data.eleTxrCache.getElement( ele, bb, pxRatio ); - - if( cache ){ - context.drawImage( cache.texture.canvas, cache.x, 0, cache.width, cache.height, bb.x1, bb.y1, bb.w, bb.h ); - } else { // if the element is not cacheable, then draw directly - r.drawElement( context, ele ); - } - } -}; - -CRp.drawElements = function( context, eles ){ - var r = this; - - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[ i ]; - - r.drawElement( context, ele ); - } -}; - -CRp.drawCachedElements = function( context, eles, pxRatio, extent ){ - var r = this; - - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[ i ]; - - r.drawCachedElement( context, ele, pxRatio, extent ); - } -}; - -CRp.drawCachedNodes = function( context, eles, pxRatio, extent ){ - var r = this; - - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[ i ]; - - if( !ele.isNode() ){ continue; } - - r.drawCachedElement( context, ele, pxRatio, extent ); - } -}; - -CRp.drawLayeredElements = function( context, eles, pxRatio, extent ){ - var r = this; - - var layers = r.data.lyrTxrCache.getLayers( eles, pxRatio ); - - if( layers ){ - for( var i = 0; i < layers.length; i++ ){ - var layer = layers[i]; - var bb = layer.bb; - - context.drawImage( layer.canvas, bb.x1, bb.y1, bb.w, bb.h ); - } - } else { // fall back on plain caching if no layers - r.drawCachedElements( context, eles, pxRatio, extent ); - } -}; - -module.exports = CRp; - -},{"../../../math":85}],67:[function(_dereq_,module,exports){ -'use strict'; - -var CRp = {}; - -CRp.safeDrawImage = function( context, img, ix, iy, iw, ih, x, y, w, h ){ - var r = this; - - try { - context.drawImage( img, ix, iy, iw, ih, x, y, w, h ); - } catch( e ){ - r.redrawHint( 'eles', true ); - r.redrawHint( 'drag', true ); - - r.drawingImage = true; - - r.redraw(); - } -}; - -CRp.drawInscribedImage = function( context, img, node ){ - var r = this; - var nodeX = node._private.position.x; - var nodeY = node._private.position.y; - var fit = node.pstyle( 'background-fit' ).value; - var xPos = node.pstyle( 'background-position-x' ); - var yPos = node.pstyle( 'background-position-y' ); - var repeat = node.pstyle( 'background-repeat' ).value; + var pos = node.position(); + var nodeX = pos.x; + var nodeY = pos.y; + var styleObj = node.cy().style(); + var getIndexedStyle = styleObj.getIndexedStyle.bind(styleObj); + var fit = getIndexedStyle(node, 'background-fit', 'value', index); + var repeat = getIndexedStyle(node, 'background-repeat', 'value', index); var nodeW = node.width(); var nodeH = node.height(); + var paddingX2 = node.padding() * 2; + var nodeTW = nodeW + (getIndexedStyle(node, 'background-width-relative-to', 'value', index) === 'inner' ? 0 : paddingX2); + var nodeTH = nodeH + (getIndexedStyle(node, 'background-height-relative-to', 'value', index) === 'inner' ? 0 : paddingX2); var rs = node._private.rscratch; - var clip = node.pstyle( 'background-clip' ).value; + var clip = node.pstyle('background-clip').value; var shouldClip = clip === 'node'; - var imgOpacity = node.pstyle( 'background-image-opacity' ).value; + var imgOpacity = getIndexedStyle(node, 'background-image-opacity', 'value', index) * nodeOpacity; var imgW = img.width || img.cachedW; var imgH = img.height || img.cachedH; // workaround for broken browsers like ie - if( null == imgW || null == imgH ){ - document.body.appendChild( img ); // eslint-disable-line no-undef + if (null == imgW || null == imgH) { + document.body.appendChild(img); // eslint-disable-line no-undef imgW = img.cachedW = img.width || img.offsetWidth; imgH = img.cachedH = img.height || img.offsetHeight; - document.body.removeChild( img ); // eslint-disable-line no-undef + document.body.removeChild(img); // eslint-disable-line no-undef } var w = imgW; var h = imgH; - var bgW = node.pstyle( 'background-width' ); - if( bgW.value !== 'auto' ){ - if( bgW.units === '%' ){ - w = bgW.value / 100 * nodeW; + if (getIndexedStyle(node, 'background-width', 'value', index) !== 'auto') { + if (getIndexedStyle(node, 'background-width', 'units', index) === '%') { + w = getIndexedStyle(node, 'background-width', 'pfValue', index) * nodeTW; } else { - w = bgW.pfValue; + w = getIndexedStyle(node, 'background-width', 'pfValue', index); } } - var bgH = node.pstyle( 'background-height' ); - if( bgH.value !== 'auto' ){ - if( bgH.units === '%' ){ - h = bgH.value / 100 * nodeH; + if (getIndexedStyle(node, 'background-height', 'value', index) !== 'auto') { + if (getIndexedStyle(node, 'background-height', 'units', index) === '%') { + h = getIndexedStyle(node, 'background-height', 'pfValue', index) * nodeTH; } else { - h = bgH.pfValue; + h = getIndexedStyle(node, 'background-height', 'pfValue', index); } } - if( w === 0 || h === 0 ){ + if (w === 0 || h === 0) { return; // no point in drawing empty image (and chrome is broken in this case) } - if( fit === 'contain' ){ - var scale = Math.min( nodeW / w, nodeH / h ); + if (fit === 'contain') { + var scale = Math.min(nodeTW / w, nodeTH / h); w *= scale; h *= scale; - - } else if( fit === 'cover' ){ - var scale = Math.max( nodeW / w, nodeH / h ); + } else if (fit === 'cover') { + var scale = Math.max(nodeTW / w, nodeTH / h); w *= scale; h *= scale; } - var x = (nodeX - nodeW / 2); // left - if( xPos.units === '%' ){ - x += (nodeW - w) * xPos.value / 100; + var x = nodeX - nodeTW / 2; // left + if (getIndexedStyle(node, 'background-position-x', 'units', index) === '%') { + x += (nodeTW - w) * getIndexedStyle(node, 'background-position-x', 'pfValue', index); } else { - x += xPos.pfValue; + x += getIndexedStyle(node, 'background-position-x', 'pfValue', index); } - var y = (nodeY - nodeH / 2); // top - if( yPos.units === '%' ){ - y += (nodeH - h) * yPos.value / 100; + var y = nodeY - nodeTH / 2; // top + if (getIndexedStyle(node, 'background-position-y', 'units', index) === '%') { + y += (nodeTH - h) * getIndexedStyle(node, 'background-position-y', 'pfValue', index); } else { - y += yPos.pfValue; + y += getIndexedStyle(node, 'background-position-y', 'pfValue', index); } - if( rs.pathCache ){ + if (rs.pathCache) { x -= nodeX; y -= nodeY; @@ -17121,93 +28110,96 @@ CRp.drawInscribedImage = function( context, img, node ){ context.globalAlpha = imgOpacity; - if( repeat === 'no-repeat' ){ + if (repeat === 'no-repeat') { - if( shouldClip ){ + if (shouldClip) { context.save(); - if( rs.pathCache ){ - context.clip( rs.pathCache ); + if (rs.pathCache) { + context.clip(rs.pathCache); } else { - r.nodeShapes[ r.getNodeShape( node ) ].draw( - context, - nodeX, nodeY, - nodeW, nodeH ); + r.nodeShapes[r.getNodeShape(node)].draw(context, nodeX, nodeY, nodeTW, nodeTH); context.clip(); } } - r.safeDrawImage( context, img, 0, 0, imgW, imgH, x, y, w, h ); + r.safeDrawImage(context, img, 0, 0, imgW, imgH, x, y, w, h); - if( shouldClip ){ + if (shouldClip) { context.restore(); } } else { - var pattern = context.createPattern( img, repeat ); + var pattern = context.createPattern(img, repeat); context.fillStyle = pattern; - r.nodeShapes[ r.getNodeShape( node ) ].draw( - context, - nodeX, nodeY, - nodeW, nodeH ); + r.nodeShapes[r.getNodeShape(node)].draw(context, nodeX, nodeY, nodeTW, nodeTH); - context.translate( x, y ); + context.translate(x, y); context.fill(); - context.translate( -x, -y ); + context.translate(-x, -y); } context.globalAlpha = gAlpha; - }; module.exports = CRp; -},{}],68:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 131 */ +/***/ (function(module, exports, __webpack_require__) { -var util = _dereq_( '../../../util' ); -var math = _dereq_( '../../../math' ); +"use strict"; + + +var util = __webpack_require__(1); +var math = __webpack_require__(2); var CRp = {}; -CRp.eleTextBiggerThanMin = function( ele, scale ){ - if( !scale ){ +CRp.eleTextBiggerThanMin = function (ele, scale) { + if (!scale) { var zoom = ele.cy().zoom(); var pxRatio = this.getPixelRatio(); - var lvl = Math.ceil( math.log2( zoom * pxRatio ) ); // the effective texture level + var lvl = Math.ceil(math.log2(zoom * pxRatio)); // the effective texture level - scale = Math.pow( 2, lvl ); + scale = Math.pow(2, lvl); } - var computedSize = ele.pstyle( 'font-size' ).pfValue * scale; - var minSize = ele.pstyle( 'min-zoomed-font-size' ).pfValue; + var computedSize = ele.pstyle('font-size').pfValue * scale; + var minSize = ele.pstyle('min-zoomed-font-size').pfValue; - if( computedSize < minSize ){ + if (computedSize < minSize) { return false; } return true; }; -CRp.drawElementText = function( context, ele, force ){ +CRp.drawElementText = function (context, ele, force) { var r = this; - if( force === undefined ){ - if( !r.eleTextBiggerThanMin( ele ) ){ return; } + if (force === undefined) { + if (!r.eleTextBiggerThanMin(ele)) { + return; + } } else { - if( !force ){ return; } + if (!force) { + return; + } } - if( ele.isNode() ){ - var label = ele.pstyle( 'label' ); + if (ele.isNode()) { + var label = ele.pstyle('label'); - if( !label || !label.value ){ return; } + if (!label || !label.value) { + return; + } - var textHalign = ele.pstyle( 'text-halign' ).strValue; - var textValign = ele.pstyle( 'text-valign' ).strValue; + var textHalign = ele.pstyle('text-halign').strValue; + var textValign = ele.pstyle('text-valign').strValue; - switch( textHalign ){ + switch (textHalign) { case 'left': context.textAlign = 'right'; break; @@ -17216,21 +28208,18 @@ CRp.drawElementText = function( context, ele, force ){ context.textAlign = 'left'; break; - default: // e.g. center + default: + // e.g. center context.textAlign = 'center'; } context.textBaseline = 'bottom'; } else { - var label = ele.pstyle( 'label' ); - var srcLabel = ele.pstyle( 'source-label' ); - var tgtLabel = ele.pstyle( 'target-label' ); + var label = ele.pstyle('label'); + var srcLabel = ele.pstyle('source-label'); + var tgtLabel = ele.pstyle('target-label'); - if( - ( !label || !label.value ) - && ( !srcLabel || !srcLabel.value ) - && ( !tgtLabel || !tgtLabel.value ) - ){ + if ((!label || !label.value) && (!srcLabel || !srcLabel.value) && (!tgtLabel || !tgtLabel.value)) { return; } @@ -17238,27 +28227,26 @@ CRp.drawElementText = function( context, ele, force ){ context.textBaseline = 'bottom'; } + r.drawText(context, ele); - r.drawText( context, ele ); + if (ele.isEdge()) { + r.drawText(context, ele, 'source'); - if( ele.isEdge() ){ - r.drawText( context, ele, 'source' ); - - r.drawText( context, ele, 'target' ); + r.drawText(context, ele, 'target'); } }; CRp.drawNodeText = CRp.drawEdgeText = CRp.drawElementText; -CRp.getFontCache = function( context ){ +CRp.getFontCache = function (context) { var cache; this.fontCaches = this.fontCaches || []; - for( var i = 0; i < this.fontCaches.length; i++ ){ - cache = this.fontCaches[ i ]; + for (var i = 0; i < this.fontCaches.length; i++) { + cache = this.fontCaches[i]; - if( cache.context === context ){ + if (cache.context === context) { return cache; } } @@ -17266,34 +28254,29 @@ CRp.getFontCache = function( context ){ cache = { context: context }; - this.fontCaches.push( cache ); + this.fontCaches.push(cache); return cache; }; // set up canvas context with font // returns transformed text string -CRp.setupTextStyle = function( context, ele ){ +CRp.setupTextStyle = function (context, ele) { // Font style var parentOpacity = ele.effectiveOpacity(); - var labelStyle = ele.pstyle( 'font-style' ).strValue; - var labelSize = ele.pstyle( 'font-size' ).pfValue + 'px'; - var labelFamily = ele.pstyle( 'font-family' ).strValue; - var labelWeight = ele.pstyle( 'font-weight' ).strValue; - var opacity = ele.pstyle( 'text-opacity' ).value * ele.pstyle( 'opacity' ).value * parentOpacity; - var outlineOpacity = ele.pstyle( 'text-outline-opacity' ).value * opacity; - var color = ele.pstyle( 'color' ).value; - var outlineColor = ele.pstyle( 'text-outline-color' ).value; - var shadowBlur = ele.pstyle( 'text-shadow-blur' ).pfValue; - var shadowOpacity = ele.pstyle( 'text-shadow-opacity' ).value; - var shadowColor = ele.pstyle( 'text-shadow-color' ).value; - var shadowOffsetX = ele.pstyle( 'text-shadow-offset-x' ).pfValue; - var shadowOffsetY = ele.pstyle( 'text-shadow-offset-y' ).pfValue; + var labelStyle = ele.pstyle('font-style').strValue; + var labelSize = ele.pstyle('font-size').pfValue + 'px'; + var labelFamily = ele.pstyle('font-family').strValue; + var labelWeight = ele.pstyle('font-weight').strValue; + var opacity = ele.pstyle('text-opacity').value * ele.pstyle('opacity').value * parentOpacity; + var outlineOpacity = ele.pstyle('text-outline-opacity').value * opacity; + var color = ele.pstyle('color').value; + var outlineColor = ele.pstyle('text-outline-color').value; var fontCacheKey = ele._private.fontKey; - var cache = this.getFontCache( context ); + var cache = this.getFontCache(context); - if( cache.key !== fontCacheKey ){ + if (cache.key !== fontCacheKey) { context.font = labelStyle + ' ' + labelWeight + ' ' + labelSize + ' ' + labelFamily; cache.key = fontCacheKey; @@ -17304,59 +28287,57 @@ CRp.setupTextStyle = function( context, ele ){ // so text outlines aren't jagged context.lineJoin = 'round'; - this.fillStyle( context, color[ 0 ], color[ 1 ], color[ 2 ], opacity ); + this.fillStyle(context, color[0], color[1], color[2], opacity); - this.strokeStyle( context, outlineColor[ 0 ], outlineColor[ 1 ], outlineColor[ 2 ], outlineOpacity ); - - this.shadowStyle( context, shadowColor, shadowOpacity, shadowBlur, shadowOffsetX, shadowOffsetY ); + this.strokeStyle(context, outlineColor[0], outlineColor[1], outlineColor[2], outlineOpacity); }; -function roundRect( ctx, x, y, width, height, radius ){ +function roundRect(ctx, x, y, width, height, radius) { var radius = radius || 5; ctx.beginPath(); - ctx.moveTo( x + radius, y ); - ctx.lineTo( x + width - radius, y ); - ctx.quadraticCurveTo( x + width, y, x + width, y + radius ); - ctx.lineTo( x + width, y + height - radius ); - ctx.quadraticCurveTo( x + width, y + height, x + width - radius, y + height ); - ctx.lineTo( x + radius, y + height ); - ctx.quadraticCurveTo( x, y + height, x, y + height - radius ); - ctx.lineTo( x, y + radius ); - ctx.quadraticCurveTo( x, y, x + radius, y ); + ctx.moveTo(x + radius, y); + ctx.lineTo(x + width - radius, y); + ctx.quadraticCurveTo(x + width, y, x + width, y + radius); + ctx.lineTo(x + width, y + height - radius); + ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height); + ctx.lineTo(x + radius, y + height); + ctx.quadraticCurveTo(x, y + height, x, y + height - radius); + ctx.lineTo(x, y + radius); + ctx.quadraticCurveTo(x, y, x + radius, y); ctx.closePath(); ctx.fill(); } // Draw text -CRp.drawText = function( context, ele, prefix ){ +CRp.drawText = function (context, ele, prefix) { var _p = ele._private; var rscratch = _p.rscratch; var parentOpacity = ele.effectiveOpacity(); - if( parentOpacity === 0 || ele.pstyle( 'text-opacity' ).value === 0 ){ + if (parentOpacity === 0 || ele.pstyle('text-opacity').value === 0) { return; } - var textX = util.getPrefixedProperty( rscratch, 'labelX', prefix ); - var textY = util.getPrefixedProperty( rscratch, 'labelY', prefix ); - var text = this.getLabelText( ele, prefix ); + var textX = util.getPrefixedProperty(rscratch, 'labelX', prefix); + var textY = util.getPrefixedProperty(rscratch, 'labelY', prefix); + var text = this.getLabelText(ele, prefix); - if( text != null && text !== '' && !isNaN( textX ) && !isNaN( textY ) ){ - this.setupTextStyle( context, ele ); + if (text != null && text !== '' && !isNaN(textX) && !isNaN(textY)) { + this.setupTextStyle(context, ele); var pdash = prefix ? prefix + '-' : ''; - var textW = util.getPrefixedProperty( rscratch, 'labelWidth', prefix ); - var textH = util.getPrefixedProperty( rscratch, 'labelHeight', prefix ); - var textAngle = util.getPrefixedProperty( rscratch, 'labelAngle', prefix ); - var marginX = ele.pstyle( pdash + 'text-margin-x' ).pfValue; - var marginY = ele.pstyle( pdash + 'text-margin-y' ).pfValue; + var textW = util.getPrefixedProperty(rscratch, 'labelWidth', prefix); + var textH = util.getPrefixedProperty(rscratch, 'labelHeight', prefix); + var textAngle = util.getPrefixedProperty(rscratch, 'labelAngle', prefix); + var marginX = ele.pstyle(pdash + 'text-margin-x').pfValue; + var marginY = ele.pstyle(pdash + 'text-margin-y').pfValue; var isEdge = ele.isEdge(); var isNode = ele.isNode(); - var halign = ele.pstyle( 'text-halign' ).value; - var valign = ele.pstyle( 'text-valign' ).value; + var halign = ele.pstyle('text-halign').value; + var valign = ele.pstyle('text-valign').value; - if( isEdge ){ + if (isEdge) { halign = 'center'; valign = 'center'; } @@ -17364,42 +28345,29 @@ CRp.drawText = function( context, ele, prefix ){ textX += marginX; textY += marginY; - var rotation = ele.pstyle( 'text-rotation' ); + var rotation = ele.pstyle(pdash + 'text-rotation'); var theta; - if( rotation.strValue === 'autorotate' ){ + if (rotation.strValue === 'autorotate') { theta = isEdge ? textAngle : 0; - } else if( rotation.strValue === 'none' ){ + } else if (rotation.strValue === 'none') { theta = 0; } else { theta = rotation.pfValue; } - if( theta !== 0 ){ + if (theta !== 0) { var orgTextX = textX; var orgTextY = textY; - context.translate( orgTextX, orgTextY ); - context.rotate( theta ); + context.translate(orgTextX, orgTextY); + context.rotate(theta); textX = 0; textY = 0; } - if( isNode ){ - var pLeft = ele.pstyle( 'padding-left' ).pfValue; - var pRight = ele.pstyle( 'padding-right' ).pfValue; - var pTop = ele.pstyle( 'padding-top' ).pfValue; - var pBottom = ele.pstyle( 'padding-bottom' ).pfValue; - - textX += pLeft / 2; - textX -= pRight / 2; - - textY += pTop / 2; - textY -= pBottom / 2; - } - - switch( valign ){ + switch (valign) { case 'top': break; case 'center': @@ -17410,14 +28378,15 @@ CRp.drawText = function( context, ele, prefix ){ break; } - var backgroundOpacity = ele.pstyle( 'text-background-opacity' ).value; - var borderOpacity = ele.pstyle( 'text-border-opacity' ).value; - var textBorderWidth = ele.pstyle( 'text-border-width' ).pfValue; + var backgroundOpacity = ele.pstyle('text-background-opacity').value; + var borderOpacity = ele.pstyle('text-border-opacity').value; + var textBorderWidth = ele.pstyle('text-border-width').pfValue; + var backgroundPadding = ele.pstyle('text-background-padding').pfValue; - if( backgroundOpacity > 0 || ( textBorderWidth > 0 && borderOpacity > 0 ) ){ - var bgX = textX; + if (backgroundOpacity > 0 || textBorderWidth > 0 && borderOpacity > 0) { + var bgX = textX - backgroundPadding; - switch( halign ){ + switch (halign) { case 'left': bgX -= textW; break; @@ -17428,453 +28397,467 @@ CRp.drawText = function( context, ele, prefix ){ break; } - var bgY = textY; + var bgY = textY - textH - backgroundPadding; + var bgW = textW + 2 * backgroundPadding; + var bgH = textH + 2 * backgroundPadding; - switch( valign ){ - case 'top': - bgY -= textH; - break; - case 'center': - bgY -= textH / 2; - break; - case 'bottom': - break; - } - - if( backgroundOpacity > 0 ){ + if (backgroundOpacity > 0) { var textFill = context.fillStyle; - var textBackgroundColor = ele.pstyle( 'text-background-color' ).value; + var textBackgroundColor = ele.pstyle('text-background-color').value; - context.fillStyle = 'rgba(' + textBackgroundColor[ 0 ] + ',' + textBackgroundColor[ 1 ] + ',' + textBackgroundColor[ 2 ] + ',' + backgroundOpacity * parentOpacity + ')'; - var styleShape = ele.pstyle( 'text-background-shape' ).strValue; - if( styleShape == 'roundrectangle' ){ - roundRect( context, bgX, bgY, textW, textH, 2 ); + context.fillStyle = 'rgba(' + textBackgroundColor[0] + ',' + textBackgroundColor[1] + ',' + textBackgroundColor[2] + ',' + backgroundOpacity * parentOpacity + ')'; + var styleShape = ele.pstyle('text-background-shape').strValue; + if (styleShape == 'roundrectangle') { + roundRect(context, bgX, bgY, bgW, bgH, 2); } else { - context.fillRect( bgX, bgY, textW, textH ); + context.fillRect(bgX, bgY, bgW, bgH); } context.fillStyle = textFill; } - if( textBorderWidth > 0 && borderOpacity > 0 ){ + if (textBorderWidth > 0 && borderOpacity > 0) { var textStroke = context.strokeStyle; var textLineWidth = context.lineWidth; - var textBorderColor = ele.pstyle( 'text-border-color' ).value; - var textBorderStyle = ele.pstyle( 'text-border-style' ).value; + var textBorderColor = ele.pstyle('text-border-color').value; + var textBorderStyle = ele.pstyle('text-border-style').value; - context.strokeStyle = 'rgba(' + textBorderColor[ 0 ] + ',' + textBorderColor[ 1 ] + ',' + textBorderColor[ 2 ] + ',' + borderOpacity * parentOpacity + ')'; + context.strokeStyle = 'rgba(' + textBorderColor[0] + ',' + textBorderColor[1] + ',' + textBorderColor[2] + ',' + borderOpacity * parentOpacity + ')'; context.lineWidth = textBorderWidth; - if( context.setLineDash ){ // for very outofdate browsers - switch( textBorderStyle ){ + if (context.setLineDash) { + // for very outofdate browsers + switch (textBorderStyle) { case 'dotted': - context.setLineDash( [ 1, 1 ] ); + context.setLineDash([1, 1]); break; case 'dashed': - context.setLineDash( [ 4, 2 ] ); + context.setLineDash([4, 2]); break; case 'double': context.lineWidth = textBorderWidth / 4; // 50% reserved for white between the two borders - context.setLineDash( [] ); + context.setLineDash([]); break; case 'solid': - context.setLineDash( [] ); + context.setLineDash([]); break; } } - context.strokeRect( bgX, bgY, textW, textH ); + context.strokeRect(bgX, bgY, bgW, bgH); - if( textBorderStyle === 'double' ){ + if (textBorderStyle === 'double') { var whiteWidth = textBorderWidth / 2; - context.strokeRect( bgX + whiteWidth, bgY + whiteWidth, textW - whiteWidth * 2, textH - whiteWidth * 2 ); + context.strokeRect(bgX + whiteWidth, bgY + whiteWidth, bgW - whiteWidth * 2, bgH - whiteWidth * 2); } - if( context.setLineDash ){ // for very outofdate browsers - context.setLineDash( [] ); + if (context.setLineDash) { + // for very outofdate browsers + context.setLineDash([]); } context.lineWidth = textLineWidth; context.strokeStyle = textStroke; } - } - var lineWidth = 2 * ele.pstyle( 'text-outline-width' ).pfValue; // *2 b/c the stroke is drawn centred on the middle + var lineWidth = 2 * ele.pstyle('text-outline-width').pfValue; // *2 b/c the stroke is drawn centred on the middle - if( lineWidth > 0 ){ + if (lineWidth > 0) { context.lineWidth = lineWidth; } - if( ele.pstyle( 'text-wrap' ).value === 'wrap' ){ - var lines = rscratch.labelWrapCachedLines; + if (ele.pstyle('text-wrap').value === 'wrap') { + var lines = util.getPrefixedProperty(rscratch, 'labelWrapCachedLines', prefix); var lineHeight = textH / lines.length; - switch( valign ){ + switch (valign) { case 'top': - textY -= ( lines.length - 1 ) * lineHeight; + textY -= (lines.length - 1) * lineHeight; break; - - case 'bottom': - // nothing required - break; - - default: case 'center': - textY -= ( lines.length - 1 ) * lineHeight / 2; + case 'bottom': + textY -= (lines.length - 1) * lineHeight; + break; } - for( var l = 0; l < lines.length; l++ ){ - if( lineWidth > 0 ){ - context.strokeText( lines[ l ], textX, textY ); + for (var l = 0; l < lines.length; l++) { + if (lineWidth > 0) { + context.strokeText(lines[l], textX, textY); } - context.fillText( lines[ l ], textX, textY ); + context.fillText(lines[l], textX, textY); textY += lineHeight; } - } else { - if( lineWidth > 0 ){ - context.strokeText( text, textX, textY ); + if (lineWidth > 0) { + context.strokeText(text, textX, textY); } - context.fillText( text, textX, textY ); + context.fillText(text, textX, textY); } - if( theta !== 0 ){ - context.rotate( -theta ); - context.translate( -orgTextX, -orgTextY ); + if (theta !== 0) { + context.rotate(-theta); + context.translate(-orgTextX, -orgTextY); } - - this.shadowStyle( context, 'transparent', 0 ); // reset for next guy } }; module.exports = CRp; -},{"../../../math":85,"../../../util":100}],69:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 132 */ +/***/ (function(module, exports, __webpack_require__) { -var is = _dereq_( '../../../is' ); +"use strict"; + + +/* global Path2D */ + +var is = __webpack_require__(0); var CRp = {}; -CRp.drawNode = function( context, node, shiftToOriginWithBb, drawLabel ){ +CRp.drawNode = function (context, node, shiftToOriginWithBb, drawLabel) { var r = this; - var nodeWidth, nodeHeight; - var rs = node._private.rscratch; + var nodeWidth = void 0, + nodeHeight = void 0; var _p = node._private; - var pos = pos || _p.position; + var rs = _p.rscratch; + var pos = node.position(); - if( !is.number( pos.x ) || !is.number( pos.y ) ){ + if (!is.number(pos.x) || !is.number(pos.y)) { return; // can't draw node with undefined position } - var usePaths = this.usePaths(); - var path; - var pathCacheHit = false; + if (!node.visible()) { + return; + } var parentOpacity = node.effectiveOpacity(); - if( parentOpacity === 0 ){ return; } - nodeWidth = node.width() + node.pstyle( 'padding-left' ).pfValue + node.pstyle( 'padding-right' ).pfValue; - nodeHeight = node.height() + node.pstyle( 'padding-top' ).pfValue + node.pstyle( 'padding-bottom' ).pfValue; + var usePaths = r.usePaths(); + var path = void 0; + var pathCacheHit = false; - context.lineWidth = node.pstyle( 'border-width' ).pfValue; + var padding = node.padding(); + + nodeWidth = node.width() + 2 * padding; + nodeHeight = node.height() + 2 * padding; // // setup shift - var bb; - if( shiftToOriginWithBb ){ + var bb = void 0; + if (shiftToOriginWithBb) { bb = shiftToOriginWithBb; - context.translate( -bb.x1, -bb.y1 ); + context.translate(-bb.x1, -bb.y1); } // // load bg image - var bgImgProp = node.pstyle( 'background-image' ); - var url = bgImgProp.value[2] || bgImgProp.value[1]; - var image; + var bgImgProp = node.pstyle('background-image'); + var urls = bgImgProp.value; + var urlDefined = new Array(urls.length); + var image = new Array(urls.length); + var numImages = 0; + for (var i = 0; i < urls.length; i++) { + var url = urls[i]; + var defd = urlDefined[i] = url != null && url !== 'none'; - if( url !== undefined ){ + if (defd) { + var bgImgCrossOrigin = node.cy().style().getIndexedStyle(node, 'background-image-crossorigin', 'value', i); - // get image, and if not loaded then ask to redraw when later loaded - image = this.getCachedImage( url, function(){ - node.trigger('background'); + numImages++; - r.redrawHint( 'eles', true ); - r.redrawHint( 'drag', true ); - - r.drawingImage = true; - - r.redraw(); - } ); - - var prevBging = _p.backgrounding; - _p.backgrounding = !image.complete; - - if( prevBging !== _p.backgrounding ){ // update style b/c :backgrounding state changed - node.updateStyle( false ); + // get image, and if not loaded then ask to redraw when later loaded + image[i] = r.getCachedImage(url, bgImgCrossOrigin, function () { + node.emitAndNotify('background'); + }); } } // // setup styles - var bgColor = node.pstyle( 'background-color' ).value; - var borderColor = node.pstyle( 'border-color' ).value; - var borderStyle = node.pstyle( 'border-style' ).value; - - this.fillStyle( context, bgColor[0], bgColor[1], bgColor[2], node.pstyle( 'background-opacity' ).value * parentOpacity ); - - this.strokeStyle( context, borderColor[0], borderColor[1], borderColor[2], node.pstyle( 'border-opacity' ).value * parentOpacity ); - - var shadowBlur = node.pstyle( 'shadow-blur' ).pfValue; - var shadowOpacity = node.pstyle( 'shadow-opacity' ).value; - var shadowColor = node.pstyle( 'shadow-color' ).value; - var shadowOffsetX = node.pstyle( 'shadow-offset-x' ).pfValue; - var shadowOffsetY = node.pstyle( 'shadow-offset-y' ).pfValue; - - this.shadowStyle( context, shadowColor, shadowOpacity, shadowBlur, shadowOffsetX, shadowOffsetY ); + var darkness = node.pstyle('background-blacken').value; + var borderWidth = node.pstyle('border-width').pfValue; + var bgColor = node.pstyle('background-color').value; + var bgOpacity = node.pstyle('background-opacity').value * parentOpacity; + var borderColor = node.pstyle('border-color').value; + var borderStyle = node.pstyle('border-style').value; + var borderOpacity = node.pstyle('border-opacity').value * parentOpacity; context.lineJoin = 'miter'; // so borders are square with the node shape - if( context.setLineDash ){ // for very outofdate browsers - switch( borderStyle ){ - case 'dotted': - context.setLineDash( [ 1, 1 ] ); - break; + var setupShapeColor = function setupShapeColor() { + var bgOpy = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : bgOpacity; - case 'dashed': - context.setLineDash( [ 4, 2 ] ); - break; + r.fillStyle(context, bgColor[0], bgColor[1], bgColor[2], bgOpy); + }; - case 'solid': - case 'double': - context.setLineDash( [ ] ); - break; - } - } + var setupBorderColor = function setupBorderColor() { + var bdrOpy = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : borderOpacity; + r.strokeStyle(context, borderColor[0], borderColor[1], borderColor[2], bdrOpy); + }; // - // draw shape + // setup shape var styleShape = node.pstyle('shape').strValue; var shapePts = node.pstyle('shape-polygon-points').pfValue; - if( usePaths ){ - var pathCacheKey = styleShape + '$' + nodeWidth + '$' + nodeHeight + ( styleShape === 'polygon' ? '$' + shapePts.join('$') : '' ); + if (usePaths) { + var pathCacheKey = styleShape + '$' + nodeWidth + '$' + nodeHeight + (styleShape === 'polygon' ? '$' + shapePts.join('$') : ''); - context.translate( pos.x, pos.y ); + context.translate(pos.x, pos.y); - if( rs.pathCacheKey === pathCacheKey ){ + if (rs.pathCacheKey === pathCacheKey) { path = rs.pathCache; pathCacheHit = true; } else { - path = new Path2D(); // eslint-disable-line no-undef + path = new Path2D(); rs.pathCacheKey = pathCacheKey; rs.pathCache = path; } } - if( !pathCacheHit ){ + var drawShape = function drawShape() { + if (!pathCacheHit) { - var npos = pos; + var npos = pos; - if( usePaths ){ - npos = { - x: 0, - y: 0 - }; + if (usePaths) { + npos = { + x: 0, + y: 0 + }; + } + + r.nodeShapes[r.getNodeShape(node)].draw(path || context, npos.x, npos.y, nodeWidth, nodeHeight); } - r.nodeShapes[ this.getNodeShape( node ) ].draw( - ( path || context ), - npos.x, - npos.y, - nodeWidth, - nodeHeight ); - } - - if( usePaths ){ - context.fill( path ); - } else { - context.fill(); - } - - this.shadowStyle( context, 'transparent', 0 ); // reset for next guy - - // - // bg image - - if( url !== undefined ){ - if( image.complete ){ - this.drawInscribedImage( context, image, node ); + if (usePaths) { + context.fill(path); + } else { + context.fill(); } - } + }; - // - // pie + var drawImages = function drawImages() { + var nodeOpacity = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : parentOpacity; - var darkness = node.pstyle( 'background-blacken' ).value; - var borderWidth = node.pstyle( 'border-width' ).pfValue; + var prevBging = _p.backgrounding; + var totalCompleted = 0; - if( this.hasPie( node ) ){ - this.drawPie( context, node, parentOpacity ); - - // redraw path for blacken and border - if( darkness !== 0 || borderWidth !== 0 ){ - - if( !usePaths ){ - r.nodeShapes[ this.getNodeShape( node ) ].draw( - context, - pos.x, - pos.y, - nodeWidth, - nodeHeight ); + for (var _i = 0; _i < image.length; _i++) { + if (urlDefined[_i] && image[_i].complete && !image[_i].error) { + totalCompleted++; + r.drawInscribedImage(context, image[_i], node, _i, nodeOpacity); } } - } - // - // darken/lighten - - if( darkness > 0 ){ - this.fillStyle( context, 0, 0, 0, darkness ); - - if( usePaths ){ - context.fill( path ); - } else { - context.fill(); + _p.backgrounding = !(totalCompleted === numImages); + if (prevBging !== _p.backgrounding) { + // update style b/c :backgrounding state changed + node.updateStyle(false); } + }; - } else if( darkness < 0 ){ - this.fillStyle( context, 255, 255, 255, -darkness ); + var drawPie = function drawPie() { + var redrawShape = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var pieOpacity = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : parentOpacity; - if( usePaths ){ - context.fill( path ); - } else { - context.fill(); + if (r.hasPie(node)) { + r.drawPie(context, node, pieOpacity); + + // redraw/restore path if steps after pie need it + if (redrawShape) { + + if (!usePaths) { + r.nodeShapes[r.getNodeShape(node)].draw(context, pos.x, pos.y, nodeWidth, nodeHeight); + } + } } - } + }; - // - // border + var darken = function darken() { + var darkenOpacity = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : parentOpacity; - if( borderWidth > 0 ){ + var opacity = (darkness > 0 ? darkness : -darkness) * darkenOpacity; + var c = darkness > 0 ? 0 : 255; - if( usePaths ){ - context.stroke( path ); - } else { - context.stroke(); + if (darkness !== 0) { + r.fillStyle(context, c, c, c, opacity); + + if (usePaths) { + context.fill(path); + } else { + context.fill(); + } } + }; - if( borderStyle === 'double' ){ - context.lineWidth = node.pstyle( 'border-width' ).pfValue / 3; + var drawBorder = function drawBorder() { + if (borderWidth > 0) { - var gco = context.globalCompositeOperation; - context.globalCompositeOperation = 'destination-out'; + context.lineWidth = borderWidth; + context.lineCap = 'butt'; - if( usePaths ){ - context.stroke( path ); + if (context.setLineDash) { + // for very outofdate browsers + switch (borderStyle) { + case 'dotted': + context.setLineDash([1, 1]); + break; + + case 'dashed': + context.setLineDash([4, 2]); + break; + + case 'solid': + case 'double': + context.setLineDash([]); + break; + } + } + + if (usePaths) { + context.stroke(path); } else { context.stroke(); } - context.globalCompositeOperation = gco; + if (borderStyle === 'double') { + context.lineWidth = borderWidth / 3; + + var gco = context.globalCompositeOperation; + context.globalCompositeOperation = 'destination-out'; + + if (usePaths) { + context.stroke(path); + } else { + context.stroke(); + } + + context.globalCompositeOperation = gco; + } + + // reset in case we changed the border style + if (context.setLineDash) { + // for very outofdate browsers + context.setLineDash([]); + } } + }; + var drawOverlay = function drawOverlay() { + var overlayPadding = node.pstyle('overlay-padding').pfValue; + var overlayOpacity = node.pstyle('overlay-opacity').value; + var overlayColor = node.pstyle('overlay-color').value; + + if (overlayOpacity > 0) { + r.fillStyle(context, overlayColor[0], overlayColor[1], overlayColor[2], overlayOpacity); + + r.nodeShapes['roundrectangle'].draw(context, pos.x, pos.y, nodeWidth + overlayPadding * 2, nodeHeight + overlayPadding * 2); + + context.fill(); + } + }; + + var drawText = function drawText() { + r.drawElementText(context, node, drawLabel); + }; + + var ghost = node.pstyle('ghost').value === 'yes'; + + if (ghost) { + var gx = node.pstyle('ghost-offset-x').pfValue; + var gy = node.pstyle('ghost-offset-y').pfValue; + var ghostOpacity = node.pstyle('ghost-opacity').value; + var effGhostOpacity = ghostOpacity * parentOpacity; + + context.translate(gx, gy); + + setupShapeColor(ghostOpacity * bgOpacity); + drawShape(); + drawImages(effGhostOpacity); + drawPie(darkness !== 0 || borderWidth !== 0); + darken(effGhostOpacity); + setupBorderColor(ghostOpacity * borderOpacity); + drawBorder(); + + context.translate(-gx, -gy); } - if( usePaths ){ - context.translate( -pos.x, -pos.y ); + setupShapeColor(); + drawShape(); + drawImages(); + drawPie(darkness !== 0 || borderWidth !== 0); + darken(); + setupBorderColor(); + drawBorder(); + + if (usePaths) { + context.translate(-pos.x, -pos.y); } - // reset in case we changed the border style - if( context.setLineDash ){ // for very outofdate browsers - context.setLineDash( [ ] ); - } - - // - // label - - r.drawElementText( context, node, drawLabel ); - - // - // overlay - - var overlayPadding = node.pstyle( 'overlay-padding' ).pfValue; - var overlayOpacity = node.pstyle( 'overlay-opacity' ).value; - var overlayColor = node.pstyle( 'overlay-color' ).value; - - if( overlayOpacity > 0 ){ - this.fillStyle( context, overlayColor[0], overlayColor[1], overlayColor[2], overlayOpacity ); - - r.nodeShapes[ 'roundrectangle' ].draw( - context, - node._private.position.x, - node._private.position.y, - nodeWidth + overlayPadding * 2, - nodeHeight + overlayPadding * 2 - ); - - context.fill(); - } + drawText(); + drawOverlay(); // // clean up shift - if( shiftToOriginWithBb ){ - context.translate( bb.x1, bb.y1 ); + if (shiftToOriginWithBb) { + context.translate(bb.x1, bb.y1); } - }; // does the node have at least one pie piece? -CRp.hasPie = function( node ){ +CRp.hasPie = function (node) { node = node[0]; // ensure ele ref return node._private.hasPie; }; -CRp.drawPie = function( context, node, nodeOpacity, pos ){ +CRp.drawPie = function (context, node, nodeOpacity, pos) { node = node[0]; // ensure ele ref + pos = pos || node.position(); - var _p = node._private; var cyStyle = node.cy().style(); - var pieSize = node.pstyle( 'pie-size' ); - var nodeW = node.width(); - var nodeH = node.height(); - var pos = pos || _p.position; + var pieSize = node.pstyle('pie-size'); var x = pos.x; var y = pos.y; - var radius = Math.min( nodeW, nodeH ) / 2; // must fit in node + var nodeW = node.width(); + var nodeH = node.height(); + var radius = Math.min(nodeW, nodeH) / 2; // must fit in node var lastPercent = 0; // what % to continue drawing pie slices from on [0, 1] var usePaths = this.usePaths(); - if( usePaths ){ + if (usePaths) { x = 0; y = 0; } - if( pieSize.units === '%' ){ - radius = radius * pieSize.value / 100; - } else if( pieSize.pfValue !== undefined ){ + if (pieSize.units === '%') { + radius = radius * pieSize.pfValue; + } else if (pieSize.pfValue !== undefined) { radius = pieSize.pfValue / 2; } - for( var i = 1; i <= cyStyle.pieBackgroundN; i++ ){ // 1..N - var size = node.pstyle( 'pie-' + i + '-background-size' ).value; - var color = node.pstyle( 'pie-' + i + '-background-color' ).value; - var opacity = node.pstyle( 'pie-' + i + '-background-opacity' ).value * nodeOpacity; + for (var i = 1; i <= cyStyle.pieBackgroundN; i++) { + // 1..N + var size = node.pstyle('pie-' + i + '-background-size').value; + var color = node.pstyle('pie-' + i + '-background-color').value; + var opacity = node.pstyle('pie-' + i + '-background-opacity').value * nodeOpacity; var percent = size / 100; // map integer range [0, 100] to [0, 1] // percent can't push beyond 1 - if( percent + lastPercent > 1 ){ + if (percent + lastPercent > 1) { percent = 1 - lastPercent; } @@ -17886,80 +28869,77 @@ CRp.drawPie = function( context, node, nodeOpacity, pos ){ // - zero size // - we're already beyond the full circle // - adding the current slice would go beyond the full circle - if( size === 0 || lastPercent >= 1 || lastPercent + percent > 1 ){ + if (size === 0 || lastPercent >= 1 || lastPercent + percent > 1) { continue; } context.beginPath(); - context.moveTo( x, y ); - context.arc( x, y, radius, angleStart, angleEnd ); + context.moveTo(x, y); + context.arc(x, y, radius, angleStart, angleEnd); context.closePath(); - this.fillStyle( context, color[0], color[1], color[2], opacity ); + this.fillStyle(context, color[0], color[1], color[2], opacity); context.fill(); lastPercent += percent; } - }; - module.exports = CRp; -},{"../../../is":83}],70:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 133 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + var CRp = {}; -var util = _dereq_( '../../../util' ); +var util = __webpack_require__(1); var motionBlurDelay = 100; // var isFirefox = typeof InstallTrigger !== 'undefined'; -CRp.getPixelRatio = function(){ +CRp.getPixelRatio = function () { var context = this.data.contexts[0]; - if( this.forcedPixelRatio != null ){ + if (this.forcedPixelRatio != null) { return this.forcedPixelRatio; } - var backingStore = context.backingStorePixelRatio || - context.webkitBackingStorePixelRatio || - context.mozBackingStorePixelRatio || - context.msBackingStorePixelRatio || - context.oBackingStorePixelRatio || - context.backingStorePixelRatio || 1; + var backingStore = context.backingStorePixelRatio || context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || context.backingStorePixelRatio || 1; return (window.devicePixelRatio || 1) / backingStore; // eslint-disable-line no-undef }; -CRp.paintCache = function( context ){ +CRp.paintCache = function (context) { var caches = this.paintCaches = this.paintCaches || []; var needToCreateCache = true; var cache; - for( var i = 0; i < caches.length; i++ ){ - cache = caches[ i ]; + for (var i = 0; i < caches.length; i++) { + cache = caches[i]; - if( cache.context === context ){ + if (cache.context === context) { needToCreateCache = false; break; } } - if( needToCreateCache ){ + if (needToCreateCache) { cache = { context: context }; - caches.push( cache ); + caches.push(cache); } return cache; }; -CRp.fillStyle = function( context, r, g, b, a ){ +CRp.fillStyle = function (context, r, g, b, a) { context.fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; // turn off for now, seems context does its own caching @@ -17973,7 +28953,7 @@ CRp.fillStyle = function( context, r, g, b, a ){ // } }; -CRp.strokeStyle = function( context, r, g, b, a ){ +CRp.strokeStyle = function (context, r, g, b, a) { context.strokeStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; // turn off for now, seems context does its own caching @@ -17987,44 +28967,17 @@ CRp.strokeStyle = function( context, r, g, b, a ){ // } }; -CRp.shadowStyle = function( context, color, opacity, blur, offsetX, offsetY ){ - var zoom = this.cy.zoom(); - - // var cache = this.paintCache( context ); - // - // // don't make expensive changes to the shadow style if it's not used - // if( cache.shadowOpacity === 0 && opacity === 0 ){ - // return; - // } - // - // cache.shadowOpacity = opacity; - - if( opacity > 0 ){ - context.shadowBlur = blur * zoom; - context.shadowColor = 'rgba(' + color[0] + ',' + color[1] + ',' + color[2] + ',' + opacity + ')'; - context.shadowOffsetX = offsetX * zoom; - context.shadowOffsetY = offsetY * zoom; - } else { - context.shadowBlur = 0; - context.shadowColor = 'transparent'; - context.shadowOffsetX = 0; - context.shadowOffsetY = 0; - } -}; - // Resize canvas -CRp.matchCanvasSize = function( container ){ +CRp.matchCanvasSize = function (container) { var r = this; var data = r.data; - var width = container.clientWidth; - var height = container.clientHeight; + var bb = r.findContainerClientCoords(); + var width = bb[2]; + var height = bb[3]; var pixelRatio = r.getPixelRatio(); var mbPxRatio = r.motionBlurPxRatio; - if( - container === r.data.bufferCanvases[ r.MOTIONBLUR_BUFFER_NODE ] || - container === r.data.bufferCanvases[ r.MOTIONBLUR_BUFFER_DRAG ] - ){ + if (container === r.data.bufferCanvases[r.MOTIONBLUR_BUFFER_NODE] || container === r.data.bufferCanvases[r.MOTIONBLUR_BUFFER_DRAG]) { pixelRatio = mbPxRatio; } @@ -18032,7 +28985,7 @@ CRp.matchCanvasSize = function( container ){ var canvasHeight = height * pixelRatio; var canvas; - if( canvasWidth === r.canvasWidth && canvasHeight === r.canvasHeight ){ + if (canvasWidth === r.canvasWidth && canvasHeight === r.canvasHeight) { return; // save cycles if same } @@ -18042,37 +28995,29 @@ CRp.matchCanvasSize = function( container ){ canvasContainer.style.width = width + 'px'; canvasContainer.style.height = height + 'px'; - for( var i = 0; i < r.CANVAS_LAYERS; i++ ){ + for (var i = 0; i < r.CANVAS_LAYERS; i++) { + canvas = data.canvases[i]; - canvas = data.canvases[ i ]; + canvas.width = canvasWidth; + canvas.height = canvasHeight; - if( canvas.width !== canvasWidth || canvas.height !== canvasHeight ){ - - canvas.width = canvasWidth; - canvas.height = canvasHeight; - - canvas.style.width = width + 'px'; - canvas.style.height = height + 'px'; - } + canvas.style.width = width + 'px'; + canvas.style.height = height + 'px'; } - for( var i = 0; i < r.BUFFER_COUNT; i++ ){ + for (var i = 0; i < r.BUFFER_COUNT; i++) { + canvas = data.bufferCanvases[i]; - canvas = data.bufferCanvases[ i ]; + canvas.width = canvasWidth; + canvas.height = canvasHeight; - if( canvas.width !== canvasWidth || canvas.height !== canvasHeight ){ - - canvas.width = canvasWidth; - canvas.height = canvasHeight; - - canvas.style.width = width + 'px'; - canvas.style.height = height + 'px'; - } + canvas.style.width = width + 'px'; + canvas.style.height = height + 'px'; } r.textureMult = 1; - if( pixelRatio <= 1 ){ - canvas = data.bufferCanvases[ r.TEXTURE_BUFFER ]; + if (pixelRatio <= 1) { + canvas = data.bufferCanvases[r.TEXTURE_BUFFER]; r.textureMult = 2; canvas.width = canvasWidth * r.textureMult; @@ -18081,20 +29026,19 @@ CRp.matchCanvasSize = function( container ){ r.canvasWidth = canvasWidth; r.canvasHeight = canvasHeight; - }; -CRp.renderTo = function( cxt, zoom, pan, pxRatio ){ - this.render( { +CRp.renderTo = function (cxt, zoom, pan, pxRatio) { + this.render({ forcedContext: cxt, forcedZoom: zoom, forcedPan: pan, drawAllLayers: true, forcedPxRatio: pxRatio - } ); + }); }; -CRp.render = function( options ){ +CRp.render = function (options) { options = options || util.staticEmptyObject(); var forcedContext = options.forcedContext; @@ -18104,7 +29048,7 @@ CRp.render = function( options ){ var forcedPan = options.forcedPan; var r = this; var pixelRatio = options.forcedPxRatio === undefined ? this.getPixelRatio() : options.forcedPxRatio; - var cy = r.cy; var data = r.data; + var cy = r.cy;var data = r.data; var needDraw = data.canvasNeedsRedraw; var textureDraw = r.textureOnViewport && !forcedContext && (r.pinching || r.hoverData.dragging || r.swipePanning || r.data.wheelZooming); var motionBlur = options.motionBlur !== undefined ? options.motionBlur : r.motionBlur; @@ -18115,10 +29059,10 @@ CRp.render = function( options ){ motionBlur = motionBlur && !forcedContext && r.motionBlurEnabled && !inBoxSelection; var motionBlurFadeEffect = motionBlur; - if( !forcedContext ){ - if( r.prevPxRatio !== pixelRatio ){ + if (!forcedContext) { + if (r.prevPxRatio !== pixelRatio) { r.invalidateContainerClientCoordsCache(); - r.matchCanvasSize( r.container ); + r.matchCanvasSize(r.container); r.redrawHint('eles', true); r.redrawHint('drag', true); @@ -18127,39 +29071,38 @@ CRp.render = function( options ){ r.prevPxRatio = pixelRatio; } - if( !forcedContext && r.motionBlurTimeout ){ - clearTimeout( r.motionBlurTimeout ); + if (!forcedContext && r.motionBlurTimeout) { + clearTimeout(r.motionBlurTimeout); } - if( motionBlur ){ - if( r.mbFrames == null ){ + if (motionBlur) { + if (r.mbFrames == null) { r.mbFrames = 0; } - if( !r.drawingImage ){ // image loading frames don't count towards motion blur blurry frames - r.mbFrames++; - } + r.mbFrames++; - if( r.mbFrames < 3 ){ // need several frames before even high quality motionblur + if (r.mbFrames < 3) { + // need several frames before even high quality motionblur motionBlurFadeEffect = false; } // go to lower quality blurry frames when several m/b frames have been rendered (avoids flashing) - if( r.mbFrames > r.minMbLowQualFrames ){ + if (r.mbFrames > r.minMbLowQualFrames) { //r.fullQualityMb = false; r.motionBlurPxRatio = r.mbPxRBlurry; } } - if( r.clearingMotionBlur ){ + if (r.clearingMotionBlur) { r.motionBlurPxRatio = 1; } // b/c drawToContext() may be async w.r.t. redraw(), keep track of last texture frame // because a rogue async texture frame would clear needDraw - if( r.textureDrawLastFrame && !textureDraw ){ - needDraw[ r.NODE ] = true; - needDraw[ r.SELECT_BOX ] = true; + if (r.textureDrawLastFrame && !textureDraw) { + needDraw[r.NODE] = true; + needDraw[r.SELECT_BOX] = true; } var coreStyle = cy.style()._private.coreStyle; @@ -18183,11 +29126,11 @@ CRp.render = function( options ){ var viewportIsDiff = prevVp === undefined || vp.zoom !== prevVp.zoom || vp.pan.x !== prevVp.pan.x || vp.pan.y !== prevVp.pan.y; // we want the low quality motionblur only when the viewport is being manipulated etc (where it's not noticed) - if( !viewportIsDiff && !(inNodeDragGesture && !hasCompoundNodes) ){ + if (!viewportIsDiff && !(inNodeDragGesture && !hasCompoundNodes)) { r.motionBlurPxRatio = 1; } - if( forcedPan ){ + if (forcedPan) { effectivePan = forcedPan; } @@ -18199,20 +29142,20 @@ CRp.render = function( options ){ var eles = r.getCachedZSortedEles(); - function mbclear( context, x, y, w, h ){ + function mbclear(context, x, y, w, h) { var gco = context.globalCompositeOperation; context.globalCompositeOperation = 'destination-out'; - r.fillStyle( context, 255, 255, 255, r.motionBlurTransparency ); - context.fillRect( x, y, w, h ); + r.fillStyle(context, 255, 255, 255, r.motionBlurTransparency); + context.fillRect(x, y, w, h); context.globalCompositeOperation = gco; } - function setContextTransform( context, clear ){ + function setContextTransform(context, clear) { var ePan, eZoom, w, h; - if( !r.clearingMotionBlur && (context === data.bufferContexts[ r.MOTIONBLUR_BUFFER_NODE ] || context === data.bufferContexts[ r.MOTIONBLUR_BUFFER_DRAG ]) ){ + if (!r.clearingMotionBlur && (context === data.bufferContexts[r.MOTIONBLUR_BUFFER_NODE] || context === data.bufferContexts[r.MOTIONBLUR_BUFFER_DRAG])) { ePan = { x: pan.x * mbPxRatio, y: pan.y * mbPxRatio @@ -18230,52 +29173,52 @@ CRp.render = function( options ){ h = r.canvasHeight; } - context.setTransform( 1, 0, 0, 1, 0, 0 ); + context.setTransform(1, 0, 0, 1, 0, 0); - if( clear === 'motionBlur' ){ - mbclear( context, 0, 0, w, h ); - } else if( !forcedContext && (clear === undefined || clear) ){ - context.clearRect( 0, 0, w, h ); + if (clear === 'motionBlur') { + mbclear(context, 0, 0, w, h); + } else if (!forcedContext && (clear === undefined || clear)) { + context.clearRect(0, 0, w, h); } - if( !drawAllLayers ){ - context.translate( ePan.x, ePan.y ); - context.scale( eZoom, eZoom ); + if (!drawAllLayers) { + context.translate(ePan.x, ePan.y); + context.scale(eZoom, eZoom); } - if( forcedPan ){ - context.translate( forcedPan.x, forcedPan.y ); + if (forcedPan) { + context.translate(forcedPan.x, forcedPan.y); } - if( forcedZoom ){ - context.scale( forcedZoom, forcedZoom ); + if (forcedZoom) { + context.scale(forcedZoom, forcedZoom); } } - if( !textureDraw ){ + if (!textureDraw) { r.textureDrawLastFrame = false; } - if( textureDraw ){ + if (textureDraw) { r.textureDrawLastFrame = true; var bb; - if( !r.textureCache ){ + if (!r.textureCache) { r.textureCache = {}; bb = r.textureCache.bb = cy.mutableElements().boundingBox(); - r.textureCache.texture = r.data.bufferCanvases[ r.TEXTURE_BUFFER ]; + r.textureCache.texture = r.data.bufferCanvases[r.TEXTURE_BUFFER]; - var cxt = r.data.bufferContexts[ r.TEXTURE_BUFFER ]; + var cxt = r.data.bufferContexts[r.TEXTURE_BUFFER]; - cxt.setTransform( 1, 0, 0, 1, 0, 0 ); - cxt.clearRect( 0, 0, r.canvasWidth * r.textureMult, r.canvasHeight * r.textureMult ); + cxt.setTransform(1, 0, 0, 1, 0, 0); + cxt.clearRect(0, 0, r.canvasWidth * r.textureMult, r.canvasHeight * r.textureMult); - r.render( { + r.render({ forcedContext: cxt, drawOnlyNodeLayer: true, forcedPxRatio: pixelRatio * r.textureMult - } ); + }); var vp = r.textureCache.viewport = { zoom: cy.zoom(), @@ -18290,880 +29233,463 @@ CRp.render = function( options ){ }; } - needDraw[ r.DRAG ] = false; - needDraw[ r.NODE ] = false; + needDraw[r.DRAG] = false; + needDraw[r.NODE] = false; - var context = data.contexts[ r.NODE ]; + var context = data.contexts[r.NODE]; var texture = r.textureCache.texture; var vp = r.textureCache.viewport; bb = r.textureCache.bb; - context.setTransform( 1, 0, 0, 1, 0, 0 ); + context.setTransform(1, 0, 0, 1, 0, 0); - if( motionBlur ){ - mbclear( context, 0, 0, vp.width, vp.height ); + if (motionBlur) { + mbclear(context, 0, 0, vp.width, vp.height); } else { - context.clearRect( 0, 0, vp.width, vp.height ); + context.clearRect(0, 0, vp.width, vp.height); } - var outsideBgColor = coreStyle[ 'outside-texture-bg-color' ].value; - var outsideBgOpacity = coreStyle[ 'outside-texture-bg-opacity' ].value; - r.fillStyle( context, outsideBgColor[0], outsideBgColor[1], outsideBgColor[2], outsideBgOpacity ); - context.fillRect( 0, 0, vp.width, vp.height ); + var outsideBgColor = coreStyle['outside-texture-bg-color'].value; + var outsideBgOpacity = coreStyle['outside-texture-bg-opacity'].value; + r.fillStyle(context, outsideBgColor[0], outsideBgColor[1], outsideBgColor[2], outsideBgOpacity); + context.fillRect(0, 0, vp.width, vp.height); var zoom = cy.zoom(); - setContextTransform( context, false ); + setContextTransform(context, false); - context.clearRect( vp.mpan.x, vp.mpan.y, vp.width / vp.zoom / pixelRatio, vp.height / vp.zoom / pixelRatio ); - context.drawImage( texture, vp.mpan.x, vp.mpan.y, vp.width / vp.zoom / pixelRatio, vp.height / vp.zoom / pixelRatio ); - - } else if( r.textureOnViewport && !forcedContext ){ // clear the cache since we don't need it + context.clearRect(vp.mpan.x, vp.mpan.y, vp.width / vp.zoom / pixelRatio, vp.height / vp.zoom / pixelRatio); + context.drawImage(texture, vp.mpan.x, vp.mpan.y, vp.width / vp.zoom / pixelRatio, vp.height / vp.zoom / pixelRatio); + } else if (r.textureOnViewport && !forcedContext) { + // clear the cache since we don't need it r.textureCache = null; } var extent = cy.extent(); - var vpManip = (r.pinching || r.hoverData.dragging || r.swipePanning || r.data.wheelZooming || r.hoverData.draggingEles); + var vpManip = r.pinching || r.hoverData.dragging || r.swipePanning || r.data.wheelZooming || r.hoverData.draggingEles; var hideEdges = r.hideEdgesOnViewport && vpManip; var needMbClear = []; - needMbClear[ r.NODE ] = !needDraw[ r.NODE ] && motionBlur && !r.clearedForMotionBlur[ r.NODE ] || r.clearingMotionBlur; - if( needMbClear[ r.NODE ] ){ r.clearedForMotionBlur[ r.NODE ] = true; } + needMbClear[r.NODE] = !needDraw[r.NODE] && motionBlur && !r.clearedForMotionBlur[r.NODE] || r.clearingMotionBlur; + if (needMbClear[r.NODE]) { + r.clearedForMotionBlur[r.NODE] = true; + } - needMbClear[ r.DRAG ] = !needDraw[ r.DRAG ] && motionBlur && !r.clearedForMotionBlur[ r.DRAG ] || r.clearingMotionBlur; - if( needMbClear[ r.DRAG ] ){ r.clearedForMotionBlur[ r.DRAG ] = true; } + needMbClear[r.DRAG] = !needDraw[r.DRAG] && motionBlur && !r.clearedForMotionBlur[r.DRAG] || r.clearingMotionBlur; + if (needMbClear[r.DRAG]) { + r.clearedForMotionBlur[r.DRAG] = true; + } - if( needDraw[ r.NODE ] || drawAllLayers || drawOnlyNodeLayer || needMbClear[ r.NODE ] ){ - var useBuffer = motionBlur && !needMbClear[ r.NODE ] && mbPxRatio !== 1; - var context = forcedContext || ( useBuffer ? r.data.bufferContexts[ r.MOTIONBLUR_BUFFER_NODE ] : data.contexts[ r.NODE ] ); + if (needDraw[r.NODE] || drawAllLayers || drawOnlyNodeLayer || needMbClear[r.NODE]) { + var useBuffer = motionBlur && !needMbClear[r.NODE] && mbPxRatio !== 1; + var context = forcedContext || (useBuffer ? r.data.bufferContexts[r.MOTIONBLUR_BUFFER_NODE] : data.contexts[r.NODE]); var clear = motionBlur && !useBuffer ? 'motionBlur' : undefined; - setContextTransform( context, clear ); + setContextTransform(context, clear); - if( hideEdges ){ - r.drawCachedNodes( context, eles.nondrag, pixelRatio, extent ); + if (hideEdges) { + r.drawCachedNodes(context, eles.nondrag, pixelRatio, extent); } else { - r.drawLayeredElements( context, eles.nondrag, pixelRatio, extent ); + r.drawLayeredElements(context, eles.nondrag, pixelRatio, extent); } - if( !drawAllLayers && !motionBlur ){ - needDraw[ r.NODE ] = false; + if (r.debug) { + r.drawDebugPoints(context, eles.nondrag); + } + + if (!drawAllLayers && !motionBlur) { + needDraw[r.NODE] = false; } } - if( !drawOnlyNodeLayer && (needDraw[ r.DRAG ] || drawAllLayers || needMbClear[ r.DRAG ]) ){ - var useBuffer = motionBlur && !needMbClear[ r.DRAG ] && mbPxRatio !== 1; - var context = forcedContext || ( useBuffer ? r.data.bufferContexts[ r.MOTIONBLUR_BUFFER_DRAG ] : data.contexts[ r.DRAG ] ); + if (!drawOnlyNodeLayer && (needDraw[r.DRAG] || drawAllLayers || needMbClear[r.DRAG])) { + var useBuffer = motionBlur && !needMbClear[r.DRAG] && mbPxRatio !== 1; + var context = forcedContext || (useBuffer ? r.data.bufferContexts[r.MOTIONBLUR_BUFFER_DRAG] : data.contexts[r.DRAG]); - setContextTransform( context, motionBlur && !useBuffer ? 'motionBlur' : undefined ); + setContextTransform(context, motionBlur && !useBuffer ? 'motionBlur' : undefined); - if( hideEdges ){ - r.drawCachedNodes( context, eles.drag, pixelRatio, extent ); + if (hideEdges) { + r.drawCachedNodes(context, eles.drag, pixelRatio, extent); } else { - r.drawCachedElements( context, eles.drag, pixelRatio, extent ); + r.drawCachedElements(context, eles.drag, pixelRatio, extent); } - if( !drawAllLayers && !motionBlur ){ - needDraw[ r.DRAG ] = false; + if (r.debug) { + r.drawDebugPoints(context, eles.drag); + } + + if (!drawAllLayers && !motionBlur) { + needDraw[r.DRAG] = false; } } - if( r.showFps || (!drawOnlyNodeLayer && (needDraw[ r.SELECT_BOX ] && !drawAllLayers)) ){ - var context = forcedContext || data.contexts[ r.SELECT_BOX ]; + if (r.showFps || !drawOnlyNodeLayer && needDraw[r.SELECT_BOX] && !drawAllLayers) { + var context = forcedContext || data.contexts[r.SELECT_BOX]; - setContextTransform( context ); + setContextTransform(context); - if( r.selection[4] == 1 && ( r.hoverData.selecting || r.touchData.selecting ) ){ + if (r.selection[4] == 1 && (r.hoverData.selecting || r.touchData.selecting)) { var zoom = r.cy.zoom(); - var borderWidth = coreStyle[ 'selection-box-border-width' ].value / zoom; + var borderWidth = coreStyle['selection-box-border-width'].value / zoom; context.lineWidth = borderWidth; - context.fillStyle = 'rgba(' - + coreStyle[ 'selection-box-color' ].value[0] + ',' - + coreStyle[ 'selection-box-color' ].value[1] + ',' - + coreStyle[ 'selection-box-color' ].value[2] + ',' - + coreStyle[ 'selection-box-opacity' ].value + ')'; + context.fillStyle = 'rgba(' + coreStyle['selection-box-color'].value[0] + ',' + coreStyle['selection-box-color'].value[1] + ',' + coreStyle['selection-box-color'].value[2] + ',' + coreStyle['selection-box-opacity'].value + ')'; - context.fillRect( - r.selection[0], - r.selection[1], - r.selection[2] - r.selection[0], - r.selection[3] - r.selection[1] ); + context.fillRect(r.selection[0], r.selection[1], r.selection[2] - r.selection[0], r.selection[3] - r.selection[1]); - if( borderWidth > 0 ){ - context.strokeStyle = 'rgba(' - + coreStyle[ 'selection-box-border-color' ].value[0] + ',' - + coreStyle[ 'selection-box-border-color' ].value[1] + ',' - + coreStyle[ 'selection-box-border-color' ].value[2] + ',' - + coreStyle[ 'selection-box-opacity' ].value + ')'; + if (borderWidth > 0) { + context.strokeStyle = 'rgba(' + coreStyle['selection-box-border-color'].value[0] + ',' + coreStyle['selection-box-border-color'].value[1] + ',' + coreStyle['selection-box-border-color'].value[2] + ',' + coreStyle['selection-box-opacity'].value + ')'; - context.strokeRect( - r.selection[0], - r.selection[1], - r.selection[2] - r.selection[0], - r.selection[3] - r.selection[1] ); + context.strokeRect(r.selection[0], r.selection[1], r.selection[2] - r.selection[0], r.selection[3] - r.selection[1]); } } - if( data.bgActivePosistion && !r.hoverData.selecting ){ + if (data.bgActivePosistion && !r.hoverData.selecting) { var zoom = r.cy.zoom(); var pos = data.bgActivePosistion; - context.fillStyle = 'rgba(' - + coreStyle[ 'active-bg-color' ].value[0] + ',' - + coreStyle[ 'active-bg-color' ].value[1] + ',' - + coreStyle[ 'active-bg-color' ].value[2] + ',' - + coreStyle[ 'active-bg-opacity' ].value + ')'; + context.fillStyle = 'rgba(' + coreStyle['active-bg-color'].value[0] + ',' + coreStyle['active-bg-color'].value[1] + ',' + coreStyle['active-bg-color'].value[2] + ',' + coreStyle['active-bg-opacity'].value + ')'; context.beginPath(); - context.arc( pos.x, pos.y, coreStyle[ 'active-bg-size' ].pfValue / zoom, 0, 2 * Math.PI ); + context.arc(pos.x, pos.y, coreStyle['active-bg-size'].pfValue / zoom, 0, 2 * Math.PI); context.fill(); } var timeToRender = r.lastRedrawTime; - if( r.showFps && timeToRender ){ - timeToRender = Math.round( timeToRender ); - var fps = Math.round( 1000 / timeToRender ); + if (r.showFps && timeToRender) { + timeToRender = Math.round(timeToRender); + var fps = Math.round(1000 / timeToRender); - context.setTransform( 1, 0, 0, 1, 0, 0 ); + context.setTransform(1, 0, 0, 1, 0, 0); context.fillStyle = 'rgba(255, 0, 0, 0.75)'; context.strokeStyle = 'rgba(255, 0, 0, 0.75)'; context.lineWidth = 1; - context.fillText( '1 frame = ' + timeToRender + ' ms = ' + fps + ' fps', 0, 20 ); + context.fillText('1 frame = ' + timeToRender + ' ms = ' + fps + ' fps', 0, 20); var maxFps = 60; - context.strokeRect( 0, 30, 250, 20 ); - context.fillRect( 0, 30, 250 * Math.min( fps / maxFps, 1 ), 20 ); + context.strokeRect(0, 30, 250, 20); + context.fillRect(0, 30, 250 * Math.min(fps / maxFps, 1), 20); } - if( !drawAllLayers ){ - needDraw[ r.SELECT_BOX ] = false; + if (!drawAllLayers) { + needDraw[r.SELECT_BOX] = false; } } // motionblur: blit rendered blurry frames - if( motionBlur && mbPxRatio !== 1 ){ - var cxtNode = data.contexts[ r.NODE ]; - var txtNode = r.data.bufferCanvases[ r.MOTIONBLUR_BUFFER_NODE ]; + if (motionBlur && mbPxRatio !== 1) { + var cxtNode = data.contexts[r.NODE]; + var txtNode = r.data.bufferCanvases[r.MOTIONBLUR_BUFFER_NODE]; - var cxtDrag = data.contexts[ r.DRAG ]; - var txtDrag = r.data.bufferCanvases[ r.MOTIONBLUR_BUFFER_DRAG ]; + var cxtDrag = data.contexts[r.DRAG]; + var txtDrag = r.data.bufferCanvases[r.MOTIONBLUR_BUFFER_DRAG]; - var drawMotionBlur = function( cxt, txt, needClear ){ - cxt.setTransform( 1, 0, 0, 1, 0, 0 ); + var drawMotionBlur = function drawMotionBlur(cxt, txt, needClear) { + cxt.setTransform(1, 0, 0, 1, 0, 0); - if( needClear || !motionBlurFadeEffect ){ - cxt.clearRect( 0, 0, r.canvasWidth, r.canvasHeight ); + if (needClear || !motionBlurFadeEffect) { + cxt.clearRect(0, 0, r.canvasWidth, r.canvasHeight); } else { - mbclear( cxt, 0, 0, r.canvasWidth, r.canvasHeight ); + mbclear(cxt, 0, 0, r.canvasWidth, r.canvasHeight); } var pxr = mbPxRatio; - cxt.drawImage( - txt, // img - 0, 0, // sx, sy - r.canvasWidth * pxr, r.canvasHeight * pxr, // sw, sh - 0, 0, // x, y - r.canvasWidth, r.canvasHeight // w, h + cxt.drawImage(txt, // img + 0, 0, // sx, sy + r.canvasWidth * pxr, r.canvasHeight * pxr, // sw, sh + 0, 0, // x, y + r.canvasWidth, r.canvasHeight // w, h ); }; - if( needDraw[ r.NODE ] || needMbClear[ r.NODE ] ){ - drawMotionBlur( cxtNode, txtNode, needMbClear[ r.NODE ] ); - needDraw[ r.NODE ] = false; + if (needDraw[r.NODE] || needMbClear[r.NODE]) { + drawMotionBlur(cxtNode, txtNode, needMbClear[r.NODE]); + needDraw[r.NODE] = false; } - if( needDraw[ r.DRAG ] || needMbClear[ r.DRAG ] ){ - drawMotionBlur( cxtDrag, txtDrag, needMbClear[ r.DRAG ] ); - needDraw[ r.DRAG ] = false; + if (needDraw[r.DRAG] || needMbClear[r.DRAG]) { + drawMotionBlur(cxtDrag, txtDrag, needMbClear[r.DRAG]); + needDraw[r.DRAG] = false; } } r.prevViewport = vp; - if( r.clearingMotionBlur ){ + if (r.clearingMotionBlur) { r.clearingMotionBlur = false; r.motionBlurCleared = true; r.motionBlur = true; } - if( motionBlur ){ - r.motionBlurTimeout = setTimeout( function(){ + if (motionBlur) { + r.motionBlurTimeout = setTimeout(function () { r.motionBlurTimeout = null; - r.clearedForMotionBlur[ r.NODE ] = false; - r.clearedForMotionBlur[ r.DRAG ] = false; + r.clearedForMotionBlur[r.NODE] = false; + r.clearedForMotionBlur[r.DRAG] = false; r.motionBlur = false; r.clearingMotionBlur = !textureDraw; r.mbFrames = 0; - needDraw[ r.NODE ] = true; - needDraw[ r.DRAG ] = true; + needDraw[r.NODE] = true; + needDraw[r.DRAG] = true; r.redraw(); - }, motionBlurDelay ); + }, motionBlurDelay); } - r.drawingImage = false; - - - if( !forcedContext && !r.initrender ){ - r.initrender = true; - cy.trigger( 'initrender' ); + if (!forcedContext) { + cy.emit('render'); } - - if( !forcedContext ){ - cy.trigger('render'); - } - }; module.exports = CRp; -},{"../../../util":100}],71:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 134 */ +/***/ (function(module, exports, __webpack_require__) { -var math = _dereq_( '../../../math' ); +"use strict"; + + +var math = __webpack_require__(2); var CRp = {}; // @O Polygon drawing -CRp.drawPolygonPath = function( - context, x, y, width, height, points ){ +CRp.drawPolygonPath = function (context, x, y, width, height, points) { var halfW = width / 2; var halfH = height / 2; - if( context.beginPath ){ context.beginPath(); } + if (context.beginPath) { + context.beginPath(); + } - context.moveTo( x + halfW * points[0], y + halfH * points[1] ); + context.moveTo(x + halfW * points[0], y + halfH * points[1]); - for( var i = 1; i < points.length / 2; i++ ){ - context.lineTo( x + halfW * points[ i * 2], y + halfH * points[ i * 2 + 1] ); + for (var i = 1; i < points.length / 2; i++) { + context.lineTo(x + halfW * points[i * 2], y + halfH * points[i * 2 + 1]); } context.closePath(); }; // Round rectangle drawing -CRp.drawRoundRectanglePath = function( - context, x, y, width, height ){ +CRp.drawRoundRectanglePath = function (context, x, y, width, height) { var halfWidth = width / 2; var halfHeight = height / 2; - var cornerRadius = math.getRoundRectangleRadius( width, height ); + var cornerRadius = math.getRoundRectangleRadius(width, height); - if( context.beginPath ){ context.beginPath(); } + if (context.beginPath) { + context.beginPath(); + } // Start at top middle - context.moveTo( x, y - halfHeight ); + context.moveTo(x, y - halfHeight); // Arc from middle top to right side - context.arcTo( x + halfWidth, y - halfHeight, x + halfWidth, y, cornerRadius ); + context.arcTo(x + halfWidth, y - halfHeight, x + halfWidth, y, cornerRadius); // Arc from right side to bottom - context.arcTo( x + halfWidth, y + halfHeight, x, y + halfHeight, cornerRadius ); + context.arcTo(x + halfWidth, y + halfHeight, x, y + halfHeight, cornerRadius); // Arc from bottom to left side - context.arcTo( x - halfWidth, y + halfHeight, x - halfWidth, y, cornerRadius ); + context.arcTo(x - halfWidth, y + halfHeight, x - halfWidth, y, cornerRadius); // Arc from left side to topBorder - context.arcTo( x - halfWidth, y - halfHeight, x, y - halfHeight, cornerRadius ); + context.arcTo(x - halfWidth, y - halfHeight, x, y - halfHeight, cornerRadius); // Join line - context.lineTo( x, y - halfHeight ); - + context.lineTo(x, y - halfHeight); context.closePath(); }; -var sin0 = Math.sin( 0 ); -var cos0 = Math.cos( 0 ); +CRp.drawBottomRoundRectanglePath = function (context, x, y, width, height) { + + var halfWidth = width / 2; + var halfHeight = height / 2; + var cornerRadius = math.getRoundRectangleRadius(width, height); + + if (context.beginPath) { + context.beginPath(); + } + + // Start at top middle + context.moveTo(x, y - halfHeight); + context.lineTo(x + halfWidth, y - halfHeight); + context.lineTo(x + halfWidth, y); + + context.arcTo(x + halfWidth, y + halfHeight, x, y + halfHeight, cornerRadius); + context.arcTo(x - halfWidth, y + halfHeight, x - halfWidth, y, cornerRadius); + + context.lineTo(x - halfWidth, y - halfHeight); + context.lineTo(x, y - halfHeight); + + context.closePath(); +}; + +CRp.drawCutRectanglePath = function (context, x, y, width, height) { + + var halfWidth = width / 2; + var halfHeight = height / 2; + var cornerLength = math.getCutRectangleCornerLength(); + + if (context.beginPath) { + context.beginPath(); + } + + context.moveTo(x - halfWidth + cornerLength, y - halfHeight); + + context.lineTo(x + halfWidth - cornerLength, y - halfHeight); + context.lineTo(x + halfWidth, y - halfHeight + cornerLength); + context.lineTo(x + halfWidth, y + halfHeight - cornerLength); + context.lineTo(x + halfWidth - cornerLength, y + halfHeight); + context.lineTo(x - halfWidth + cornerLength, y + halfHeight); + context.lineTo(x - halfWidth, y + halfHeight - cornerLength); + context.lineTo(x - halfWidth, y - halfHeight + cornerLength); + + context.closePath(); +}; + +CRp.drawBarrelPath = function (context, x, y, width, height) { + + var halfWidth = width / 2; + var halfHeight = height / 2; + + var xBegin = x - halfWidth; + var xEnd = x + halfWidth; + var yBegin = y - halfHeight; + var yEnd = y + halfHeight; + + var barrelCurveConstants = math.getBarrelCurveConstants(width, height); + var wOffset = barrelCurveConstants.widthOffset; + var hOffset = barrelCurveConstants.heightOffset; + var ctrlPtXOffset = barrelCurveConstants.ctrlPtOffsetPct * wOffset; + + if (context.beginPath) { + context.beginPath(); + } + + context.moveTo(xBegin, yBegin + hOffset); + + context.lineTo(xBegin, yEnd - hOffset); + context.quadraticCurveTo(xBegin + ctrlPtXOffset, yEnd, xBegin + wOffset, yEnd); + + context.lineTo(xEnd - wOffset, yEnd); + context.quadraticCurveTo(xEnd - ctrlPtXOffset, yEnd, xEnd, yEnd - hOffset); + + context.lineTo(xEnd, yBegin + hOffset); + context.quadraticCurveTo(xEnd - ctrlPtXOffset, yBegin, xEnd - wOffset, yBegin); + + context.lineTo(xBegin + wOffset, yBegin); + context.quadraticCurveTo(xBegin + ctrlPtXOffset, yBegin, xBegin, yBegin + hOffset); + + context.closePath(); +}; + +var sin0 = Math.sin(0); +var cos0 = Math.cos(0); var sin = {}; var cos = {}; var ellipseStepSize = Math.PI / 40; -for( var i = 0 * Math.PI; i < 2 * Math.PI; i += ellipseStepSize ){ - sin[ i ] = Math.sin( i ); - cos[ i ] = Math.cos( i ); +for (var i = 0 * Math.PI; i < 2 * Math.PI; i += ellipseStepSize) { + sin[i] = Math.sin(i); + cos[i] = Math.cos(i); } -CRp.drawEllipsePath = function( context, centerX, centerY, width, height ){ - if( context.beginPath ){ context.beginPath(); } +CRp.drawEllipsePath = function (context, centerX, centerY, width, height) { + if (context.beginPath) { + context.beginPath(); + } - if( context.ellipse ){ - context.ellipse( centerX, centerY, width / 2, height / 2, 0, 0, 2 * Math.PI ); - } else { - var xPos, yPos; - var rw = width / 2; - var rh = height / 2; - for( var i = 0 * Math.PI; i < 2 * Math.PI; i += ellipseStepSize ){ - xPos = centerX - (rw * sin[ i ]) * sin0 + (rw * cos[ i ]) * cos0; - yPos = centerY + (rh * cos[ i ]) * sin0 + (rh * sin[ i ]) * cos0; + if (context.ellipse) { + context.ellipse(centerX, centerY, width / 2, height / 2, 0, 0, 2 * Math.PI); + } else { + var xPos, yPos; + var rw = width / 2; + var rh = height / 2; + for (var i = 0 * Math.PI; i < 2 * Math.PI; i += ellipseStepSize) { + xPos = centerX - rw * sin[i] * sin0 + rw * cos[i] * cos0; + yPos = centerY + rh * cos[i] * sin0 + rh * sin[i] * cos0; - if( i === 0 ){ - context.moveTo( xPos, yPos ); - } else { - context.lineTo( xPos, yPos ); - } + if (i === 0) { + context.moveTo(xPos, yPos); + } else { + context.lineTo(xPos, yPos); } } + } - context.closePath(); - }; + context.closePath(); +}; module.exports = CRp; -},{"../../../math":85}],72:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 135 */ +/***/ (function(module, exports, __webpack_require__) { -var math = _dereq_( '../../../math' ); -var util = _dereq_( '../../../util' ); -var Heap = _dereq_( '../../../heap' ); -var defs = _dereq_( './texture-cache-defs' ); +"use strict"; -var minTxrH = 25; // the size of the texture cache for small height eles (special case) -var txrStepH = 50; // the min size of the regular cache, and the size it increases with each step up -var minLvl = -4; // when scaling smaller than that we don't need to re-render -var maxLvl = 2; // when larger than this scale just render directly (caching is not helpful) -var maxZoom = 3.99; // beyond this zoom level, layered textures are not used -var eleTxrSpacing = 8; // spacing between elements on textures to avoid blitting overlaps -var defTxrWidth = 1024; // default/minimum texture width -var maxTxrW = 1024; // the maximum width of a texture -var maxTxrH = 1024; // the maximum height of a texture -var minUtility = 0.5; // if usage of texture is less than this, it is retired -var maxFullness = 0.8; // fullness of texture after which queue removal is checked -var maxFullnessChecks = 10; // dequeued after this many checks -var allowEdgeTxrCaching = false; // whether edges can be cached as textures (TODO maybe better on if webgl supported?) -var allowParentTxrCaching = false; // whether parent nodes can be cached as textures (TODO maybe better on if webgl supported?) -var deqCost = 0.15; // % of add'l rendering cost allowed for dequeuing ele caches each frame -var deqAvgCost = 0.1; // % of add'l rendering cost compared to average overall redraw time -var deqNoDrawCost = 0.9; // % of avg frame time that can be used for dequeueing when not drawing -var deqFastCost = 0.9; // % of frame time to be used when >60fps -var deqRedrawThreshold = 100; // time to batch redraws together from dequeueing to allow more dequeueing calcs to happen in the meanwhile -var maxDeqSize = 1; // number of eles to dequeue and render at higher texture in each batch -var getTxrReasons = { - dequeue: 'dequeue', - downscale: 'downscale', - highQuality: 'highQuality' -}; - -var ElementTextureCache = function( renderer ){ - var self = this; - - self.renderer = renderer; - self.onDequeues = []; - - self.setupDequeueing(); -}; - -var ETCp = ElementTextureCache.prototype; - -ETCp.reasons = getTxrReasons; - -// the list of textures in which new subtextures for elements can be placed -ETCp.getTextureQueue = function( txrH ){ - var self = this; - self.eleImgCaches = self.eleImgCaches || {}; - - return ( self.eleImgCaches[ txrH ] = self.eleImgCaches[ txrH ] || [] ); -}; - -// the list of usused textures which can be recycled (in use in texture queue) -ETCp.getRetiredTextureQueue = function( txrH ){ - var self = this; - - var rtxtrQs = self.eleImgCaches.retired = self.eleImgCaches.retired || {}; - var rtxtrQ = rtxtrQs[ txrH ] = rtxtrQs[ txrH ] || []; - - return rtxtrQ; -}; - -// queue of element draw requests at different scale levels -ETCp.getElementQueue = function(){ - var self = this; - - var q = self.eleCacheQueue = self.eleCacheQueue || new Heap(function( a, b ){ - return b.reqs - a.reqs; - }); - - return q; -}; - -// queue of element draw requests at different scale levels (element id lookup) -ETCp.getElementIdToQueue = function(){ - var self = this; - - var id2q = self.eleIdToCacheQueue = self.eleIdToCacheQueue || {}; - - return id2q; -}; - -ETCp.getElement = function( ele, bb, pxRatio, lvl, reason ){ - var self = this; - var r = this.renderer; - var rs = ele._private.rscratch; - var zoom = r.cy.zoom(); - - if( lvl == null ){ - lvl = Math.ceil( math.log2( zoom * pxRatio ) ); - } - - if( lvl < minLvl ){ - lvl = minLvl; - } else if( zoom >= maxZoom || lvl > maxLvl ){ - return null; - } - - var scale = Math.pow( 2, lvl ); - var eleScaledH = bb.h * scale; - var eleScaledW = bb.w * scale; - var caches = rs.imgCaches = rs.imgCaches || {}; - var eleCache = caches[lvl]; - - if( eleCache ){ - return eleCache; - } - - var txrH; // which texture height this ele belongs to - - if( eleScaledH <= minTxrH ){ - txrH = minTxrH; - } else if( eleScaledH <= txrStepH ){ - txrH = txrStepH; - } else { - txrH = Math.ceil( eleScaledH / txrStepH ) * txrStepH; - } - - if( - eleScaledH > maxTxrH - || eleScaledW > maxTxrW - || ( !allowEdgeTxrCaching && ele.isEdge() ) - || ( !allowParentTxrCaching && ele.isParent() ) - ){ - return null; // caching large elements is not efficient - } - - var txrQ = self.getTextureQueue( txrH ); - - // first try the second last one in case it has space at the end - var txr = txrQ[ txrQ.length - 2 ]; - - var addNewTxr = function(){ - return self.recycleTexture( txrH, eleScaledW ) || self.addTexture( txrH, eleScaledW ); - }; - - // try the last one if there is no second last one - if( !txr ){ - txr = txrQ[ txrQ.length - 1 ]; - } - - // if the last one doesn't exist, we need a first one - if( !txr ){ - txr = addNewTxr(); - } - - // if there's no room in the current texture, we need a new one - if( txr.width - txr.usedWidth < eleScaledW ){ - txr = addNewTxr(); - } - - var scaledLabelShown = r.eleTextBiggerThanMin( ele, scale ); - var scalableFrom = function( otherCache ){ - return otherCache && otherCache.scaledLabelShown === scaledLabelShown; - }; - - var deqing = reason && reason === getTxrReasons.dequeue; - var highQualityReq = reason && reason === getTxrReasons.highQuality; - var downscaleReq = reason && reason === getTxrReasons.downscale; - - var higherCache; // the nearest cache with a higher level - for( var l = lvl + 1; l <= maxLvl; l++ ){ - var c = caches[l]; - - if( c ){ higherCache = c; break; } - } - - var oneUpCache = higherCache && higherCache.level === lvl + 1 ? higherCache : null; - - var downscale = function(){ - txr.context.drawImage( - oneUpCache.texture.canvas, - oneUpCache.x, 0, - oneUpCache.width, oneUpCache.height, - txr.usedWidth, 0, - eleScaledW, eleScaledH - ); - }; - - if( scalableFrom(oneUpCache) ){ - // then we can relatively cheaply rescale the existing image w/o rerendering - downscale(); - - } else if( scalableFrom(higherCache) ){ - // then use the higher cache for now and queue the next level down - // to cheaply scale towards the smaller level - - if( highQualityReq ){ - for( var l = higherCache.level; l > lvl; l-- ){ - oneUpCache = self.getElement( ele, bb, pxRatio, l, getTxrReasons.downscale ); - } - - downscale(); - - } else { - self.queueElement( ele, bb, higherCache.level - 1 ); - - return higherCache; - } - } else { - - var lowerCache; // the nearest cache with a lower level - if( !deqing && !highQualityReq && !downscaleReq ){ - for( var l = lvl - 1; l >= minLvl; l-- ){ - var c = caches[l]; - - if( c ){ lowerCache = c; break; } - } - } - - if( scalableFrom(lowerCache) ){ - // then use the lower quality cache for now and queue the better one for later - - self.queueElement( ele, bb, lvl ); - - return lowerCache; - } - - txr.context.translate( txr.usedWidth, 0 ); - txr.context.scale( scale, scale ); - - r.drawElement( txr.context, ele, bb, scaledLabelShown ); - - txr.context.scale( 1/scale, 1/scale ); - txr.context.translate( -txr.usedWidth, 0 ); - } - - eleCache = caches[lvl] = { - ele: ele, - x: txr.usedWidth, - texture: txr, - level: lvl, - scale: scale, - width: eleScaledW, - height: eleScaledH, - scaledLabelShown: scaledLabelShown - }; - - txr.usedWidth += Math.ceil( eleScaledW + eleTxrSpacing ); - - txr.eleCaches.push( eleCache ); - - self.checkTextureFullness( txr ); - - return eleCache; -}; - -ETCp.invalidateElement = function( ele ){ - var self = this; - var caches = ele._private.rscratch.imgCaches; - - if( caches ){ - for( var lvl = minLvl; lvl <= maxLvl; lvl++ ){ - var cache = caches[ lvl ]; - - if( cache ){ - var txr = cache.texture; - - // remove space from the texture it belongs to - txr.invalidatedWidth += cache.width; - - // remove refs with the element - caches[ lvl ] = null; - util.removeFromArray( txr.eleCaches, cache ); - - // might have to remove the entire texture if it's not efficiently using its space - self.checkTextureUtility( txr ); - } - } - } -}; - -ETCp.checkTextureUtility = function( txr ){ - // invalidate all entries in the cache if the cache size is small - if( txr.invalidatedWidth >= minUtility * txr.width ){ - this.retireTexture( txr ); - } -}; - -ETCp.checkTextureFullness = function( txr ){ - // if texture has been mostly filled and passed over several times, remove - // it from the queue so we don't need to waste time looking at it to put new things - - var self = this; - var txrQ = self.getTextureQueue( txr.height ); - - if( txr.usedWidth / txr.width > maxFullness && txr.fullnessChecks >= maxFullnessChecks ){ - util.removeFromArray( txrQ, txr ); - } else { - txr.fullnessChecks++; - } -}; - -ETCp.retireTexture = function( txr ){ - var self = this; - var txrH = txr.height; - var txrQ = self.getTextureQueue( txrH ); - - // retire the texture from the active / searchable queue: - - util.removeFromArray( txrQ, txr ); - - txr.retired = true; - - // remove the refs from the eles to the caches: - - var eleCaches = txr.eleCaches; - - for( var i = 0; i < eleCaches.length; i++ ){ - var eleCache = eleCaches[i]; - var ele = eleCache.ele; - var lvl = eleCache.level; - var imgCaches = ele._private.rscratch.imgCaches; - - if( imgCaches ){ - imgCaches[ lvl ] = null; - } - } - - util.clearArray( eleCaches ); - - // add the texture to a retired queue so it can be recycled in future: - - var rtxtrQ = self.getRetiredTextureQueue( txrH ); - - rtxtrQ.push( txr ); -}; - -ETCp.addTexture = function( txrH, minW ){ - var self = this; - var txrQ = self.getTextureQueue( txrH ); - var txr = {}; - - txrQ.push( txr ); - - txr.eleCaches = []; - - txr.height = txrH; - txr.width = Math.max( defTxrWidth, minW ); - txr.usedWidth = 0; - txr.invalidatedWidth = 0; - txr.fullnessChecks = 0; - - txr.canvas = document.createElement('canvas'); // eslint-disable-line no-undef - txr.canvas.width = txr.width; - txr.canvas.height = txr.height; - - txr.context = txr.canvas.getContext('2d'); - - return txr; -}; - -ETCp.recycleTexture = function( txrH, minW ){ - var self = this; - var txrQ = self.getTextureQueue( txrH ); - var rtxtrQ = self.getRetiredTextureQueue( txrH ); - - for( var i = 0; i < rtxtrQ.length; i++ ){ - var txr = rtxtrQ[i]; - - if( txr.width >= minW ){ - txr.retired = false; - - txr.usedWidth = 0; - txr.invalidatedWidth = 0; - txr.fullnessChecks = 0; - - util.clearArray( txr.eleCaches ); - - txr.context.clearRect( 0, 0, txr.width, txr.height ); - - util.removeFromArray( rtxtrQ, txr ); - txrQ.push( txr ); - - return txr; - } - } -}; - -ETCp.queueElement = function( ele, bb, lvl ){ - var self = this; - var q = self.getElementQueue(); - var id2q = self.getElementIdToQueue(); - var id = ele.id(); - var existingReq = id2q[ id ]; - - if( existingReq ){ // use the max lvl b/c in between lvls are cheap to make - existingReq.level = Math.max( existingReq.level, lvl ); - existingReq.reqs++; - - q.updateItem( existingReq ); - } else { - var req = { - ele: ele, - bb: bb, - position: math.copyPosition( ele.position() ), - level: lvl, - reqs: 1 - }; - - if( ele.isEdge() ){ - req.positions = { - source: math.copyPosition( ele.source().position() ), - target: math.copyPosition( ele.target().position() ) - }; - } - - q.push( req ); - - id2q[ id ] = req; - } -}; - -ETCp.dequeue = function( pxRatio, extent ){ - var self = this; - var q = self.getElementQueue(); - var id2q = self.getElementIdToQueue(); - var dequeued = []; - - for( var i = 0; i < maxDeqSize; i++ ){ - if( q.size() > 0 ){ - var req = q.pop(); - - id2q[ req.ele.id() ] = null; - - dequeued.push( req ); - - var ele = req.ele; - var bb; - - if( - ( ele.isEdge() - && ( - !math.arePositionsSame( ele.source().position(), req.positions.source ) - || !math.arePositionsSame( ele.target().position(), req.positions.target ) - ) - ) - || ( !math.arePositionsSame( ele.position(), req.position ) ) - ){ - bb = ele.boundingBox(); - } else { - bb = req.bb; - } - - self.getElement( req.ele, bb, pxRatio, req.level, getTxrReasons.dequeue ); - } else { - break; - } - } - - return dequeued; -}; - -ETCp.onDequeue = function( fn ){ this.onDequeues.push( fn ); }; -ETCp.offDequeue = function( fn ){ util.removeFromArray( this.onDequeues, fn ); }; - -ETCp.setupDequeueing = defs.setupDequeueing({ - deqRedrawThreshold: deqRedrawThreshold, - deqCost: deqCost, - deqAvgCost: deqAvgCost, - deqNoDrawCost: deqNoDrawCost, - deqFastCost: deqFastCost, - deq: function( self, pxRatio, extent ){ - return self.dequeue( pxRatio, extent ); - }, - onDeqd: function( self, deqd ){ - for( var i = 0; i < self.onDequeues.length; i++ ){ - var fn = self.onDequeues[i]; - - fn( deqd ); - } - }, - shouldRedraw: function( self, deqd, pxRatio, extent ){ - for( var i = 0; i < deqd.length; i++ ){ - var bb = deqd[i].bb; - - if( math.boundingBoxesIntersect( bb, extent ) ){ - return true; - } - } - - return false; - }, - priority: function( self ){ - return self.renderer.beforeRenderPriorities.eleTxrDeq; - } -}); - -module.exports = ElementTextureCache; - -},{"../../../heap":81,"../../../math":85,"../../../util":100,"./texture-cache-defs":77}],73:[function(_dereq_,module,exports){ -'use strict'; - -var is = _dereq_( '../../../is' ); +var is = __webpack_require__(0); var CRp = {}; -CRp.createBuffer = function( w, h ){ - var buffer = document.createElement( 'canvas' ); // eslint-disable-line no-undef +CRp.createBuffer = function (w, h) { + var buffer = document.createElement('canvas'); // eslint-disable-line no-undef buffer.width = w; buffer.height = h; - return [ buffer, buffer.getContext( '2d' ) ]; + return [buffer, buffer.getContext('2d')]; }; -CRp.bufferCanvasImage = function( options ){ +CRp.bufferCanvasImage = function (options) { var cy = this.cy; var eles = cy.mutableElements(); var bb = eles.boundingBox(); - var width = options.full ? Math.ceil( bb.w ) : this.container.clientWidth; - var height = options.full ? Math.ceil( bb.h ) : this.container.clientHeight; - var specdMaxDims = is.number( options.maxWidth ) || is.number( options.maxHeight ); + var ctrRect = this.findContainerClientCoords(); + var width = options.full ? Math.ceil(bb.w) : ctrRect[2]; + var height = options.full ? Math.ceil(bb.h) : ctrRect[3]; + var specdMaxDims = is.number(options.maxWidth) || is.number(options.maxHeight); var pxRatio = this.getPixelRatio(); var scale = 1; - if( options.scale !== undefined ){ + if (options.scale !== undefined) { width *= options.scale; height *= options.scale; scale = options.scale; - } else if( specdMaxDims ){ + } else if (specdMaxDims) { var maxScaleW = Infinity; var maxScaleH = Infinity; - if( is.number( options.maxWidth ) ){ + if (is.number(options.maxWidth)) { maxScaleW = scale * options.maxWidth / width; } - if( is.number( options.maxHeight ) ){ + if (is.number(options.maxHeight)) { maxScaleH = scale * options.maxHeight / height; } - scale = Math.min( maxScaleW, maxScaleH ); + scale = Math.min(maxScaleW, maxScaleH); width *= scale; height *= scale; } - if( !specdMaxDims ){ + if (!specdMaxDims) { width *= pxRatio; height *= pxRatio; scale *= pxRatio; } - var buffCanvas = document.createElement( 'canvas' ); // eslint-disable-line no-undef + var buffCanvas = document.createElement('canvas'); // eslint-disable-line no-undef buffCanvas.width = width; buffCanvas.height = height; @@ -19171,29 +29697,28 @@ CRp.bufferCanvasImage = function( options ){ buffCanvas.style.width = width + 'px'; buffCanvas.style.height = height + 'px'; - var buffCxt = buffCanvas.getContext( '2d' ); + var buffCxt = buffCanvas.getContext('2d'); // Rasterize the layers, but only if container has nonzero size - if( width > 0 && height > 0 ){ + if (width > 0 && height > 0) { - buffCxt.clearRect( 0, 0, width, height ); - - if( options.bg ){ - buffCxt.fillStyle = options.bg; - buffCxt.rect( 0, 0, width, height ); - buffCxt.fill(); - } + buffCxt.clearRect(0, 0, width, height); buffCxt.globalCompositeOperation = 'source-over'; var zsortedEles = this.getCachedZSortedEles(); - if( options.full ){ // draw the full bounds of the graph - buffCxt.translate( -bb.x1 * scale, -bb.y1 * scale ); - buffCxt.scale( scale, scale ); + if (options.full) { + // draw the full bounds of the graph + buffCxt.translate(-bb.x1 * scale, -bb.y1 * scale); + buffCxt.scale(scale, scale); - this.drawElements( buffCxt, zsortedEles ); - } else { // draw the current view + this.drawElements(buffCxt, zsortedEles); + + buffCxt.scale(1 / scale, 1 / scale); + buffCxt.translate(bb.x1 * scale, bb.y1 * scale); + } else { + // draw the current view var pan = cy.pan(); var translation = { @@ -19203,6398 +29728,115 @@ CRp.bufferCanvasImage = function( options ){ scale *= cy.zoom(); - buffCxt.translate( translation.x, translation.y ); - buffCxt.scale( scale, scale ); + buffCxt.translate(translation.x, translation.y); + buffCxt.scale(scale, scale); - this.drawElements( buffCxt, zsortedEles ); + this.drawElements(buffCxt, zsortedEles); + + buffCxt.scale(1 / scale, 1 / scale); + buffCxt.translate(-translation.x, -translation.y); + } + + // need to fill bg at end like this in order to fill cleared transparent pixels in jpgs + if (options.bg) { + buffCxt.globalCompositeOperation = 'destination-over'; + + buffCxt.fillStyle = options.bg; + buffCxt.rect(0, 0, width, height); + buffCxt.fill(); } } return buffCanvas; }; -CRp.png = function( options ){ - return this.bufferCanvasImage( options ).toDataURL( 'image/png' ); +function b64ToBlob(b64, mimeType) { + var bytes = atob(b64); + var buff = new ArrayBuffer(bytes.length); + var buffUint8 = new Uint8Array(buff); + + for (var i = 0; i < bytes.length; i++) { + buffUint8[i] = bytes.charCodeAt(i); + } + + return new Blob([buff], { type: mimeType }); +} + +function b64UriToB64(b64uri) { + var i = b64uri.indexOf(','); + + return b64uri.substr(i + 1); }; -CRp.jpg = function( options ){ - return this.bufferCanvasImage( options ).toDataURL( 'image/jpeg' ); +function output(options, canvas, mimeType) { + var b64Uri = canvas.toDataURL(mimeType, options.quality); + + switch (options.output) { + case 'blob': + return b64ToBlob(b64UriToB64(b64Uri), mimeType); + + case 'base64': + return b64UriToB64(b64Uri); + + case 'base64uri': + default: + return b64Uri; + } +} + +CRp.png = function (options) { + return output(options, this.bufferCanvasImage(options), 'image/png'); +}; + +CRp.jpg = function (options) { + return output(options, this.bufferCanvasImage(options), 'image/jpeg'); }; module.exports = CRp; -},{"../../../is":83}],74:[function(_dereq_,module,exports){ -/* -The canvas renderer was written by Yue Dong. +/***/ }), +/* 136 */ +/***/ (function(module, exports, __webpack_require__) { -Modifications tracked on Github. -*/ +"use strict"; -'use strict'; - -var util = _dereq_( '../../../util' ); -var is = _dereq_( '../../../is' ); -var ElementTextureCache = _dereq_('./ele-texture-cache'); -var LayeredTextureCache = _dereq_('./layered-texture-cache'); - -var CR = CanvasRenderer; -var CRp = CanvasRenderer.prototype; - -CRp.CANVAS_LAYERS = 3; -// -CRp.SELECT_BOX = 0; -CRp.DRAG = 1; -CRp.NODE = 2; - -CRp.BUFFER_COUNT = 3; -// -CRp.TEXTURE_BUFFER = 0; -CRp.MOTIONBLUR_BUFFER_NODE = 1; -CRp.MOTIONBLUR_BUFFER_DRAG = 2; - -function CanvasRenderer( options ){ - var r = this; - - r.data = { - canvases: new Array( CRp.CANVAS_LAYERS ), - contexts: new Array( CRp.CANVAS_LAYERS ), - canvasNeedsRedraw: new Array( CRp.CANVAS_LAYERS ), - - bufferCanvases: new Array( CRp.BUFFER_COUNT ), - bufferContexts: new Array( CRp.CANVAS_LAYERS ), - }; - - r.data.canvasContainer = document.createElement( 'div' ); // eslint-disable-line no-undef - var containerStyle = r.data.canvasContainer.style; - r.data.canvasContainer.setAttribute( 'style', '-webkit-tap-highlight-color: rgba(0,0,0,0);' ); - containerStyle.position = 'relative'; - containerStyle.zIndex = '0'; - containerStyle.overflow = 'hidden'; - - var container = options.cy.container(); - container.appendChild( r.data.canvasContainer ); - container.setAttribute( 'style', ( container.getAttribute( 'style' ) || '' ) + '-webkit-tap-highlight-color: rgba(0,0,0,0);' ); - - for( var i = 0; i < CRp.CANVAS_LAYERS; i++ ){ - var canvas = r.data.canvases[ i ] = document.createElement( 'canvas' ); // eslint-disable-line no-undef - r.data.contexts[ i ] = canvas.getContext( '2d' ); - canvas.setAttribute( 'style', '-webkit-user-select: none; -moz-user-select: -moz-none; user-select: none; -webkit-tap-highlight-color: rgba(0,0,0,0); outline-style: none;' + ( is.ms() ? ' -ms-touch-action: none; touch-action: none; ' : '' ) ); - canvas.style.position = 'absolute'; - canvas.setAttribute( 'data-id', 'layer' + i ); - canvas.style.zIndex = String( CRp.CANVAS_LAYERS - i ); - r.data.canvasContainer.appendChild( canvas ); - - r.data.canvasNeedsRedraw[ i ] = false; - } - r.data.topCanvas = r.data.canvases[0]; - - r.data.canvases[ CRp.NODE ].setAttribute( 'data-id', 'layer' + CRp.NODE + '-node' ); - r.data.canvases[ CRp.SELECT_BOX ].setAttribute( 'data-id', 'layer' + CRp.SELECT_BOX + '-selectbox' ); - r.data.canvases[ CRp.DRAG ].setAttribute( 'data-id', 'layer' + CRp.DRAG + '-drag' ); - - for( var i = 0; i < CRp.BUFFER_COUNT; i++ ){ - r.data.bufferCanvases[ i ] = document.createElement( 'canvas' ); // eslint-disable-line no-undef - r.data.bufferContexts[ i ] = r.data.bufferCanvases[ i ].getContext( '2d' ); - r.data.bufferCanvases[ i ].style.position = 'absolute'; - r.data.bufferCanvases[ i ].setAttribute( 'data-id', 'buffer' + i ); - r.data.bufferCanvases[ i ].style.zIndex = String( -i - 1 ); - r.data.bufferCanvases[ i ].style.visibility = 'hidden'; - //r.data.canvasContainer.appendChild(r.data.bufferCanvases[i]); - } - - r.pathsEnabled = true; - - r.data.eleTxrCache = new ElementTextureCache( r ); - r.data.lyrTxrCache = new LayeredTextureCache( r, r.data.eleTxrCache ); - - r.onUpdateEleCalcs(function invalidateTextureCaches( willDraw, eles ){ - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[i]; - var rs = ele._private.rstyle; - var de = rs.dirtyEvents; - - if( ele.isNode() && de && de.length === 1 && de['position'] ){ - // then keep cached ele texture - } else { - r.data.eleTxrCache.invalidateElement( ele ); - } - } - - if( eles.length > 0 ){ - r.data.lyrTxrCache.invalidateElements( eles ); - } - }); -} - -CRp.redrawHint = function( group, bool ){ - var r = this; - - switch( group ){ - case 'eles': - r.data.canvasNeedsRedraw[ CRp.NODE ] = bool; - break; - case 'drag': - r.data.canvasNeedsRedraw[ CRp.DRAG ] = bool; - break; - case 'select': - r.data.canvasNeedsRedraw[ CRp.SELECT_BOX ] = bool; - break; - } -}; - -// whether to use Path2D caching for drawing -var pathsImpld = typeof Path2D !== 'undefined'; - -CRp.path2dEnabled = function( on ){ - if( on === undefined ){ - return this.pathsEnabled; - } - - this.pathsEnabled = on ? true : false; -}; - -CRp.usePaths = function(){ - return pathsImpld && this.pathsEnabled; -}; - -[ - _dereq_( './arrow-shapes' ), - _dereq_( './drawing-elements' ), - _dereq_( './drawing-edges' ), - _dereq_( './drawing-images' ), - _dereq_( './drawing-label-text' ), - _dereq_( './drawing-nodes' ), - _dereq_( './drawing-redraw' ), - _dereq_( './drawing-shapes' ), - _dereq_( './export-image' ), - _dereq_( './node-shapes' ) -].forEach( function( props ){ - util.extend( CRp, props ); -} ); - -module.exports = CR; - -},{"../../../is":83,"../../../util":100,"./arrow-shapes":64,"./drawing-edges":65,"./drawing-elements":66,"./drawing-images":67,"./drawing-label-text":68,"./drawing-nodes":69,"./drawing-redraw":70,"./drawing-shapes":71,"./ele-texture-cache":72,"./export-image":73,"./layered-texture-cache":75,"./node-shapes":76}],75:[function(_dereq_,module,exports){ -'use strict'; - -var util = _dereq_( '../../../util' ); -var math = _dereq_( '../../../math' ); -var Heap = _dereq_( '../../../heap' ); -var is = _dereq_( '../../../is' ); -var defs = _dereq_( './texture-cache-defs' ); - -var defNumLayers = 1; // default number of layers to use -var minLvl = -4; // when scaling smaller than that we don't need to re-render -var maxLvl = 2; // when larger than this scale just render directly (caching is not helpful) -var maxZoom = 3.99; // beyond this zoom level, layered textures are not used -var deqRedrawThreshold = 50; // time to batch redraws together from dequeueing to allow more dequeueing calcs to happen in the meanwhile -var refineEleDebounceTime = 50; // time to debounce sharper ele texture updates -var disableEleImgSmoothing = true; // when drawing eles on layers from an ele cache ; crisper and more performant when true -var deqCost = 0.15; // % of add'l rendering cost allowed for dequeuing ele caches each frame -var deqAvgCost = 0.1; // % of add'l rendering cost compared to average overall redraw time -var deqNoDrawCost = 0.9; // % of avg frame time that can be used for dequeueing when not drawing -var deqFastCost = 0.9; // % of frame time to be used when >60fps -var maxDeqSize = 1; // number of eles to dequeue and render at higher texture in each batch -var invalidThreshold = 250; // time threshold for disabling b/c of invalidations -var maxLayerArea = 4000 * 4000; // layers can't be bigger than this -var alwaysQueue = true; // never draw all the layers in a level on a frame; draw directly until all dequeued -var useHighQualityEleTxrReqs = true; // whether to use high quality ele txr requests (generally faster and cheaper in the longterm) - -var useEleTxrCaching = true; // whether to use individual ele texture caching underneath this cache - -// var log = function(){ console.log.apply( console, arguments ); }; - -var LayeredTextureCache = function( renderer, eleTxrCache ){ - var self = this; - - var r = self.renderer = renderer; - - self.layersByLevel = {}; // e.g. 2 => [ layer1, layer2, ..., layerN ] - - self.firstGet = true; - - self.lastInvalidationTime = util.performanceNow() - 2*invalidThreshold; - - self.skipping = false; - - r.beforeRender(function( willDraw, now ){ - if( now - self.lastInvalidationTime <= invalidThreshold ){ - self.skipping = true; - } else { - self.skipping = false; - } - }); - - var qSort = function(a, b){ - return b.reqs - a.reqs; - }; - - self.layersQueue = new Heap( qSort ); - - self.eleTxrCache = eleTxrCache; - - self.setupEleCacheInvalidation(); - - self.setupDequeueing(); -}; - -var LTCp = LayeredTextureCache.prototype; - -var layerIdPool = 0; -var MAX_INT = Math.pow(2, 53) - 1; - -LTCp.makeLayer = function( bb, lvl ){ - var scale = Math.pow( 2, lvl ); - - var w = Math.ceil( bb.w * scale ); - var h = Math.ceil( bb.h * scale ); - - var canvas = document.createElement('canvas'); // eslint-disable-line no-undef - - canvas.width = w; - canvas.height = h; - - var layer = { - id: (layerIdPool = ++layerIdPool % MAX_INT ), - bb: bb, - level: lvl, - width: w, - height: h, - canvas: canvas, - context: canvas.getContext('2d'), - eles: [], - elesQueue: [], - reqs: 0 - }; - - // log('make layer %s with w %s and h %s and lvl %s', layer.id, layer.width, layer.height, layer.level); - - var cxt = layer.context; - var dx = -layer.bb.x1; - var dy = -layer.bb.y1; - - // do the transform on creation to save cycles (it's the same for all eles) - cxt.scale( scale, scale ); - cxt.translate( dx, dy ); - - return layer; -}; - -LTCp.getLayers = function( eles, pxRatio, lvl ){ - var self = this; - var r = self.renderer; - var cy = r.cy; - var zoom = cy.zoom(); - var firstGet = self.firstGet; - - self.firstGet = false; - - // log('--\nget layers with %s eles', eles.length); - //log eles.map(function(ele){ return ele.id() }) ); - - if( lvl == null ){ - lvl = Math.ceil( math.log2( zoom * pxRatio ) ); - - if( lvl < minLvl ){ - lvl = minLvl; - } else if( zoom >= maxZoom || lvl > maxLvl ){ - return null; - } - } - - self.validateLayersElesOrdering( lvl, eles ); - - var layersByLvl = self.layersByLevel; - var scale = Math.pow( 2, lvl ); - var layers = layersByLvl[ lvl ] = layersByLvl[ lvl ] || []; - var bb; - - var lvlComplete = self.levelIsComplete( lvl, eles ); - var tmpLayers; - - var checkTempLevels = function(){ - var canUseAsTmpLvl = function( l ){ - self.validateLayersElesOrdering( l, eles ); - - if( self.levelIsComplete( l, eles ) ){ - tmpLayers = layersByLvl[l]; - return true; - } - }; - - var checkLvls = function( dir ){ - if( tmpLayers ){ return; } - - for( var l = lvl + dir; minLvl <= l && l <= maxLvl; l += dir ){ - if( canUseAsTmpLvl(l) ){ break; } - } - }; - - checkLvls( +1 ); - checkLvls( -1 ); - - // remove the invalid layers; they will be replaced as needed later in this function - for( var i = layers.length - 1; i >= 0; i-- ){ - var layer = layers[i]; - - if( layer.invalid ){ - util.removeFromArray( layers, layer ); - } - } - }; - - if( !lvlComplete ){ - // if the current level is incomplete, then use the closest, best quality layerset temporarily - // and later queue the current layerset so we can get the proper quality level soon - - checkTempLevels(); - - } else { - // log('level complete, using existing layers\n--'); - return layers; - } - - var getBb = function(){ - if( !bb ){ - bb = math.makeBoundingBox(); - - for( var i = 0; i < eles.length; i++ ){ - math.updateBoundingBox( bb, eles[i].boundingBox() ); - } - } - - return bb; - }; - - var makeLayer = function( opts ){ - opts = opts || {}; - - var after = opts.after; - - getBb(); - - var area = ( bb.w * scale ) * ( bb.h * scale ); - - if( area > maxLayerArea ){ - return null; - } - - var layer = self.makeLayer( bb, lvl ); - - if( after != null ){ - var index = layers.indexOf( after ) + 1; - - layers.splice( index, 0, layer ); - } else if( opts.insert === undefined || opts.insert ){ - // no after specified => first layer made so put at start - layers.unshift( layer ); - } - - // if( tmpLayers ){ - //self.queueLayer( layer ); - // } - - return layer; - }; - - if( self.skipping && !firstGet ){ - // log('skip layers'); - return null; - } - - // log('do layers'); - - var layer = null; - var maxElesPerLayer = eles.length / defNumLayers; - var allowLazyQueueing = alwaysQueue && !firstGet; - - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[i]; - var rs = ele._private.rscratch; - var caches = rs.imgLayerCaches = rs.imgLayerCaches || {}; - - // log('look at ele', ele.id()); - - var existingLayer = caches[ lvl ]; - - if( existingLayer ){ - // reuse layer for later eles - // log('reuse layer for', ele.id()); - layer = existingLayer; - continue; - } - - if( - !layer - || layer.eles.length >= maxElesPerLayer - || ( defNumLayers > 1 && !math.boundingBoxInBoundingBox( layer.bb, ele.boundingBox() ) ) - ){ - // log('make new layer for ele %s', ele.id()); - - layer = makeLayer({ insert: true, after: layer }); - - // if now layer can be built then we can't use layers at this level - if( !layer ){ return null; } - - // log('new layer with id %s', layer.id); - } - - if( tmpLayers || allowLazyQueueing ){ - // log('queue ele %s in layer %s', ele.id(), layer.id); - self.queueLayer( layer, ele ); - } else { - // log('draw ele %s in layer %s', ele.id(), layer.id); - self.drawEleInLayer( layer, ele, lvl, pxRatio ); - } - - layer.eles.push( ele ); - - caches[ lvl ] = layer; - } - - // log('--'); - - if( tmpLayers ){ // then we only queued the current layerset and can't draw it yet - return tmpLayers; - } - - if( allowLazyQueueing ){ - // log('lazy queue level', lvl); - return null; - } - - return layers; -}; - -// a layer may want to use an ele cache of a higher level to avoid blurriness -// so the layer level might not equal the ele level -LTCp.getEleLevelForLayerLevel = function( lvl, pxRatio ){ - return lvl; -}; - -function imgSmoothing( context, bool ){ - if( context.imageSmoothingEnabled != null ){ - context.imageSmoothingEnabled = bool; - } else { - context.webkitImageSmoothingEnabled = bool; - context.mozImageSmoothingEnabled = bool; - context.msImageSmoothingEnabled = bool; - } -} - -LTCp.drawEleInLayer = function( layer, ele, lvl, pxRatio ){ - var self = this; - var r = this.renderer; - var context = layer.context; - var bb = ele.boundingBox(); - var eleCache = self.eleTxrCache; - var reason = useHighQualityEleTxrReqs ? eleCache.reasons.highQuality : undefined; - - lvl = self.getEleLevelForLayerLevel( lvl, pxRatio ); - - var cache = useEleTxrCaching ? eleCache.getElement( ele, bb, null, lvl, reason ) : null; - - if( cache ){ - if( disableEleImgSmoothing ){ imgSmoothing( context, false ); } - - context.drawImage( cache.texture.canvas, cache.x, 0, cache.width, cache.height, bb.x1, bb.y1, bb.w, bb.h ); - - if( disableEleImgSmoothing ){ imgSmoothing( context, true ); } - } else { // if the element is not cacheable, then draw directly - r.drawElement( context, ele ); - } -}; - -LTCp.levelIsComplete = function( lvl, eles ){ - var self = this; - var layers = self.layersByLevel[ lvl ]; - - if( !layers || layers.length === 0 ){ return false; } - - var numElesInLayers = 0; - - for( var i = 0; i < layers.length; i++ ){ - var layer = layers[i]; - - // if there are any eles needed to be drawn yet, the level is not complete - if( layer.reqs > 0 ){ return false; } - - // if the layer is invalid, the level is not complete - if( layer.invalid ){ return false; } - - numElesInLayers += layer.eles.length; - } - - // we should have exactly the number of eles passed in to be complete - if( numElesInLayers !== eles.length ){ return false; } - - return true; -}; - -LTCp.validateLayersElesOrdering = function( lvl, eles ){ - var layers = this.layersByLevel[ lvl ]; - - if( !layers ){ return; } - - // if in a layer the eles are not in the same order, then the layer is invalid - // (i.e. there is an ele in between the eles in the layer) - - for( var i = 0; i < layers.length; i++ ){ - var layer = layers[i]; - var offset = -1; - - // find the offset - for( var j = 0; j < eles.length; j++ ){ - if( layer.eles[0] === eles[j] ){ - offset = j; - break; - } - } - - if( offset < 0 ){ - // then the layer has nonexistant elements and is invalid - this.invalidateLayer( layer ); - continue; - } - - // the eles in the layer must be in the same continuous order, else the layer is invalid - - var o = offset; - - for( var j = 0; j < layer.eles.length; j++ ){ - if( layer.eles[j] !== eles[o+j] ){ - // log('invalidate based on ordering', layer.id); - - this.invalidateLayer( layer ); - break; - } - } - } -}; - -LTCp.updateElementsInLayers = function( eles, update ){ - var self = this; - var isEles = is.element( eles[0] ); - - // collect udpated elements (cascaded from the layers) and update each - // layer itself along the way - for( var i = 0; i < eles.length; i++ ){ - var req = isEles ? null : eles[i]; - var ele = isEles ? eles[i] : eles[i].ele; - var rs = ele._private.rscratch; - var caches = rs.imgLayerCaches = rs.imgLayerCaches || {}; - - for( var l = minLvl; l <= maxLvl; l++ ){ - var layer = caches[l]; - - if( !layer ){ continue; } - - // if update is a request from the ele cache, then it affects only - // the matching level - if( req && self.getEleLevelForLayerLevel( layer.level ) !== req.level ){ - continue; - } - - update( layer, ele, req ); - } - } -}; - -LTCp.haveLayers = function(){ - var self = this; - var haveLayers = false; - - for( var l = minLvl; l <= maxLvl; l++ ){ - var layers = self.layersByLevel[l]; - - if( layers && layers.length > 0 ){ - haveLayers = true; - break; - } - } - - return haveLayers; -}; - -LTCp.invalidateElements = function( eles ){ - var self = this; - - self.lastInvalidationTime = util.performanceNow(); - - // log('update invalidate layer time from eles'); - - if( eles.length === 0 || !self.haveLayers() ){ return; } - - self.updateElementsInLayers( eles, function invalAssocLayers( layer, ele, req ){ - self.invalidateLayer( layer ); - } ); -}; - -LTCp.invalidateLayer = function( layer ){ - // log('update invalidate layer time'); - - this.lastInvalidationTime = util.performanceNow(); - - if( layer.invalid ){ return; } // save cycles - - var lvl = layer.level; - var eles = layer.eles; - var layers = this.layersByLevel[ lvl ]; - - // log('invalidate layer', layer.id ); - - util.removeFromArray( layers, layer ); - // layer.eles = []; - - layer.elesQueue = []; - - layer.invalid = true; - - if( layer.replacement ){ - layer.replacement.invalid = true; - } - - for( var i = 0; i < eles.length; i++ ){ - var caches = eles[i]._private.rscratch.imgLayerCaches; - - if( caches ){ - caches[ lvl ] = null; - } - } -}; - -LTCp.refineElementTextures = function( eles ){ - var self = this; - - // log('refine', eles.length); - - self.updateElementsInLayers( eles, function refineEachEle( layer, ele, req ){ - var rLyr = layer.replacement; - - if( !rLyr ){ - rLyr = layer.replacement = self.makeLayer( layer.bb, layer.level ); - rLyr.replaces = layer; - rLyr.eles = layer.eles; - - // log('make replacement layer %s for %s with level %s', rLyr.id, layer.id, rLyr.level); - } - - if( !rLyr.reqs ){ - for( var i = 0; i < rLyr.eles.length; i++ ){ - self.queueLayer( rLyr, rLyr.eles[i] ); - } - - // log('queue replacement layer refinement', rLyr.id); - } - } ); -}; - -LTCp.setupEleCacheInvalidation = function(){ - var self = this; - var eleDeqs = []; - - if( !useEleTxrCaching ){ return; } - - var updatedElesInLayers = util.debounce( function(){ - self.refineElementTextures( eleDeqs ); - - eleDeqs = []; - }, refineEleDebounceTime ); - - self.eleTxrCache.onDequeue(function( reqs ){ - for( var i = 0; i < reqs.length; i++ ){ - eleDeqs.push( reqs[i] ); - } - - updatedElesInLayers(); - }); -}; - -LTCp.queueLayer = function( layer, ele ){ - var self = this; - var q = self.layersQueue; - var elesQ = layer.elesQueue; - var hasId = elesQ.hasId = elesQ.hasId || {}; - - // if a layer is going to be replaced, queuing is a waste of time - if( layer.replacement ){ return; } - - if( ele ){ - if( hasId[ ele.id() ] ){ - return; - } - - elesQ.push( ele ); - hasId[ ele.id() ] = true; - } - - if( layer.reqs ){ - layer.reqs++; - - q.updateItem( layer ); - } else { - layer.reqs = 1; - - q.push( layer ); - } -}; - -LTCp.dequeue = function( pxRatio ){ - var self = this; - var q = self.layersQueue; - var deqd = []; - var eleDeqs = 0; - - while( eleDeqs < maxDeqSize ){ - if( q.size() === 0 ){ break; } - - var layer = q.peek(); - - // if a layer has been or will be replaced, then don't waste time with it - if( layer.replacement ){ - // log('layer %s in queue skipped b/c it already has a replacement', layer.id); - q.pop(); - continue; - } - - // if this is a replacement layer that has been superceded, then forget it - if( layer.replaces && layer !== layer.replaces.replacement ){ - // log('layer is no longer the most uptodate replacement; dequeued', layer.id) - q.pop(); - continue; - } - - if( layer.invalid ){ - // log('replacement layer %s is invalid; dequeued', layer.id); - q.pop(); - continue; - } - - var ele = layer.elesQueue.shift(); - - if( ele ){ - // log('dequeue layer %s', layer.id); - - self.drawEleInLayer( layer, ele, layer.level, pxRatio ); - - eleDeqs++; - } - - if( deqd.length === 0 ){ - // we need only one entry in deqd to queue redrawing etc - deqd.push( true ); - } - - // if the layer has all its eles done, then remove from the queue - if( layer.elesQueue.length === 0 ){ - q.pop(); - - layer.reqs = 0; - - // log('dequeue of layer %s complete', layer.id); - - // when a replacement layer is dequeued, it replaces the old layer in the level - if( layer.replaces ){ - self.applyLayerReplacement( layer ); - } - - self.requestRedraw(); - } - } - - return deqd; -}; - -LTCp.applyLayerReplacement = function( layer ){ - var self = this; - var layersInLevel = self.layersByLevel[ layer.level ]; - var replaced = layer.replaces; - var index = layersInLevel.indexOf( replaced ); - - // if the replaced layer is not in the active list for the level, then replacing - // refs would be a mistake (i.e. overwriting the true active layer) - if( index < 0 || replaced.invalid ){ - // log('replacement layer would have no effect', layer.id); - return; - } - - layersInLevel[ index ] = layer; // replace level ref - - // replace refs in eles - for( var i = 0; i < layer.eles.length; i++ ){ - var _p = layer.eles[i]._private; - var cache = _p.imgLayerCaches = _p.imgLayerCaches || {}; - - if( cache ){ - cache[ layer.level ] = layer; - } - } - - // log('apply replacement layer %s over %s', layer.id, replaced.id); - - self.requestRedraw(); -}; - -LTCp.requestRedraw = util.debounce( function(){ - var r = this.renderer; - - r.redrawHint( 'eles', true ); - r.redrawHint( 'drag', true ); - r.redraw(); -}, 100 ); - -LTCp.setupDequeueing = defs.setupDequeueing({ - deqRedrawThreshold: deqRedrawThreshold, - deqCost: deqCost, - deqAvgCost: deqAvgCost, - deqNoDrawCost: deqNoDrawCost, - deqFastCost: deqFastCost, - deq: function( self, pxRatio ){ - return self.dequeue( pxRatio ); - }, - onDeqd: util.noop, - shouldRedraw: util.trueify, - priority: function( self ){ - return self.renderer.beforeRenderPriorities.lyrTxrDeq; - } -}); - -module.exports = LayeredTextureCache; - -},{"../../../heap":81,"../../../is":83,"../../../math":85,"../../../util":100,"./texture-cache-defs":77}],76:[function(_dereq_,module,exports){ -'use strict'; var CRp = {}; -CRp.nodeShapeImpl = function( name, context, centerX, centerY, width, height, points ){ - switch( name ){ +CRp.nodeShapeImpl = function (name, context, centerX, centerY, width, height, points) { + switch (name) { case 'ellipse': - return this.drawEllipsePath( context, centerX, centerY, width, height ); + return this.drawEllipsePath(context, centerX, centerY, width, height); case 'polygon': - return this.drawPolygonPath( context, centerX, centerY, width, height, points ); + return this.drawPolygonPath(context, centerX, centerY, width, height, points); case 'roundrectangle': - return this.drawRoundRectanglePath( context, centerX, centerY, width, height ); + return this.drawRoundRectanglePath(context, centerX, centerY, width, height); + case 'cutrectangle': + return this.drawCutRectanglePath(context, centerX, centerY, width, height); + case 'bottomroundrectangle': + return this.drawBottomRoundRectanglePath(context, centerX, centerY, width, height); + case 'barrel': + return this.drawBarrelPath(context, centerX, centerY, width, height); } }; module.exports = CRp; -},{}],77:[function(_dereq_,module,exports){ -'use strict'; +/***/ }), +/* 137 */ +/***/ (function(module, exports, __webpack_require__) { -var util = _dereq_( '../../../util' ); +"use strict"; -var fullFpsTime = 1000/60; // assume 60 frames per second -module.exports = { - setupDequeueing: function( opts ){ - return function setupDequeueingImpl(){ - var self = this; - var r = this.renderer; - - if( self.dequeueingSetup ){ - return; - } else { - self.dequeueingSetup = true; - } - - var queueRedraw = util.debounce( function(){ - r.redrawHint( 'eles', true ); - r.redrawHint( 'drag', true ); - - r.redraw(); - }, opts.deqRedrawThreshold ); - - var dequeue = function( willDraw, frameStartTime ){ - var startTime = util.performanceNow(); - var avgRenderTime = r.averageRedrawTime; - var renderTime = r.lastRedrawTime; - var deqd = []; - var extent = r.cy.extent(); - var pixelRatio = r.getPixelRatio(); - - while( true ){ - var now = util.performanceNow(); - var duration = now - startTime; - var frameDuration = now - frameStartTime; - - if( renderTime < fullFpsTime ){ - // if we're rendering faster than the ideal fps, then do dequeueing - // during all of the remaining frame time - - var timeAvailable = fullFpsTime - ( willDraw ? avgRenderTime : 0 ); - - if( frameDuration >= opts.deqFastCost * timeAvailable ){ - break; - } - } else { - if( willDraw ){ - if( - duration >= opts.deqCost * renderTime - || duration >= opts.deqAvgCost * avgRenderTime - ){ - break; - } - } else if( frameDuration >= opts.deqNoDrawCost * fullFpsTime ){ - break; - } - } - - var thisDeqd = opts.deq( self, pixelRatio, extent ); - - if( thisDeqd.length > 0 ){ - for( var i = 0; i < thisDeqd.length; i++ ){ - deqd.push( thisDeqd[i] ); - } - } else { - break; - } - } - - // callbacks on dequeue - if( deqd.length > 0 ){ - opts.onDeqd( self, deqd ); - - if( !willDraw && opts.shouldRedraw( self, deqd, pixelRatio, extent ) ){ - queueRedraw(); - } - } - }; - - var priority = opts.priority || util.noop; - - r.beforeRender( dequeue, priority( self ) ); - }; - } -}; - -},{"../../../util":100}],78:[function(_dereq_,module,exports){ -'use strict'; - -module.exports = [ - { name: 'null', impl: _dereq_( './null' ) }, - { name: 'base', impl: _dereq_( './base' ) }, - { name: 'canvas', impl: _dereq_( './canvas' ) } -]; - -},{"./base":60,"./canvas":74,"./null":79}],79:[function(_dereq_,module,exports){ -'use strict'; - -function NullRenderer( options ){ - this.options = options; - this.notifications = 0; // for testing -} - -var noop = function(){}; - -NullRenderer.prototype = { - recalculateRenderedStyle: noop, - notify: function(){ this.notifications++; }, - init: noop -}; - -module.exports = NullRenderer; - -},{}],80:[function(_dereq_,module,exports){ -/*! Weaver licensed under MIT (https://tldrlegal.com/license/mit-license), copyright Max Franz */ - -'use strict'; - -var is = _dereq_('./is'); -var util = _dereq_('./util'); -var Thread = _dereq_('./thread'); -var Promise = _dereq_('./promise'); -var define = _dereq_('./define'); - -var Fabric = function( N ){ - if( !(this instanceof Fabric) ){ - return new Fabric( N ); - } - - this._private = { - pass: [] - }; - - var defN = 4; - - if( is.number(N) ){ - // then use the specified number of threads - } if( typeof navigator !== 'undefined' && navigator.hardwareConcurrency != null ){ - N = navigator.hardwareConcurrency; - } else { - try{ - N = _dereq_('os').cpus().length; - } catch( err ){ - N = defN; - } - } // TODO could use an estimation here but would the additional expense be worth it? - - for( var i = 0; i < N; i++ ){ - this[i] = new Thread(); - } - - this.length = N; -}; - -var fabfn = Fabric.prototype; // short alias - -util.extend(fabfn, { - - instanceString: function(){ return 'fabric'; }, - - // require fn in all threads - require: function( fn, as ){ - for( var i = 0; i < this.length; i++ ){ - var thread = this[i]; - - thread.require( fn, as ); - } - - return this; - }, - - // get a random thread - random: function(){ - var i = Math.round( (this.length - 1) * Math.random() ); - var thread = this[i]; - - return thread; - }, - - // run on random thread - run: function( fn ){ - var pass = this._private.pass.shift(); - - return this.random().pass( pass ).run( fn ); - }, - - // sends a random thread a message - message: function( m ){ - return this.random().message( m ); - }, - - // send all threads a message - broadcast: function( m ){ - for( var i = 0; i < this.length; i++ ){ - var thread = this[i]; - - thread.message( m ); - } - - return this; // chaining - }, - - // stop all threads - stop: function(){ - for( var i = 0; i < this.length; i++ ){ - var thread = this[i]; - - thread.stop(); - } - - return this; // chaining - }, - - // pass data to be used with .spread() etc. - pass: function( data ){ - var pass = this._private.pass; - - if( is.array(data) ){ - pass.push( data ); - } else { - throw 'Only arrays may be used with fabric.pass()'; - } - - return this; // chaining - }, - - spreadSize: function(){ - var subsize = Math.ceil( this._private.pass[0].length / this.length ); - - subsize = Math.max( 1, subsize ); // don't pass less than one ele to each thread - - return subsize; - }, - - // split the data into slices to spread the data equally among threads - spread: function( fn ){ - var self = this; - var _p = self._private; - var subsize = self.spreadSize(); // number of pass eles to handle in each thread - var pass = _p.pass.shift().concat([]); // keep a copy - var runPs = []; - - for( var i = 0; i < this.length; i++ ){ - var thread = this[i]; - var slice = pass.splice( 0, subsize ); - - var runP = thread.pass( slice ).run( fn ); - - runPs.push( runP ); - - var doneEarly = pass.length === 0; - if( doneEarly ){ break; } - } - - return Promise.all( runPs ).then(function( thens ){ - var postpass = []; - var p = 0; - - // fill postpass with the total result joined from all threads - for( var i = 0; i < thens.length; i++ ){ - var then = thens[i]; // array result from thread i - - for( var j = 0; j < then.length; j++ ){ - var t = then[j]; // array element - - postpass[ p++ ] = t; - } - } - - return postpass; - }); - }, - - // parallel version of array.map() - map: function( fn ){ - var self = this; - - self.require( fn, '_$_$_fabmap' ); - - return self.spread(function( split ){ - var mapped = []; - var origResolve = resolve; // jshint ignore:line - - resolve = function( val ){ // jshint ignore:line - mapped.push( val ); - }; - - for( var i = 0; i < split.length; i++ ){ - var oldLen = mapped.length; - var ret = _$_$_fabmap( split[i] ); // jshint ignore:line - var nothingInsdByResolve = oldLen === mapped.length; - - if( nothingInsdByResolve ){ - mapped.push( ret ); - } - } - - resolve = origResolve; // jshint ignore:line - - return mapped; - }); - - }, - - // parallel version of array.filter() - filter: function( fn ){ - var _p = this._private; - var pass = _p.pass[0]; - - return this.map( fn ).then(function( include ){ - var ret = []; - - for( var i = 0; i < pass.length; i++ ){ - var datum = pass[i]; - var incDatum = include[i]; - - if( incDatum ){ - ret.push( datum ); - } - } - - return ret; - }); - }, - - // sorts the passed array using a divide and conquer strategy - sort: function( cmp ){ - var self = this; - var P = this._private.pass[0].length; - var subsize = this.spreadSize(); - - cmp = cmp || function( a, b ){ // default comparison function - if( a < b ){ - return -1; - } else if( a > b ){ - return 1; - } - - return 0; - }; - - self.require( cmp, '_$_$_cmp' ); - - return self.spread(function( split ){ // sort each split normally - var sortedSplit = split.sort( _$_$_cmp ); // jshint ignore:line - resolve( sortedSplit ); // jshint ignore:line - - }).then(function( joined ){ - // do all the merging in the main thread to minimise data transfer - - // TODO could do merging in separate threads but would incur add'l cost of data transfer - // for each level of the merge - - var merge = function( i, j, max ){ - // don't overflow array - j = Math.min( j, P ); - max = Math.min( max, P ); - - // left and right sides of merge - var l = i; - var r = j; - - var sorted = []; - - for( var k = l; k < max; k++ ){ - - var eleI = joined[i]; - var eleJ = joined[j]; - - if( i < r && ( j >= max || cmp(eleI, eleJ) <= 0 ) ){ - sorted.push( eleI ); - i++; - } else { - sorted.push( eleJ ); - j++; - } - - } - - // in the array proper, put the sorted values - for( var k = 0; k < sorted.length; k++ ){ // kth sorted item - var index = l + k; - - joined[ index ] = sorted[k]; - } - }; - - for( var splitL = subsize; splitL < P; splitL *= 2 ){ // merge until array is "split" as 1 - - for( var i = 0; i < P; i += 2*splitL ){ - merge( i, i + splitL, i + 2*splitL ); - } - - } - - return joined; - }); - } - - -}); - -var defineRandomPasser = function( opts ){ - opts = opts || {}; - - return function( fn, arg1 ){ - var pass = this._private.pass.shift(); - - return this.random().pass( pass )[ opts.threadFn ]( fn, arg1 ); - }; -}; - -util.extend(fabfn, { - randomMap: defineRandomPasser({ threadFn: 'map' }), - - reduce: defineRandomPasser({ threadFn: 'reduce' }), - - reduceRight: defineRandomPasser({ threadFn: 'reduceRight' }) -}); - -// aliases -var fn = fabfn; -fn.promise = fn.run; -fn.terminate = fn.halt = fn.stop; -fn.include = fn.require; - -// pull in event apis -util.extend(fabfn, { - on: define.on(), - one: define.on({ unbindSelfOnTrigger: true }), - off: define.off(), - trigger: define.trigger() -}); - -define.eventAliasesOn( fabfn ); - -module.exports = Fabric; - -},{"./define":44,"./is":83,"./promise":86,"./thread":98,"./util":100,"os":undefined}],81:[function(_dereq_,module,exports){ -/*! -Ported by Xueqiao Xu ; - -PSF LICENSE AGREEMENT FOR PYTHON 2.7.2 - -1. This LICENSE AGREEMENT is between the Python Software Foundation (“PSF”), and the Individual or Organization (“Licensee”) accessing and otherwise using Python 2.7.2 software in source or binary form and its associated documentation. -2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python 2.7.2 alone or in any derivative version, provided, however, that PSF’s License Agreement and PSF’s notice of copyright, i.e., “Copyright © 2001-2012 Python Software Foundation; All Rights Reserved” are retained in Python 2.7.2 alone or in any derivative version prepared by Licensee. -3. In the event Licensee prepares a derivative work that is based on or incorporates Python 2.7.2 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python 2.7.2. -4. PSF is making Python 2.7.2 available to Licensee on an “AS IS” basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.7.2 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. -5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 2.7.2 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.7.2, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. -6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. -7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between PSF and Licensee. This License Agreement does not grant permission to use PSF trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. -8. By copying, installing or otherwise using Python 2.7.2, Licensee agrees to be bound by the terms and conditions of this License Agreement. -*/ - -'use strict'; -/* jshint ignore:start */ - -// Generated by CoffeeScript 1.8.0 -(function(){ - var Heap, defaultCmp, floor, heapify, heappop, heappush, heappushpop, heapreplace, insort, min, nlargest, nsmallest, updateItem, _siftdown, _siftup; - - floor = Math.floor, min = Math.min; - - - /* - Default comparison function to be used - */ - - defaultCmp = function( x, y ){ - if( x < y ){ - return -1; - } - if( x > y ){ - return 1; - } - return 0; - }; - - - /* - Insert item x in list a, and keep it sorted assuming a is sorted. - - If x is already in a, insert it to the right of the rightmost x. - - Optional args lo (default 0) and hi (default a.length) bound the slice - of a to be searched. - */ - - insort = function( a, x, lo, hi, cmp ){ - var mid; - if( lo == null ){ - lo = 0; - } - if( cmp == null ){ - cmp = defaultCmp; - } - if( lo < 0 ){ - throw new Error( 'lo must be non-negative' ); - } - if( hi == null ){ - hi = a.length; - } - while( lo < hi ){ - mid = floor( (lo + hi) / 2 ); - if( cmp( x, a[ mid ] ) < 0 ){ - hi = mid; - } else { - lo = mid + 1; - } - } - return ([].splice.apply( a, [ lo, lo - lo ].concat( x ) ), x); - }; - - - /* - Push item onto heap, maintaining the heap invariant. - */ - - heappush = function( array, item, cmp ){ - if( cmp == null ){ - cmp = defaultCmp; - } - array.push( item ); - return _siftdown( array, 0, array.length - 1, cmp ); - }; - - - /* - Pop the smallest item off the heap, maintaining the heap invariant. - */ - - heappop = function( array, cmp ){ - var lastelt, returnitem; - if( cmp == null ){ - cmp = defaultCmp; - } - lastelt = array.pop(); - if( array.length ){ - returnitem = array[0]; - array[0] = lastelt; - _siftup( array, 0, cmp ); - } else { - returnitem = lastelt; - } - return returnitem; - }; - - - /* - Pop and return the current smallest value, and add the new item. - - This is more efficient than heappop() followed by heappush(), and can be - more appropriate when using a fixed size heap. Note that the value - returned may be larger than item! That constrains reasonable use of - this routine unless written as part of a conditional replacement: - if item > array[0] - item = heapreplace(array, item) - */ - - heapreplace = function( array, item, cmp ){ - var returnitem; - if( cmp == null ){ - cmp = defaultCmp; - } - returnitem = array[0]; - array[0] = item; - _siftup( array, 0, cmp ); - return returnitem; - }; - - - /* - Fast version of a heappush followed by a heappop. - */ - - heappushpop = function( array, item, cmp ){ - var _ref; - if( cmp == null ){ - cmp = defaultCmp; - } - if( array.length && cmp( array[0], item ) < 0 ){ - _ref = [ array[0], item ], item = _ref[0], array[0] = _ref[1]; - _siftup( array, 0, cmp ); - } - return item; - }; - - - /* - Transform list into a heap, in-place, in O(array.length) time. - */ - - heapify = function( array, cmp ){ - var i, _i, _j, _len, _ref, _ref1, _results, _results1; - if( cmp == null ){ - cmp = defaultCmp; - } - _ref1 = (function(){ - _results1 = []; - for( var _j = 0, _ref = floor( array.length / 2 ); 0 <= _ref ? _j < _ref : _j > _ref; 0 <= _ref ? _j++ : _j-- ){ _results1.push( _j ); } - return _results1; - }).apply( this ).reverse(); - _results = []; - for( _i = 0, _len = _ref1.length; _i < _len; _i++ ){ - i = _ref1[ _i ]; - _results.push( _siftup( array, i, cmp ) ); - } - return _results; - }; - - - /* - Update the position of the given item in the heap. - This function should be called every time the item is being modified. - */ - - updateItem = function( array, item, cmp ){ - var pos; - if( cmp == null ){ - cmp = defaultCmp; - } - pos = array.indexOf( item ); - if( pos === -1 ){ - return; - } - _siftdown( array, 0, pos, cmp ); - return _siftup( array, pos, cmp ); - }; - - - /* - Find the n largest elements in a dataset. - */ - - nlargest = function( array, n, cmp ){ - var elem, result, _i, _len, _ref; - if( cmp == null ){ - cmp = defaultCmp; - } - result = array.slice( 0, n ); - if( !result.length ){ - return result; - } - heapify( result, cmp ); - _ref = array.slice( n ); - for( _i = 0, _len = _ref.length; _i < _len; _i++ ){ - elem = _ref[ _i ]; - heappushpop( result, elem, cmp ); - } - return result.sort( cmp ).reverse(); - }; - - - /* - Find the n smallest elements in a dataset. - */ - - nsmallest = function( array, n, cmp ){ - var elem, i, los, result, _i, _j, _len, _ref, _ref1, _results; - if( cmp == null ){ - cmp = defaultCmp; - } - if( n * 10 <= array.length ){ - result = array.slice( 0, n ).sort( cmp ); - if( !result.length ){ - return result; - } - los = result[ result.length - 1]; - _ref = array.slice( n ); - for( _i = 0, _len = _ref.length; _i < _len; _i++ ){ - elem = _ref[ _i ]; - if( cmp( elem, los ) < 0 ){ - insort( result, elem, 0, null, cmp ); - result.pop(); - los = result[ result.length - 1]; - } - } - return result; - } - heapify( array, cmp ); - _results = []; - for( i = _j = 0, _ref1 = min( n, array.length ); 0 <= _ref1 ? _j < _ref1 : _j > _ref1; i = 0 <= _ref1 ? ++_j : --_j ){ - _results.push( heappop( array, cmp ) ); - } - return _results; - }; - - _siftdown = function( array, startpos, pos, cmp ){ - var newitem, parent, parentpos; - if( cmp == null ){ - cmp = defaultCmp; - } - newitem = array[ pos ]; - while( pos > startpos ){ - parentpos = (pos - 1) >> 1; - parent = array[ parentpos ]; - if( cmp( newitem, parent ) < 0 ){ - array[ pos ] = parent; - pos = parentpos; - continue; - } - break; - } - return array[ pos ] = newitem; - }; - - _siftup = function( array, pos, cmp ){ - var childpos, endpos, newitem, rightpos, startpos; - if( cmp == null ){ - cmp = defaultCmp; - } - endpos = array.length; - startpos = pos; - newitem = array[ pos ]; - childpos = 2 * pos + 1; - while( childpos < endpos ){ - rightpos = childpos + 1; - if( rightpos < endpos && !(cmp( array[ childpos ], array[ rightpos ] ) < 0) ){ - childpos = rightpos; - } - array[ pos ] = array[ childpos ]; - pos = childpos; - childpos = 2 * pos + 1; - } - array[ pos ] = newitem; - return _siftdown( array, startpos, pos, cmp ); - }; - - Heap = (function(){ - Heap.push = heappush; - - Heap.pop = heappop; - - Heap.replace = heapreplace; - - Heap.pushpop = heappushpop; - - Heap.heapify = heapify; - - Heap.updateItem = updateItem; - - Heap.nlargest = nlargest; - - Heap.nsmallest = nsmallest; - - function Heap( cmp ){ - this.cmp = cmp != null ? cmp : defaultCmp; - this.nodes = []; - } - - Heap.prototype.push = function( x ){ - return heappush( this.nodes, x, this.cmp ); - }; - - Heap.prototype.pop = function(){ - return heappop( this.nodes, this.cmp ); - }; - - Heap.prototype.peek = function(){ - return this.nodes[0]; - }; - - Heap.prototype.contains = function( x ){ - return this.nodes.indexOf( x ) !== -1; - }; - - Heap.prototype.replace = function( x ){ - return heapreplace( this.nodes, x, this.cmp ); - }; - - Heap.prototype.pushpop = function( x ){ - return heappushpop( this.nodes, x, this.cmp ); - }; - - Heap.prototype.heapify = function(){ - return heapify( this.nodes, this.cmp ); - }; - - Heap.prototype.updateItem = function( x ){ - return updateItem( this.nodes, x, this.cmp ); - }; - - Heap.prototype.clear = function(){ - return this.nodes = []; - }; - - Heap.prototype.empty = function(){ - return this.nodes.length === 0; - }; - - Heap.prototype.size = function(){ - return this.nodes.length; - }; - - Heap.prototype.clone = function(){ - var heap; - heap = new Heap(); - heap.nodes = this.nodes.slice( 0 ); - return heap; - }; - - Heap.prototype.toArray = function(){ - return this.nodes.slice( 0 ); - }; - - Heap.prototype.insert = Heap.prototype.push; - - Heap.prototype.top = Heap.prototype.peek; - - Heap.prototype.front = Heap.prototype.peek; - - Heap.prototype.has = Heap.prototype.contains; - - Heap.prototype.copy = Heap.prototype.clone; - - return Heap; - - })(); - - (function( root, factory ){ - if( typeof define === 'function' && define.amd ){ // eslint-disable-line no-undef - return define( [], factory ); // eslint-disable-line no-undef - } else if( typeof exports === 'object' ){ - return module.exports = factory(); - } else { - return root.Heap = factory(); - } - })( this, function(){ - return Heap; - } ); - -}).call( this ); - -/* jshint ignore:end */ - -},{}],82:[function(_dereq_,module,exports){ -'use strict'; - -_dereq_('./-preamble'); - -var window = _dereq_( './window' ); -var is = _dereq_( './is' ); -var Core = _dereq_( './core' ); -var extension = _dereq_( './extension' ); -var registerJquery = _dereq_( './jquery-plugin' ); -var Stylesheet = _dereq_( './stylesheet' ); -var Thread = _dereq_( './thread' ); -var Fabric = _dereq_( './fabric' ); - -var cytoscape = function( options ){ // jshint ignore:line - // if no options specified, use default - if( options === undefined ){ - options = {}; - } - - // create instance - if( is.plainObject( options ) ){ - return new Core( options ); - } - - // allow for registration of extensions - else if( is.string( options ) ){ - return extension.apply( extension, arguments ); - } -}; - -// replaced by build system -cytoscape.version = _dereq_('./version.json'); - -// try to register w/ jquery -if( window && window.jQuery ){ - registerJquery( window.jQuery, cytoscape ); -} - -// expose register api -cytoscape.registerJquery = function( jQuery ){ - registerJquery( jQuery, cytoscape ); -}; - -// expose public apis (mostly for extensions) -cytoscape.stylesheet = cytoscape.Stylesheet = Stylesheet; -cytoscape.thread = cytoscape.Thread = Thread; -cytoscape.fabric = cytoscape.Fabric = Fabric; - -module.exports = cytoscape; - -},{"./-preamble":1,"./core":37,"./extension":46,"./fabric":80,"./is":83,"./jquery-plugin":84,"./stylesheet":97,"./thread":98,"./version.json":106,"./window":107}],83:[function(_dereq_,module,exports){ -'use strict'; - -/*global HTMLElement DocumentTouch */ - -var window = _dereq_( './window' ); -var navigator = window ? window.navigator : null; -var document = window ? window.document : null; - -var typeofstr = typeof ''; -var typeofobj = typeof {}; -var typeoffn = typeof function(){}; -var typeofhtmlele = typeof HTMLElement; - -var instanceStr = function( obj ){ - return obj && obj.instanceString && is.fn( obj.instanceString ) ? obj.instanceString() : null; -}; - -var is = { - defined: function( obj ){ - return obj != null; // not undefined or null - }, - - string: function( obj ){ - return obj != null && typeof obj == typeofstr; - }, - - fn: function( obj ){ - return obj != null && typeof obj === typeoffn; - }, - - array: function( obj ){ - return Array.isArray ? Array.isArray( obj ) : obj != null && obj instanceof Array; - }, - - plainObject: function( obj ){ - return obj != null && typeof obj === typeofobj && !is.array( obj ) && obj.constructor === Object; - }, - - object: function( obj ){ - return obj != null && typeof obj === typeofobj; - }, - - number: function( obj ){ - return obj != null && typeof obj === typeof 1 && !isNaN( obj ); - }, - - integer: function( obj ){ - return is.number( obj ) && Math.floor( obj ) === obj; - }, - - bool: function( obj ){ - return obj != null && typeof obj === typeof true; - }, - - htmlElement: function( obj ){ - if( 'undefined' === typeofhtmlele ){ - return undefined; - } else { - return null != obj && obj instanceof HTMLElement; - } - }, - - elementOrCollection: function( obj ){ - return is.element( obj ) || is.collection( obj ); - }, - - element: function( obj ){ - return instanceStr( obj ) === 'collection' && obj._private.single; - }, - - collection: function( obj ){ - return instanceStr( obj ) === 'collection' && !obj._private.single; - }, - - core: function( obj ){ - return instanceStr( obj ) === 'core'; - }, - - style: function( obj ){ - return instanceStr( obj ) === 'style'; - }, - - stylesheet: function( obj ){ - return instanceStr( obj ) === 'stylesheet'; - }, - - event: function( obj ){ - return instanceStr( obj ) === 'event'; - }, - - thread: function( obj ){ - return instanceStr( obj ) === 'thread'; - }, - - fabric: function( obj ){ - return instanceStr( obj ) === 'fabric'; - }, - - emptyString: function( obj ){ - if( obj === undefined || obj === null ){ // null is empty - return true; - } else if( obj === '' || obj.match( /^\s+$/ ) ){ - return true; // empty string is empty - } - - return false; // otherwise, we don't know what we've got - }, - - nonemptyString: function( obj ){ - if( obj && is.string( obj ) && obj !== '' && !obj.match( /^\s+$/ ) ){ - return true; - } - - return false; - }, - - domElement: function( obj ){ - if( typeof HTMLElement === 'undefined' ){ - return false; // we're not in a browser so it doesn't matter - } else { - return obj instanceof HTMLElement; - } - }, - - boundingBox: function( obj ){ - return is.plainObject( obj ) && - is.number( obj.x1 ) && is.number( obj.x2 ) && - is.number( obj.y1 ) && is.number( obj.y2 ) - ; - }, - - promise: function( obj ){ - return is.object( obj ) && is.fn( obj.then ); - }, - - touch: function(){ - return window && ( ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch ); - }, - - gecko: function(){ - return window && ( typeof InstallTrigger !== 'undefined' || ('MozAppearance' in document.documentElement.style) ); - }, - - webkit: function(){ - return window && ( typeof webkitURL !== 'undefined' || ('WebkitAppearance' in document.documentElement.style) ); - }, - - chromium: function(){ - return window && ( typeof chrome !== 'undefined' ); - }, - - khtml: function(){ - return navigator && navigator.vendor.match( /kde/i ); // probably a better way to detect this... - }, - - khtmlEtc: function(){ - return is.khtml() || is.webkit() || is.chromium(); - }, - - ms: function(){ - return navigator && navigator.userAgent.match( /msie|trident|edge/i ); // probably a better way to detect this... - }, - - windows: function(){ - return navigator && navigator.appVersion.match( /Win/i ); - }, - - mac: function(){ - return navigator && navigator.appVersion.match( /Mac/i ); - }, - - linux: function(){ - return navigator && navigator.appVersion.match( /Linux/i ); - }, - - unix: function(){ - return navigator && navigator.appVersion.match( /X11/i ); - } -}; - -module.exports = is; - -},{"./window":107}],84:[function(_dereq_,module,exports){ -'use strict'; - -var is = _dereq_( './is' ); - -var cyReg = function( $ele ){ - var d = $ele[0]._cyreg = $ele[0]._cyreg || {}; - - return d; -}; - -var registerJquery = function( $, cytoscape ){ - if( !$ ){ return; } // no jquery => don't need this - - if( $.fn.cytoscape ){ return; } // already registered - - // allow calls on a jQuery selector by proxying calls to $.cytoscape - // e.g. $("#foo").cytoscape(options) => $.cytoscape(options) on #foo - $.fn.cytoscape = function( opts ){ - var $this = $( this ); - - // get object - if( opts === 'get' ){ - return cyReg( $this ).cy; - } - - // bind to ready - else if( is.fn( opts ) ){ - - var ready = opts; - var cy = cyReg( $this ).cy; - - if( cy && cy.isReady() ){ // already ready so just trigger now - cy.trigger( 'ready', [], ready ); - - } else { // not yet ready, so add to readies list - var data = cyReg( $this ); - var readies = data.readies = data.readies || []; - - readies.push( ready ); - } - - } - - // proxy to create instance - else if( is.plainObject( opts ) ){ - return $this.each( function(){ - var options = $.extend( {}, opts, { - container: $( this )[0] - } ); - - cytoscape( options ); - } ); - } - }; - - // allow access to the global cytoscape object under jquery for legacy reasons - $.cytoscape = cytoscape; - - // use short alias (cy) if not already defined - if( $.fn.cy == null && $.cy == null ){ - $.fn.cy = $.fn.cytoscape; - $.cy = $.cytoscape; - } -}; - -module.exports = registerJquery; - -},{"./is":83}],85:[function(_dereq_,module,exports){ -'use strict'; - -var math = {}; - -math.arePositionsSame = function( p1, p2 ){ - return p1.x === p2.x && p1.y === p2.y; -}; - -math.copyPosition = function( p ){ - return { x: p.x, y: p.y }; -}; - -math.array2point = function( arr ){ - return { - x: arr[0], - y: arr[1] - }; -}; - -math.deg2rad = function( deg ){ - return Math.PI * deg / 180; -}; - -math.log2 = Math.log2 || function( n ){ - return Math.log( n ) / Math.log( 2 ); -}; - -math.signum = function( x ){ - if( x > 0 ){ - return 1; - } else if( x < 0 ){ - return -1; - } else { - return 0; - } -}; - -math.dist = function( p1, p2 ){ - return Math.sqrt( math.sqdist( p1, p2 ) ); -}; - -math.sqdist = function( p1, p2 ){ - var dx = p2.x - p1.x; - var dy = p2.y - p1.y; - - return dx * dx + dy * dy; -}; - -// from http://en.wikipedia.org/wiki/Bézier_curve#Quadratic_curves -math.qbezierAt = function( p0, p1, p2, t ){ - return (1 - t) * (1 - t) * p0 + 2 * (1 - t) * t * p1 + t * t * p2; -}; - -math.qbezierPtAt = function( p0, p1, p2, t ){ - return { - x: math.qbezierAt( p0.x, p1.x, p2.x, t ), - y: math.qbezierAt( p0.y, p1.y, p2.y, t ) - }; -}; - -math.lineAt = function( p0, p1, t, d ){ - var vec = { - x: p1.x - p0.x, - y: p1.y - p0.y - }; - - var vecDist = math.dist( p0, p1 ); - - var normVec = { - x: vec.x / vecDist, - y: vec.y / vecDist - }; - - t = t == null ? 0 : t; - - var d = d != null ? d : t * vecDist; - - return { - x: p0.x + normVec.x * d, - y: p0.y + normVec.y * d - }; -}; - -math.lineAtDist = function( p0, p1, d ){ - return math.lineAt( p0, p1, undefined, d ); -}; - -// get angle at A via cosine law -math.triangleAngle = function( A, B, C ){ - var a = math.dist( B, C ); - var b = math.dist( A, C ); - var c = math.dist( A, B ); - - return Math.acos( (a*a + b*b - c*c)/(2*a*b) ); -}; - -math.bound = function( min, val, max ){ - return Math.max( min, Math.min( max, val ) ); -}; - -// makes a full bb (x1, y1, x2, y2, w, h) from implicit params -math.makeBoundingBox = function( bb ){ - if( bb == null ){ - return { - x1: Infinity, - y1: Infinity, - x2: -Infinity, - y2: -Infinity, - w: 0, - h: 0 - }; - } else if( bb.x1 != null && bb.y1 != null ){ - if( bb.x2 != null && bb.y2 != null && bb.x2 >= bb.x1 && bb.y2 >= bb.y1 ){ - return { - x1: bb.x1, - y1: bb.y1, - x2: bb.x2, - y2: bb.y2, - w: bb.x2 - bb.x1, - h: bb.y2 - bb.y1 - }; - } else if( bb.w != null && bb.h != null && bb.w >= 0 && bb.h >= 0 ){ - return { - x1: bb.x1, - y1: bb.y1, - x2: bb.x1 + bb.w, - y2: bb.y1 + bb.h, - w: bb.w, - h: bb.h - }; - } - } -}; - -math.updateBoundingBox = function( bb1, bb2 ){ - // update bb1 with bb2 bounds - - bb1.x1 = Math.min( bb1.x1, bb2.x1 ); - bb1.x2 = Math.max( bb1.x2, bb2.x2 ); - bb1.w = bb1.x2 - bb1.x1; - - bb1.y1 = Math.min( bb1.y1, bb2.y1 ); - bb1.y2 = Math.max( bb1.y2, bb2.y2 ); - bb1.h = bb1.y2 - bb1.y1; -}; - -math.expandBoundingBox = function( bb, padding ){ - bb.x1 -= padding; - bb.x2 += padding; - bb.y1 -= padding; - bb.y2 += padding; - bb.w = bb.x2 - bb.x1; - bb.h = bb.y2 - bb.y1; - - return bb; -}; - -math.boundingBoxesIntersect = function( bb1, bb2 ){ - // case: one bb to right of other - if( bb1.x1 > bb2.x2 ){ return false; } - if( bb2.x1 > bb1.x2 ){ return false; } - - // case: one bb to left of other - if( bb1.x2 < bb2.x1 ){ return false; } - if( bb2.x2 < bb1.x1 ){ return false; } - - // case: one bb above other - if( bb1.y2 < bb2.y1 ){ return false; } - if( bb2.y2 < bb1.y1 ){ return false; } - - // case: one bb below other - if( bb1.y1 > bb2.y2 ){ return false; } - if( bb2.y1 > bb1.y2 ){ return false; } - - // otherwise, must have some overlap - return true; -}; - -math.inBoundingBox = function( bb, x, y ){ - return bb.x1 <= x && x <= bb.x2 && bb.y1 <= y && y <= bb.y2; -}; - -math.pointInBoundingBox = function( bb, pt ){ - return this.inBoundingBox( bb, pt.x, pt.y ); -}; - -math.boundingBoxInBoundingBox = function( bb1, bb2 ){ - return ( - math.inBoundingBox( bb1, bb2.x1, bb2.y1 ) - && math.inBoundingBox( bb1, bb2.x2, bb2.y2 ) - ); -}; - -math.roundRectangleIntersectLine = function( - x, y, nodeX, nodeY, width, height, padding ){ - - var cornerRadius = this.getRoundRectangleRadius( width, height ); - - var halfWidth = width / 2; - var halfHeight = height / 2; - - // Check intersections with straight line segments - var straightLineIntersections; - - // Top segment, left to right - { - var topStartX = nodeX - halfWidth + cornerRadius - padding; - var topStartY = nodeY - halfHeight - padding; - var topEndX = nodeX + halfWidth - cornerRadius + padding; - var topEndY = topStartY; - - straightLineIntersections = this.finiteLinesIntersect( - x, y, nodeX, nodeY, topStartX, topStartY, topEndX, topEndY, false ); - - if( straightLineIntersections.length > 0 ){ - return straightLineIntersections; - } - } - - // Right segment, top to bottom - { - var rightStartX = nodeX + halfWidth + padding; - var rightStartY = nodeY - halfHeight + cornerRadius - padding; - var rightEndX = rightStartX; - var rightEndY = nodeY + halfHeight - cornerRadius + padding; - - straightLineIntersections = this.finiteLinesIntersect( - x, y, nodeX, nodeY, rightStartX, rightStartY, rightEndX, rightEndY, false ); - - if( straightLineIntersections.length > 0 ){ - return straightLineIntersections; - } - } - - // Bottom segment, left to right - { - var bottomStartX = nodeX - halfWidth + cornerRadius - padding; - var bottomStartY = nodeY + halfHeight + padding; - var bottomEndX = nodeX + halfWidth - cornerRadius + padding; - var bottomEndY = bottomStartY; - - straightLineIntersections = this.finiteLinesIntersect( - x, y, nodeX, nodeY, bottomStartX, bottomStartY, bottomEndX, bottomEndY, false ); - - if( straightLineIntersections.length > 0 ){ - return straightLineIntersections; - } - } - - // Left segment, top to bottom - { - var leftStartX = nodeX - halfWidth - padding; - var leftStartY = nodeY - halfHeight + cornerRadius - padding; - var leftEndX = leftStartX; - var leftEndY = nodeY + halfHeight - cornerRadius + padding; - - straightLineIntersections = this.finiteLinesIntersect( - x, y, nodeX, nodeY, leftStartX, leftStartY, leftEndX, leftEndY, false ); - - if( straightLineIntersections.length > 0 ){ - return straightLineIntersections; - } - } - - // Check intersections with arc segments - var arcIntersections; - - // Top Left - { - var topLeftCenterX = nodeX - halfWidth + cornerRadius; - var topLeftCenterY = nodeY - halfHeight + cornerRadius; - arcIntersections = this.intersectLineCircle( - x, y, nodeX, nodeY, - topLeftCenterX, topLeftCenterY, cornerRadius + padding ); - - // Ensure the intersection is on the desired quarter of the circle - if( arcIntersections.length > 0 - && arcIntersections[0] <= topLeftCenterX - && arcIntersections[1] <= topLeftCenterY ){ - return [ arcIntersections[0], arcIntersections[1] ]; - } - } - - // Top Right - { - var topRightCenterX = nodeX + halfWidth - cornerRadius; - var topRightCenterY = nodeY - halfHeight + cornerRadius; - arcIntersections = this.intersectLineCircle( - x, y, nodeX, nodeY, - topRightCenterX, topRightCenterY, cornerRadius + padding ); - - // Ensure the intersection is on the desired quarter of the circle - if( arcIntersections.length > 0 - && arcIntersections[0] >= topRightCenterX - && arcIntersections[1] <= topRightCenterY ){ - return [ arcIntersections[0], arcIntersections[1] ]; - } - } - - // Bottom Right - { - var bottomRightCenterX = nodeX + halfWidth - cornerRadius; - var bottomRightCenterY = nodeY + halfHeight - cornerRadius; - arcIntersections = this.intersectLineCircle( - x, y, nodeX, nodeY, - bottomRightCenterX, bottomRightCenterY, cornerRadius + padding ); - - // Ensure the intersection is on the desired quarter of the circle - if( arcIntersections.length > 0 - && arcIntersections[0] >= bottomRightCenterX - && arcIntersections[1] >= bottomRightCenterY ){ - return [ arcIntersections[0], arcIntersections[1] ]; - } - } - - // Bottom Left - { - var bottomLeftCenterX = nodeX - halfWidth + cornerRadius; - var bottomLeftCenterY = nodeY + halfHeight - cornerRadius; - arcIntersections = this.intersectLineCircle( - x, y, nodeX, nodeY, - bottomLeftCenterX, bottomLeftCenterY, cornerRadius + padding ); - - // Ensure the intersection is on the desired quarter of the circle - if( arcIntersections.length > 0 - && arcIntersections[0] <= bottomLeftCenterX - && arcIntersections[1] >= bottomLeftCenterY ){ - return [ arcIntersections[0], arcIntersections[1] ]; - } - } - - return []; // if nothing -}; - -math.inLineVicinity = function( x, y, lx1, ly1, lx2, ly2, tolerance ){ - var t = tolerance; - - var x1 = Math.min( lx1, lx2 ); - var x2 = Math.max( lx1, lx2 ); - var y1 = Math.min( ly1, ly2 ); - var y2 = Math.max( ly1, ly2 ); - - return x1 - t <= x && x <= x2 + t - && y1 - t <= y && y <= y2 + t; -}; - -math.inBezierVicinity = function( - x, y, x1, y1, x2, y2, x3, y3, tolerance ){ - - var bb = { - x1: Math.min( x1, x3, x2 ) - tolerance, - x2: Math.max( x1, x3, x2 ) + tolerance, - y1: Math.min( y1, y3, y2 ) - tolerance, - y2: Math.max( y1, y3, y2 ) + tolerance - }; - - // if outside the rough bounding box for the bezier, then it can't be a hit - if( x < bb.x1 || x > bb.x2 || y < bb.y1 || y > bb.y2 ){ - // console.log('bezier out of rough bb') - return false; - } else { - // console.log('do more expensive check'); - return true; - } - -}; - -math.solveCubic = function( a, b, c, d, result ){ - - // Solves a cubic function, returns root in form [r1, i1, r2, i2, r3, i3], where - // r is the real component, i is the imaginary component - - // An implementation of the Cardano method from the year 1545 - // http://en.wikipedia.org/wiki/Cubic_function#The_nature_of_the_roots - - b /= a; - c /= a; - d /= a; - - var discriminant, q, r, dum1, s, t, term1, r13; - - q = (3.0 * c - (b * b)) / 9.0; - r = -(27.0 * d) + b * (9.0 * c - 2.0 * (b * b)); - r /= 54.0; - - discriminant = q * q * q + r * r; - result[1] = 0; - term1 = (b / 3.0); - - if( discriminant > 0 ){ - s = r + Math.sqrt( discriminant ); - s = ((s < 0) ? -Math.pow( -s, (1.0 / 3.0) ) : Math.pow( s, (1.0 / 3.0) )); - t = r - Math.sqrt( discriminant ); - t = ((t < 0) ? -Math.pow( -t, (1.0 / 3.0) ) : Math.pow( t, (1.0 / 3.0) )); - result[0] = -term1 + s + t; - term1 += (s + t) / 2.0; - result[4] = result[2] = -term1; - term1 = Math.sqrt( 3.0 ) * (-t + s) / 2; - result[3] = term1; - result[5] = -term1; - return; - } - - result[5] = result[3] = 0; - - if( discriminant === 0 ){ - r13 = ((r < 0) ? -Math.pow( -r, (1.0 / 3.0) ) : Math.pow( r, (1.0 / 3.0) )); - result[0] = -term1 + 2.0 * r13; - result[4] = result[2] = -(r13 + term1); - return; - } - - q = -q; - dum1 = q * q * q; - dum1 = Math.acos( r / Math.sqrt( dum1 ) ); - r13 = 2.0 * Math.sqrt( q ); - result[0] = -term1 + r13 * Math.cos( dum1 / 3.0 ); - result[2] = -term1 + r13 * Math.cos( (dum1 + 2.0 * Math.PI) / 3.0 ); - result[4] = -term1 + r13 * Math.cos( (dum1 + 4.0 * Math.PI) / 3.0 ); - - return; -}; - -math.sqdistToQuadraticBezier = function( - x, y, x1, y1, x2, y2, x3, y3 ){ - - // Find minimum distance by using the minimum of the distance - // function between the given point and the curve - - // This gives the coefficients of the resulting cubic equation - // whose roots tell us where a possible minimum is - // (Coefficients are divided by 4) - - var a = 1.0 * x1 * x1 - 4 * x1 * x2 + 2 * x1 * x3 + 4 * x2 * x2 - 4 * x2 * x3 + x3 * x3 - + y1 * y1 - 4 * y1 * y2 + 2 * y1 * y3 + 4 * y2 * y2 - 4 * y2 * y3 + y3 * y3; - - var b = 1.0 * 9 * x1 * x2 - 3 * x1 * x1 - 3 * x1 * x3 - 6 * x2 * x2 + 3 * x2 * x3 - + 9 * y1 * y2 - 3 * y1 * y1 - 3 * y1 * y3 - 6 * y2 * y2 + 3 * y2 * y3; - - var c = 1.0 * 3 * x1 * x1 - 6 * x1 * x2 + x1 * x3 - x1 * x + 2 * x2 * x2 + 2 * x2 * x - x3 * x - + 3 * y1 * y1 - 6 * y1 * y2 + y1 * y3 - y1 * y + 2 * y2 * y2 + 2 * y2 * y - y3 * y; - - var d = 1.0 * x1 * x2 - x1 * x1 + x1 * x - x2 * x - + y1 * y2 - y1 * y1 + y1 * y - y2 * y; - - // debug("coefficients: " + a / a + ", " + b / a + ", " + c / a + ", " + d / a); - - var roots = []; - - // Use the cubic solving algorithm - this.solveCubic( a, b, c, d, roots ); - - var zeroThreshold = 0.0000001; - - var params = []; - - for( var index = 0; index < 6; index += 2 ){ - if( Math.abs( roots[ index + 1] ) < zeroThreshold - && roots[ index ] >= 0 - && roots[ index ] <= 1.0 ){ - params.push( roots[ index ] ); - } - } - - params.push( 1.0 ); - params.push( 0.0 ); - - var minDistanceSquared = -1; - var closestParam; - - var curX, curY, distSquared; - for( var i = 0; i < params.length; i++ ){ - curX = Math.pow( 1.0 - params[ i ], 2.0 ) * x1 - + 2.0 * (1 - params[ i ]) * params[ i ] * x2 - + params[ i ] * params[ i ] * x3; - - curY = Math.pow( 1 - params[ i ], 2.0 ) * y1 - + 2 * (1.0 - params[ i ]) * params[ i ] * y2 - + params[ i ] * params[ i ] * y3; - - distSquared = Math.pow( curX - x, 2 ) + Math.pow( curY - y, 2 ); - // debug('distance for param ' + params[i] + ": " + Math.sqrt(distSquared)); - if( minDistanceSquared >= 0 ){ - if( distSquared < minDistanceSquared ){ - minDistanceSquared = distSquared; - closestParam = params[ i ]; - } - } else { - minDistanceSquared = distSquared; - closestParam = params[ i ]; - } - } - - return minDistanceSquared; -}; - -math.sqdistToFiniteLine = function( x, y, x1, y1, x2, y2 ){ - var offset = [ x - x1, y - y1 ]; - var line = [ x2 - x1, y2 - y1 ]; - - var lineSq = line[0] * line[0] + line[1] * line[1]; - var hypSq = offset[0] * offset[0] + offset[1] * offset[1]; - - var dotProduct = offset[0] * line[0] + offset[1] * line[1]; - var adjSq = dotProduct * dotProduct / lineSq; - - if( dotProduct < 0 ){ - return hypSq; - } - - if( adjSq > lineSq ){ - return (x - x2) * (x - x2) + (y - y2) * (y - y2); - } - - return hypSq - adjSq; -}; - -math.pointInsidePolygonPoints = function( x, y, points ){ - var x1, y1, x2, y2; - var y3; - - // Intersect with vertical line through (x, y) - var up = 0; - var down = 0; - for( var i = 0; i < points.length / 2; i++ ){ - - x1 = points[ i * 2]; - y1 = points[ i * 2 + 1]; - - if( i + 1 < points.length / 2 ){ - x2 = points[ (i + 1) * 2]; - y2 = points[ (i + 1) * 2 + 1]; - } else { - x2 = points[ (i + 1 - points.length / 2) * 2]; - y2 = points[ (i + 1 - points.length / 2) * 2 + 1]; - } - - if( x1 == x && x2 == x ){ - // then ignore - } else if( (x1 >= x && x >= x2) - || (x1 <= x && x <= x2) ){ - - y3 = (x - x1) / (x2 - x1) * (y2 - y1) + y1; - - if( y3 > y ){ - up++; - } - - if( y3 < y ){ - down++; - } - - } else { - continue; - } - - } - - if( up % 2 === 0 ){ - return false; - } else { - return true; - } -}; - -math.pointInsidePolygon = function( - x, y, basePoints, centerX, centerY, width, height, direction, padding ){ - - //var direction = arguments[6]; - var transformedPoints = new Array( basePoints.length ); - - // Gives negative angle - var angle; - - if( direction[0] != null ){ - angle = Math.atan( direction[1] / direction[0] ); - - if( direction[0] < 0 ){ - angle = angle + Math.PI / 2; - } else { - angle = -angle - Math.PI / 2; - } - } else { - angle = direction; - } - - var cos = Math.cos( -angle ); - var sin = Math.sin( -angle ); - - // console.log("base: " + basePoints); - for( var i = 0; i < transformedPoints.length / 2; i++ ){ - transformedPoints[ i * 2] = - width / 2 * (basePoints[ i * 2] * cos - - basePoints[ i * 2 + 1] * sin); - - transformedPoints[ i * 2 + 1] = - height / 2 * (basePoints[ i * 2 + 1] * cos - + basePoints[ i * 2] * sin); - - transformedPoints[ i * 2] += centerX; - transformedPoints[ i * 2 + 1] += centerY; - } - - var points; - - if( padding > 0 ){ - var expandedLineSet = this.expandPolygon( - transformedPoints, - -padding ); - - points = this.joinLines( expandedLineSet ); - } else { - points = transformedPoints; - } - - return math.pointInsidePolygonPoints( x, y, points ); -}; - -math.joinLines = function( lineSet ){ - - var vertices = new Array( lineSet.length / 2 ); - - var currentLineStartX, currentLineStartY, currentLineEndX, currentLineEndY; - var nextLineStartX, nextLineStartY, nextLineEndX, nextLineEndY; - - for( var i = 0; i < lineSet.length / 4; i++ ){ - currentLineStartX = lineSet[ i * 4]; - currentLineStartY = lineSet[ i * 4 + 1]; - currentLineEndX = lineSet[ i * 4 + 2]; - currentLineEndY = lineSet[ i * 4 + 3]; - - if( i < lineSet.length / 4 - 1 ){ - nextLineStartX = lineSet[ (i + 1) * 4]; - nextLineStartY = lineSet[ (i + 1) * 4 + 1]; - nextLineEndX = lineSet[ (i + 1) * 4 + 2]; - nextLineEndY = lineSet[ (i + 1) * 4 + 3]; - } else { - nextLineStartX = lineSet[0]; - nextLineStartY = lineSet[1]; - nextLineEndX = lineSet[2]; - nextLineEndY = lineSet[3]; - } - - var intersection = this.finiteLinesIntersect( - currentLineStartX, currentLineStartY, - currentLineEndX, currentLineEndY, - nextLineStartX, nextLineStartY, - nextLineEndX, nextLineEndY, - true ); - - vertices[ i * 2] = intersection[0]; - vertices[ i * 2 + 1] = intersection[1]; - } - - return vertices; -}; - -math.expandPolygon = function( points, pad ){ - - var expandedLineSet = new Array( points.length * 2 ); - - var currentPointX, currentPointY, nextPointX, nextPointY; - - for( var i = 0; i < points.length / 2; i++ ){ - currentPointX = points[ i * 2]; - currentPointY = points[ i * 2 + 1]; - - if( i < points.length / 2 - 1 ){ - nextPointX = points[ (i + 1) * 2]; - nextPointY = points[ (i + 1) * 2 + 1]; - } else { - nextPointX = points[0]; - nextPointY = points[1]; - } - - // Current line: [currentPointX, currentPointY] to [nextPointX, nextPointY] - - // Assume CCW polygon winding - - var offsetX = (nextPointY - currentPointY); - var offsetY = -(nextPointX - currentPointX); - - // Normalize - var offsetLength = Math.sqrt( offsetX * offsetX + offsetY * offsetY ); - var normalizedOffsetX = offsetX / offsetLength; - var normalizedOffsetY = offsetY / offsetLength; - - expandedLineSet[ i * 4] = currentPointX + normalizedOffsetX * pad; - expandedLineSet[ i * 4 + 1] = currentPointY + normalizedOffsetY * pad; - expandedLineSet[ i * 4 + 2] = nextPointX + normalizedOffsetX * pad; - expandedLineSet[ i * 4 + 3] = nextPointY + normalizedOffsetY * pad; - } - - return expandedLineSet; -}; - -math.intersectLineEllipse = function( - x, y, centerX, centerY, ellipseWradius, ellipseHradius ){ - - var dispX = centerX - x; - var dispY = centerY - y; - - dispX /= ellipseWradius; - dispY /= ellipseHradius; - - var len = Math.sqrt( dispX * dispX + dispY * dispY ); - - var newLength = len - 1; - - if( newLength < 0 ){ - return []; - } - - var lenProportion = newLength / len; - - return [ (centerX - x) * lenProportion + x, (centerY - y) * lenProportion + y ]; -}; - -// Returns intersections of increasing distance from line's start point -math.intersectLineCircle = function( - x1, y1, x2, y2, centerX, centerY, radius ){ - - // Calculate d, direction vector of line - var d = [ x2 - x1, y2 - y1 ]; // Direction vector of line - var c = [ centerX, centerY ]; // Center of circle - var f = [ x1 - centerX, y1 - centerY ]; - - var a = d[0] * d[0] + d[1] * d[1]; - var b = 2 * (f[0] * d[0] + f[1] * d[1]); - var c = (f[0] * f[0] + f[1] * f[1]) - radius * radius ; - - var discriminant = b * b - 4 * a * c; - - if( discriminant < 0 ){ - return []; - } - - var t1 = (-b + Math.sqrt( discriminant )) / (2 * a); - var t2 = (-b - Math.sqrt( discriminant )) / (2 * a); - - var tMin = Math.min( t1, t2 ); - var tMax = Math.max( t1, t2 ); - var inRangeParams = []; - - if( tMin >= 0 && tMin <= 1 ){ - inRangeParams.push( tMin ); - } - - if( tMax >= 0 && tMax <= 1 ){ - inRangeParams.push( tMax ); - } - - if( inRangeParams.length === 0 ){ - return []; - } - - var nearIntersectionX = inRangeParams[0] * d[0] + x1; - var nearIntersectionY = inRangeParams[0] * d[1] + y1; - - if( inRangeParams.length > 1 ){ - - if( inRangeParams[0] == inRangeParams[1] ){ - return [ nearIntersectionX, nearIntersectionY ]; - } else { - - var farIntersectionX = inRangeParams[1] * d[0] + x1; - var farIntersectionY = inRangeParams[1] * d[1] + y1; - - return [ nearIntersectionX, nearIntersectionY, farIntersectionX, farIntersectionY ]; - } - - } else { - return [ nearIntersectionX, nearIntersectionY ]; - } - -}; - -math.findCircleNearPoint = function( centerX, centerY, - radius, farX, farY ){ - - var displacementX = farX - centerX; - var displacementY = farY - centerY; - var distance = Math.sqrt( displacementX * displacementX - + displacementY * displacementY ); - - var unitDisplacementX = displacementX / distance; - var unitDisplacementY = displacementY / distance; - - return [ centerX + unitDisplacementX * radius, - centerY + unitDisplacementY * radius ]; -}; - -math.findMaxSqDistanceToOrigin = function( points ){ - var maxSqDistance = 0.000001; - var sqDistance; - - for( var i = 0; i < points.length / 2; i++ ){ - - sqDistance = points[ i * 2] * points[ i * 2] - + points[ i * 2 + 1] * points[ i * 2 + 1]; - - if( sqDistance > maxSqDistance ){ - maxSqDistance = sqDistance; - } - } - - return maxSqDistance; -}; - -math.midOfThree = function( a, b, c ){ - if( (b <= a && a <= c) || (c <= a && a <= b) ){ - return a; - } else if( (a <= b && b <= c) || (c <= b && b <= a) ){ - return b; - } else { - return c; - } -}; - -math.finiteLinesIntersect = function( x1, y1, x2, y2, x3, y3, x4, y4, infiniteLines ){ - - var dx13 = x1 - x3; - var dx21 = x2 - x1; - var dx43 = x4 - x3; - - var dy13 = y1 - y3; - var dy21 = y2 - y1; - var dy43 = y4 - y3; - - var ua_t = dx43 * dy13 - dy43 * dx13; - var ub_t = dx21 * dy13 - dy21 * dx13; - var u_b = dy43 * dx21 - dx43 * dy21; - - if( u_b !== 0 ){ - var ua = ua_t / u_b; - var ub = ub_t / u_b; - - var flptThreshold = 0.001; - var min = 0 - flptThreshold; - var max = 1 + flptThreshold; - - if( min <= ua && ua <= max && min <= ub && ub <= max ){ - return [ x1 + ua * dx21, y1 + ua * dy21 ]; - - } else { - if( !infiniteLines ){ - return []; - } else { - return [ x1 + ua * dx21, y1 + ua * dy21 ]; - } - } - } else { - if( ua_t === 0 || ub_t === 0 ){ - - // Parallel, coincident lines. Check if overlap - - // Check endpoint of second line - if( this.midOfThree( x1, x2, x4 ) === x4 ){ - return [ x4, y4 ]; - } - - // Check start point of second line - if( this.midOfThree( x1, x2, x3 ) === x3 ){ - return [ x3, y3 ]; - } - - // Endpoint of first line - if( this.midOfThree( x3, x4, x2 ) === x2 ){ - return [ x2, y2 ]; - } - - return []; - } else { - - // Parallel, non-coincident - return []; - } - } -}; - -math.polygonIntersectLine = function( - x, y, basePoints, centerX, centerY, width, height, padding ){ - - var intersections = []; - var intersection; - - var transformedPoints = new Array( basePoints.length ); - - for( var i = 0; i < transformedPoints.length / 2; i++ ){ - transformedPoints[ i * 2] = basePoints[ i * 2] * width + centerX; - transformedPoints[ i * 2 + 1] = basePoints[ i * 2 + 1] * height + centerY; - } - - var points; - - if( padding > 0 ){ - var expandedLineSet = math.expandPolygon( - transformedPoints, - -padding ); - - points = math.joinLines( expandedLineSet ); - } else { - points = transformedPoints; - } - // var points = transformedPoints; - - var currentX, currentY, nextX, nextY; - - for( var i = 0; i < points.length / 2; i++ ){ - - currentX = points[ i * 2]; - currentY = points[ i * 2 + 1]; - - if( i < points.length / 2 - 1 ){ - nextX = points[ (i + 1) * 2]; - nextY = points[ (i + 1) * 2 + 1]; - } else { - nextX = points[0]; - nextY = points[1]; - } - - intersection = this.finiteLinesIntersect( - x, y, centerX, centerY, - currentX, currentY, - nextX, nextY ); - - if( intersection.length !== 0 ){ - intersections.push( intersection[0], intersection[1] ); - } - } - - return intersections; -}; - -math.shortenIntersection = function( - intersection, offset, amount ){ - - var disp = [ intersection[0] - offset[0], intersection[1] - offset[1] ]; - - var length = Math.sqrt( disp[0] * disp[0] + disp[1] * disp[1] ); - - var lenRatio = (length - amount) / length; - - if( lenRatio < 0 ){ - lenRatio = 0.00001; - } - - return [ offset[0] + lenRatio * disp[0], offset[1] + lenRatio * disp[1] ]; -}; - -math.generateUnitNgonPointsFitToSquare = function( sides, rotationRadians ){ - var points = math.generateUnitNgonPoints( sides, rotationRadians ); - points = math.fitPolygonToSquare( points ); - - return points; -}; - -math.fitPolygonToSquare = function( points ){ - var x, y; - var sides = points.length / 2; - var minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity; - - for( var i = 0; i < sides; i++ ){ - x = points[2 * i ]; - y = points[2 * i + 1]; - - minX = Math.min( minX, x ); - maxX = Math.max( maxX, x ); - minY = Math.min( minY, y ); - maxY = Math.max( maxY, y ); - } - - // stretch factors - var sx = 2 / (maxX - minX); - var sy = 2 / (maxY - minY); - - for( var i = 0; i < sides; i++ ){ - x = points[2 * i ] = points[2 * i ] * sx; - y = points[2 * i + 1] = points[2 * i + 1] * sy; - - minX = Math.min( minX, x ); - maxX = Math.max( maxX, x ); - minY = Math.min( minY, y ); - maxY = Math.max( maxY, y ); - } - - if( minY < -1 ){ - for( var i = 0; i < sides; i++ ){ - y = points[2 * i + 1] = points[2 * i + 1] + (-1 - minY); - } - } - - return points; -}; - -math.generateUnitNgonPoints = function( sides, rotationRadians ){ - - var increment = 1.0 / sides * 2 * Math.PI; - var startAngle = sides % 2 === 0 ? - Math.PI / 2.0 + increment / 2.0 : Math.PI / 2.0; - // console.log(nodeShapes['square']); - startAngle += rotationRadians; - - var points = new Array( sides * 2 ); - - var currentAngle, x, y; - for( var i = 0; i < sides; i++ ){ - currentAngle = i * increment + startAngle; - - x = points[2 * i ] = Math.cos( currentAngle );// * (1 + i/2); - y = points[2 * i + 1] = Math.sin( -currentAngle );// * (1 + i/2); - } - - return points; -}; - -math.getRoundRectangleRadius = function( width, height ){ - - // Set the default radius, unless half of width or height is smaller than default - return Math.min( width / 4, height / 4, 8 ); -}; - -module.exports = math; - -},{}],86:[function(_dereq_,module,exports){ -/*! -Embeddable Minimum Strictly-Compliant Promises/A+ 1.1.1 Thenable -Copyright (c) 2013-2014 Ralf S. Engelschall (http://engelschall.com) -Licensed under The MIT License (http://opensource.org/licenses/MIT) -*/ - -'use strict'; - -/* promise states [Promises/A+ 2.1] */ -var STATE_PENDING = 0; /* [Promises/A+ 2.1.1] */ -var STATE_FULFILLED = 1; /* [Promises/A+ 2.1.2] */ -var STATE_REJECTED = 2; /* [Promises/A+ 2.1.3] */ - -/* promise object constructor */ -var api = function( executor ){ - /* optionally support non-constructor/plain-function call */ - if( !(this instanceof api) ) - return new api( executor ); - - /* initialize object */ - this.id = 'Thenable/1.0.7'; - this.state = STATE_PENDING; /* initial state */ - this.fulfillValue = undefined; /* initial value */ /* [Promises/A+ 1.3, 2.1.2.2] */ - this.rejectReason = undefined; /* initial reason */ /* [Promises/A+ 1.5, 2.1.3.2] */ - this.onFulfilled = []; /* initial handlers */ - this.onRejected = []; /* initial handlers */ - - /* provide optional information-hiding proxy */ - this.proxy = { - then: this.then.bind( this ) - }; - - /* support optional executor function */ - if( typeof executor === 'function' ) - executor.call( this, this.fulfill.bind( this ), this.reject.bind( this ) ); -}; - -/* promise API methods */ -api.prototype = { - /* promise resolving methods */ - fulfill: function( value ){ return deliver( this, STATE_FULFILLED, 'fulfillValue', value ); }, - reject: function( value ){ return deliver( this, STATE_REJECTED, 'rejectReason', value ); }, - - /* "The then Method" [Promises/A+ 1.1, 1.2, 2.2] */ - then: function( onFulfilled, onRejected ){ - var curr = this; - var next = new api(); /* [Promises/A+ 2.2.7] */ - curr.onFulfilled.push( - resolver( onFulfilled, next, 'fulfill' ) ); /* [Promises/A+ 2.2.2/2.2.6] */ - curr.onRejected.push( - resolver( onRejected, next, 'reject' ) ); /* [Promises/A+ 2.2.3/2.2.6] */ - execute( curr ); - return next.proxy; /* [Promises/A+ 2.2.7, 3.3] */ - } -}; - -/* deliver an action */ -var deliver = function( curr, state, name, value ){ - if( curr.state === STATE_PENDING ){ - curr.state = state; /* [Promises/A+ 2.1.2.1, 2.1.3.1] */ - curr[ name ] = value; /* [Promises/A+ 2.1.2.2, 2.1.3.2] */ - execute( curr ); - } - return curr; -}; - -/* execute all handlers */ -var execute = function( curr ){ - if( curr.state === STATE_FULFILLED ) - execute_handlers( curr, 'onFulfilled', curr.fulfillValue ); - else if( curr.state === STATE_REJECTED ) - execute_handlers( curr, 'onRejected', curr.rejectReason ); -}; - -/* execute particular set of handlers */ -var execute_handlers = function( curr, name, value ){ - /* global setImmediate: true */ - /* global setTimeout: true */ - - /* short-circuit processing */ - if( curr[ name ].length === 0 ) - return; - - /* iterate over all handlers, exactly once */ - var handlers = curr[ name ]; - curr[ name ] = []; /* [Promises/A+ 2.2.2.3, 2.2.3.3] */ - var func = function(){ - for( var i = 0; i < handlers.length; i++ ) - handlers[ i ]( value ); /* [Promises/A+ 2.2.5] */ - }; - - /* execute procedure asynchronously */ /* [Promises/A+ 2.2.4, 3.1] */ - if( typeof setImmediate === 'function' ) - setImmediate( func ); - else - setTimeout( func, 0 ); -}; - -/* generate a resolver function */ -var resolver = function( cb, next, method ){ - return function( value ){ - if( typeof cb !== 'function' ) /* [Promises/A+ 2.2.1, 2.2.7.3, 2.2.7.4] */ - next[ method ].call( next, value ); /* [Promises/A+ 2.2.7.3, 2.2.7.4] */ - else { - var result; - try { result = cb( value ); } /* [Promises/A+ 2.2.2.1, 2.2.3.1, 2.2.5, 3.2] */ - catch( e ){ - next.reject( e ); /* [Promises/A+ 2.2.7.2] */ - return; - } - resolve( next, result ); /* [Promises/A+ 2.2.7.1] */ - } - }; -}; - -/* "Promise Resolution Procedure" */ /* [Promises/A+ 2.3] */ -var resolve = function( promise, x ){ - /* sanity check arguments */ /* [Promises/A+ 2.3.1] */ - if( promise === x || promise.proxy === x ){ - promise.reject( new TypeError( 'cannot resolve promise with itself' ) ); - return; - } - - /* surgically check for a "then" method - (mainly to just call the "getter" of "then" only once) */ - var then; - if( (typeof x === 'object' && x !== null) || typeof x === 'function' ){ - try { then = x.then; } /* [Promises/A+ 2.3.3.1, 3.5] */ - catch( e ){ - promise.reject( e ); /* [Promises/A+ 2.3.3.2] */ - return; - } - } - - /* handle own Thenables [Promises/A+ 2.3.2] - and similar "thenables" [Promises/A+ 2.3.3] */ - if( typeof then === 'function' ){ - var resolved = false; - try { - /* call retrieved "then" method */ /* [Promises/A+ 2.3.3.3] */ - then.call( x, - /* resolvePromise */ /* [Promises/A+ 2.3.3.3.1] */ - function( y ){ - if( resolved ) return; resolved = true; /* [Promises/A+ 2.3.3.3.3] */ - if( y === x ) /* [Promises/A+ 3.6] */ - promise.reject( new TypeError( 'circular thenable chain' ) ); - else - resolve( promise, y ); - }, - - /* rejectPromise */ /* [Promises/A+ 2.3.3.3.2] */ - function( r ){ - if( resolved ) return; resolved = true; /* [Promises/A+ 2.3.3.3.3] */ - promise.reject( r ); - } - ); - } - catch( e ){ - if( !resolved ) /* [Promises/A+ 2.3.3.3.3] */ - promise.reject( e ); /* [Promises/A+ 2.3.3.3.4] */ - } - return; - } - - /* handle other values */ - promise.fulfill( x ); /* [Promises/A+ 2.3.4, 2.3.3.4] */ -}; - -// so we always have Promise.all() -api.all = function( ps ){ - return new api(function( resolveAll, rejectAll ){ - var vals = new Array( ps.length ); - var doneCount = 0; - - var fulfill = function( i, val ){ - vals[ i ] = val; - doneCount++; - - if( doneCount === ps.length ){ - resolveAll( vals ); - } - }; - - for( var i = 0; i < ps.length; i++ ){ - (function( i ){ - var p = ps[i]; - var isPromise = p != null && p.then != null; - - if( isPromise ){ - p.then( function( val ){ - fulfill( i, val ); - }, function( err ){ - rejectAll( err ); - } ); - } else { - var val = p; - fulfill( i, val ); - } - })( i ); - } - - } ); -}; - -api.resolve = function( val ){ - return new api(function( resolve, reject ){ resolve( val ); }); -}; - -api.reject = function( val ){ - return new api(function( resolve, reject ){ reject( val ); }); -}; - -module.exports = typeof Promise !== 'undefined' ? Promise : api; // eslint-disable-line no-undef - -},{}],87:[function(_dereq_,module,exports){ -'use strict'; - -var is = _dereq_( './is' ); -var util = _dereq_( './util' ); - -var Selector = function( selector ){ - - if( !(this instanceof Selector) ){ - return new Selector( selector ); - } - - var self = this; - - self._private = { - selectorText: null, - invalid: true - }; - - // storage for parsed queries - var newQuery = function(){ - return { - classes: [], - colonSelectors: [], - data: [], - group: null, - ids: [], - meta: [], - - // fake selectors - collection: null, // a collection to match against - filter: null, // filter function - - // these are defined in the upward direction rather than down (e.g. child) - // because we need to go up in Selector.filter() - parent: null, // parent query obj - ancestor: null, // ancestor query obj - subject: null, // defines subject in compound query (subject query obj; points to self if subject) - - // use these only when subject has been defined - child: null, - descendant: null - }; - }; - - if( !selector || ( is.string( selector ) && selector.match( /^\s*$/ ) ) ){ - - self.length = 0; - - } else if( selector === '*' || selector === 'edge' || selector === 'node' ){ - - // make single, group-only selectors cheap to make and cheap to filter - - self[0] = newQuery(); - self[0].group = selector === '*' ? selector : selector + 's'; - self[0].groupOnly = true; - self._private.invalid = false; - self._private.selectorText = selector; - self.length = 1; - - } else if( is.elementOrCollection( selector ) ){ - - var collection = selector.collection(); - - self[0] = newQuery(); - self[0].collection = collection; - self.length = 1; - - } else if( is.fn( selector ) ){ - - self[0] = newQuery(); - self[0].filter = selector; - self.length = 1; - - } else if( is.string( selector ) ){ - - // the current subject in the query - var currentSubject = null; - - // tokens in the query language - var tokens = { - metaChar: '[\\!\\"\\#\\$\\%\\&\\\'\\(\\)\\*\\+\\,\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\]\\^\\`\\{\\|\\}\\~]', // chars we need to escape in var names, etc - comparatorOp: '=|\\!=|>|>=|<|<=|\\$=|\\^=|\\*=', // binary comparison op (used in data selectors) - boolOp: '\\?|\\!|\\^', // boolean (unary) operators (used in data selectors) - string: '"(?:\\\\"|[^"])+"' + '|' + "'(?:\\\\'|[^'])+'", // string literals (used in data selectors) -- doublequotes | singlequotes - number: util.regex.number, // number literal (used in data selectors) --- e.g. 0.1234, 1234, 12e123 - meta: 'degree|indegree|outdegree', // allowed metadata fields (i.e. allowed functions to use from Collection) - separator: '\\s*,\\s*', // queries are separated by commas, e.g. edge[foo = 'bar'], node.someClass - descendant: '\\s+', - child: '\\s+>\\s+', - subject: '\\$' - }; - tokens.variable = '(?:[\\w-]|(?:\\\\' + tokens.metaChar + '))+'; // a variable name - tokens.value = tokens.string + '|' + tokens.number; // a value literal, either a string or number - tokens.className = tokens.variable; // a class name (follows variable conventions) - tokens.id = tokens.variable; // an element id (follows variable conventions) - - // when a token like a variable has escaped meta characters, we need to clean the backslashes out - // so that values get compared properly in Selector.filter() - var cleanMetaChars = function( str ){ - return str.replace( new RegExp( '\\\\(' + tokens.metaChar + ')', 'g' ), function( match, $1, offset, original ){ - return $1; - } ); - }; - - // add @ variants to comparatorOp - var ops = tokens.comparatorOp.split( '|' ); - for( var i = 0; i < ops.length; i++ ){ - var op = ops[ i ]; - tokens.comparatorOp += '|@' + op; - } - - // add ! variants to comparatorOp - var ops = tokens.comparatorOp.split( '|' ); - for( var i = 0; i < ops.length; i++ ){ - var op = ops[ i ]; - - if( op.indexOf( '!' ) >= 0 ){ continue; } // skip ops that explicitly contain ! - if( op === '=' ){ continue; } // skip = b/c != is explicitly defined - - tokens.comparatorOp += '|\\!' + op; - } - - // NOTE: add new expression syntax here to have it recognised by the parser; - // - a query contains all adjacent (i.e. no separator in between) expressions; - // - the current query is stored in self[i] --- you can use the reference to `this` in the populate function; - // - you need to check the query objects in Selector.filter() for it actually filter properly, but that's pretty straight forward - // - when you add something here, also add to Selector.toString() - var exprs = [ - { - name: 'group', - query: true, - regex: '(node|edge|\\*)', - populate: function( group ){ - this.group = group === '*' ? group : group + 's'; - } - }, - - { - name: 'state', - query: true, - // NB: if one colon selector is a substring of another from its start, place the longer one first - // e.g. :foobar|:foo - regex: '(:selected|:unselected|:locked|:unlocked|:visible|:hidden|:transparent|:grabbed|:free|:removed|:inside|:grabbable|:ungrabbable|:animated|:unanimated|:selectable|:unselectable|:orphan|:nonorphan|:parent|:child|:loop|:simple|:active|:inactive|:touch|:backgrounding|:nonbackgrounding)', - populate: function( state ){ - this.colonSelectors.push( state ); - } - }, - - { - name: 'id', - query: true, - regex: '\\#(' + tokens.id + ')', - populate: function( id ){ - this.ids.push( cleanMetaChars( id ) ); - } - }, - - { - name: 'className', - query: true, - regex: '\\.(' + tokens.className + ')', - populate: function( className ){ - this.classes.push( cleanMetaChars( className ) ); - } - }, - - { - name: 'dataExists', - query: true, - regex: '\\[\\s*(' + tokens.variable + ')\\s*\\]', - populate: function( variable ){ - this.data.push( { - field: cleanMetaChars( variable ) - } ); - } - }, - - { - name: 'dataCompare', - query: true, - regex: '\\[\\s*(' + tokens.variable + ')\\s*(' + tokens.comparatorOp + ')\\s*(' + tokens.value + ')\\s*\\]', - populate: function( variable, comparatorOp, value ){ - var valueIsString = new RegExp( '^' + tokens.string + '$' ).exec( value ) != null; - - if( valueIsString ){ - value = value.substring( 1, value.length - 1 ); - } else { - value = parseFloat( value ); - } - - this.data.push( { - field: cleanMetaChars( variable ), - operator: comparatorOp, - value: value - } ); - } - }, - - { - name: 'dataBool', - query: true, - regex: '\\[\\s*(' + tokens.boolOp + ')\\s*(' + tokens.variable + ')\\s*\\]', - populate: function( boolOp, variable ){ - this.data.push( { - field: cleanMetaChars( variable ), - operator: boolOp - } ); - } - }, - - { - name: 'metaCompare', - query: true, - regex: '\\[\\[\\s*(' + tokens.meta + ')\\s*(' + tokens.comparatorOp + ')\\s*(' + tokens.number + ')\\s*\\]\\]', - populate: function( meta, comparatorOp, number ){ - this.meta.push( { - field: cleanMetaChars( meta ), - operator: comparatorOp, - value: parseFloat( number ) - } ); - } - }, - - { - name: 'nextQuery', - separator: true, - regex: tokens.separator, - populate: function(){ - // go on to next query - self[ ++i ] = newQuery(); - currentSubject = null; - } - }, - - { - name: 'child', - separator: true, - regex: tokens.child, - populate: function(){ - // this query is the parent of the following query - var childQuery = newQuery(); - childQuery.parent = this; - childQuery.subject = currentSubject; - - // we're now populating the child query with expressions that follow - self[ i ] = childQuery; - } - }, - - { - name: 'descendant', - separator: true, - regex: tokens.descendant, - populate: function(){ - // this query is the ancestor of the following query - var descendantQuery = newQuery(); - descendantQuery.ancestor = this; - descendantQuery.subject = currentSubject; - - // we're now populating the descendant query with expressions that follow - self[ i ] = descendantQuery; - } - }, - - { - name: 'subject', - modifier: true, - regex: tokens.subject, - populate: function(){ - if( currentSubject != null && this.subject != this ){ - util.error( 'Redefinition of subject in selector `' + selector + '`' ); - return false; - } - - currentSubject = this; - this.subject = this; - } - - } - ]; - - self._private.selectorText = selector; - var remaining = selector; - var i = 0; - - // of all the expressions, find the first match in the remaining text - var consumeExpr = function( expectation ){ - var expr; - var match; - var name; - - for( var j = 0; j < exprs.length; j++ ){ - var e = exprs[ j ]; - var n = e.name; - - // ignore this expression if it doesn't meet the expectation function - if( is.fn( expectation ) && !expectation( n, e ) ){ continue; } - - var m = remaining.match( new RegExp( '^' + e.regex ) ); - - if( m != null ){ - match = m; - expr = e; - name = n; - - var consumed = m[0]; - remaining = remaining.substring( consumed.length ); - - break; // we've consumed one expr, so we can return now - } - } - - return { - expr: expr, - match: match, - name: name - }; - }; - - // consume all leading whitespace - var consumeWhitespace = function(){ - var match = remaining.match( /^\s+/ ); - - if( match ){ - var consumed = match[0]; - remaining = remaining.substring( consumed.length ); - } - }; - - self[0] = newQuery(); // get started - - consumeWhitespace(); // get rid of leading whitespace - for( ;; ){ - var check = consumeExpr(); - - if( check.expr == null ){ - util.error( 'The selector `' + selector + '`is invalid' ); - return; - } else { - var args = []; - for( var j = 1; j < check.match.length; j++ ){ - args.push( check.match[ j ] ); - } - - // let the token populate the selector object (i.e. in self[i]) - var ret = check.expr.populate.apply( self[ i ], args ); - - if( ret === false ){ return; } // exit if population failed - } - - // we're done when there's nothing left to parse - if( remaining.match( /^\s*$/ ) ){ - break; - } - } - - self.length = i + 1; - - // adjust references for subject - for( var j = 0; j < self.length; j++ ){ - var query = self[ j ]; - - if( query.subject != null ){ - // go up the tree until we reach the subject - for( ;; ){ - if( query.subject == query ){ break; } // done if subject is self - - if( query.parent != null ){ // swap parent/child reference - var parent = query.parent; - var child = query; - - child.parent = null; - parent.child = child; - - query = parent; // go up the tree - } else if( query.ancestor != null ){ // swap ancestor/descendant - var ancestor = query.ancestor; - var descendant = query; - - descendant.ancestor = null; - ancestor.descendant = descendant; - - query = ancestor; // go up the tree - } else { - util.error( 'When adjusting references for the selector `' + query + '`, neither parent nor ancestor was found' ); - break; - } - } // for - - self[ j ] = query.subject; // subject should be the root query - } // if - } // for - - } else { - util.error( 'A selector must be created from a string; found ' + selector ); - return; - } - - self._private.invalid = false; - -}; - -var selfn = Selector.prototype; - -selfn.size = function(){ - return this.length; -}; - -selfn.eq = function( i ){ - return this[ i ]; -}; - -var queryMatches = function( query, ele ){ - var ele_p = ele._private; - - // make single group-only selectors really cheap to check since they're the most common ones - if( query.groupOnly ){ - return query.group === '*' || query.group === ele_p.group; - } - - // check group - if( query.group != null && query.group != '*' && query.group != ele_p.group ){ - return false; - } - - var cy = ele.cy(); - - // check colon selectors - var allColonSelectorsMatch = true; - for( var k = 0; k < query.colonSelectors.length; k++ ){ - var sel = query.colonSelectors[ k ]; - - switch( sel ){ - case ':selected': - allColonSelectorsMatch = ele.selected(); - break; - case ':unselected': - allColonSelectorsMatch = !ele.selected(); - break; - case ':selectable': - allColonSelectorsMatch = ele.selectable(); - break; - case ':unselectable': - allColonSelectorsMatch = !ele.selectable(); - break; - case ':locked': - allColonSelectorsMatch = ele.locked(); - break; - case ':unlocked': - allColonSelectorsMatch = !ele.locked(); - break; - case ':visible': - allColonSelectorsMatch = ele.visible(); - break; - case ':hidden': - allColonSelectorsMatch = !ele.visible(); - break; - case ':transparent': - allColonSelectorsMatch = ele.transparent(); - break; - case ':grabbed': - allColonSelectorsMatch = ele.grabbed(); - break; - case ':free': - allColonSelectorsMatch = !ele.grabbed(); - break; - case ':removed': - allColonSelectorsMatch = ele.removed(); - break; - case ':inside': - allColonSelectorsMatch = !ele.removed(); - break; - case ':grabbable': - allColonSelectorsMatch = ele.grabbable(); - break; - case ':ungrabbable': - allColonSelectorsMatch = !ele.grabbable(); - break; - case ':animated': - allColonSelectorsMatch = ele.animated(); - break; - case ':unanimated': - allColonSelectorsMatch = !ele.animated(); - break; - case ':parent': - allColonSelectorsMatch = ele.isNode() && ele.children().nonempty(); - break; - case ':child': - case ':nonorphan': - allColonSelectorsMatch = ele.isNode() && ele.parent().nonempty(); - break; - case ':orphan': - allColonSelectorsMatch = ele.isNode() && ele.parent().empty(); - break; - case ':loop': - allColonSelectorsMatch = ele.isEdge() && ele.data( 'source' ) === ele.data( 'target' ); - break; - case ':simple': - allColonSelectorsMatch = ele.isEdge() && ele.data( 'source' ) !== ele.data( 'target' ); - break; - case ':active': - allColonSelectorsMatch = ele.active(); - break; - case ':inactive': - allColonSelectorsMatch = !ele.active(); - break; - case ':touch': - allColonSelectorsMatch = is.touch(); - break; - case ':backgrounding': - allColonSelectorsMatch = ele.backgrounding(); - break; - case ':nonbackgrounding': - allColonSelectorsMatch = !ele.backgrounding(); - break; - } - - if( !allColonSelectorsMatch ) break; - } - if( !allColonSelectorsMatch ) return false; - - // check id - var allIdsMatch = true; - for( var k = 0; k < query.ids.length; k++ ){ - var id = query.ids[ k ]; - var actualId = ele_p.data.id; - - allIdsMatch = allIdsMatch && (id == actualId); - - if( !allIdsMatch ) break; - } - if( !allIdsMatch ) return false; - - // check classes - var allClassesMatch = true; - for( var k = 0; k < query.classes.length; k++ ){ - var cls = query.classes[ k ]; - - allClassesMatch = allClassesMatch && ele.hasClass( cls ); - - if( !allClassesMatch ) break; - } - if( !allClassesMatch ) return false; - - // generic checking for data/metadata - var operandsMatch = function( params ){ - var allDataMatches = true; - for( var k = 0; k < query[ params.name ].length; k++ ){ - var data = query[ params.name ][ k ]; - var operator = data.operator; - var value = data.value; - var field = data.field; - var matches; - - if( operator != null && value != null ){ - - var fieldVal = params.fieldValue( field ); - var fieldStr = !is.string( fieldVal ) && !is.number( fieldVal ) ? '' : '' + fieldVal; - var valStr = '' + value; - - var caseInsensitive = false; - if( operator.indexOf( '@' ) >= 0 ){ - fieldStr = fieldStr.toLowerCase(); - valStr = valStr.toLowerCase(); - - operator = operator.replace( '@', '' ); - caseInsensitive = true; - } - - var notExpr = false; - if( operator.indexOf( '!' ) >= 0 ){ - operator = operator.replace( '!', '' ); - notExpr = true; - } - - // if we're doing a case insensitive comparison, then we're using a STRING comparison - // even if we're comparing numbers - if( caseInsensitive ){ - value = valStr.toLowerCase(); - fieldVal = fieldStr.toLowerCase(); - } - - var isIneqCmp = false; - - switch( operator ){ - case '*=': - matches = fieldStr.indexOf( valStr ) >= 0; - break; - case '$=': - matches = fieldStr.indexOf( valStr, fieldStr.length - valStr.length ) >= 0; - break; - case '^=': - matches = fieldStr.indexOf( valStr ) === 0; - break; - case '=': - matches = fieldVal === value; - break; - case '>': - isIneqCmp = true; - matches = fieldVal > value; - break; - case '>=': - isIneqCmp = true; - matches = fieldVal >= value; - break; - case '<': - isIneqCmp = true; - matches = fieldVal < value; - break; - case '<=': - isIneqCmp = true; - matches = fieldVal <= value; - break; - default: - matches = false; - break; - } - - // apply the not op, but null vals for inequalities should always stay non-matching - if( notExpr && ( fieldVal != null || !isIneqCmp ) ){ - matches = !matches; - } - } else if( operator != null ){ - switch( operator ){ - case '?': - matches = params.fieldTruthy( field ); - break; - case '!': - matches = !params.fieldTruthy( field ); - break; - case '^': - matches = params.fieldUndefined( field ); - break; - } - } else { - matches = !params.fieldUndefined( field ); - } - - if( !matches ){ - allDataMatches = false; - break; - } - } // for - - return allDataMatches; - }; // operandsMatch - - // check data matches - var allDataMatches = operandsMatch( { - name: 'data', - fieldValue: function( field ){ - return ele_p.data[ field ]; - }, - fieldUndefined: function( field ){ - return ele_p.data[ field ] === undefined; - }, - fieldTruthy: function( field ){ - if( ele_p.data[ field ] ){ - return true; - } - return false; - } - } ); - - if( !allDataMatches ){ - return false; - } - - // check metadata matches - var allMetaMatches = operandsMatch( { - name: 'meta', - fieldValue: function( field ){ - return ele[ field ](); - }, - fieldUndefined: function( field ){ - return ele[ field ]() == null; - }, - fieldTruthy: function( field ){ - if( ele[ field ]() ){ - return true; - } - return false; - } - } ); - - if( !allMetaMatches ){ - return false; - } - - // check collection - if( query.collection != null ){ - var matchesAny = query.collection.hasElementWithId( ele.id() ); - - if( !matchesAny ){ - return false; - } - } - - // check filter function - if( query.filter != null && ele.collection().filter( query.filter ).size() === 0 ){ - return false; - } - - // check parent/child relations - var confirmRelations = function( query, eles ){ - if( query != null ){ - var matches = false; - - if( !cy.hasCompoundNodes() ){ - return false; - } - - eles = eles(); // save cycles if query == null - - // query must match for at least one element (may be recursive) - for( var i = 0; i < eles.length; i++ ){ - if( queryMatches( query, eles[ i ] ) ){ - matches = true; - break; - } - } - - return matches; - } else { - return true; - } - }; - - if( !confirmRelations( query.parent, function(){ - return ele.parent(); - } ) ){ return false; } - - if( !confirmRelations( query.ancestor, function(){ - return ele.parents(); - } ) ){ return false; } - - if( !confirmRelations( query.child, function(){ - return ele.children(); - } ) ){ return false; } - - if( !confirmRelations( query.descendant, function(){ - return ele.descendants(); - } ) ){ return false; } - - // we've reached the end, so we've matched everything for this query - return true; -}; // queryMatches - -// filter an existing collection -selfn.filter = function( collection ){ - var self = this; - var cy = collection.cy(); - - // don't bother trying if it's invalid - if( self._private.invalid ){ - return cy.collection(); - } - - var selectorFunction = function( i, element ){ - for( var j = 0; j < self.length; j++ ){ - var query = self[ j ]; - - if( queryMatches( query, element ) ){ - return true; - } - } - - return false; - }; - - if( self._private.selectorText == null ){ - selectorFunction = function(){ return true; }; - } - - var filteredCollection = collection.filter( selectorFunction ); - - return filteredCollection; -}; // filter - -// does selector match a single element? -selfn.matches = function( ele ){ - var self = this; - - // don't bother trying if it's invalid - if( self._private.invalid ){ - return false; - } - - for( var j = 0; j < self.length; j++ ){ - var query = self[ j ]; - - if( queryMatches( query, ele ) ){ - return true; - } - } - - return false; -}; // filter - -// ith query to string -selfn.toString = selfn.selector = function(){ - - var str = ''; - - var clean = function( obj, isValue ){ - if( is.string( obj ) ){ - return isValue ? '"' + obj + '"' : obj; - } - return ''; - }; - - var queryToString = function( query ){ - var str = ''; - - if( query.subject === query ){ - str += '$'; - } - - var group = clean( query.group ); - str += group.substring( 0, group.length - 1 ); - - for( var j = 0; j < query.data.length; j++ ){ - var data = query.data[ j ]; - - if( data.value ){ - str += '[' + data.field + clean( data.operator ) + clean( data.value, true ) + ']'; - } else { - str += '[' + clean( data.operator ) + data.field + ']'; - } - } - - for( var j = 0; j < query.meta.length; j++ ){ - var meta = query.meta[ j ]; - str += '[[' + meta.field + clean( meta.operator ) + clean( meta.value, true ) + ']]'; - } - - for( var j = 0; j < query.colonSelectors.length; j++ ){ - var sel = query.colonSelectors[ i ]; - str += sel; - } - - for( var j = 0; j < query.ids.length; j++ ){ - var sel = '#' + query.ids[ i ]; - str += sel; - } - - for( var j = 0; j < query.classes.length; j++ ){ - var sel = '.' + query.classes[ j ]; - str += sel; - } - - if( query.parent != null ){ - str = queryToString( query.parent ) + ' > ' + str; - } - - if( query.ancestor != null ){ - str = queryToString( query.ancestor ) + ' ' + str; - } - - if( query.child != null ){ - str += ' > ' + queryToString( query.child ); - } - - if( query.descendant != null ){ - str += ' ' + queryToString( query.descendant ); - } - - return str; - }; - - for( var i = 0; i < this.length; i++ ){ - var query = this[ i ]; - - str += queryToString( query ); - - if( this.length > 1 && i < this.length - 1 ){ - str += ', '; - } - } - - return str; -}; - -module.exports = Selector; - -},{"./is":83,"./util":100}],88:[function(_dereq_,module,exports){ -'use strict'; - -var util = _dereq_( '../util' ); -var is = _dereq_( '../is' ); - -var styfn = {}; - -// (potentially expensive calculation) -// apply the style to the element based on -// - its bypass -// - what selectors match it -styfn.apply = function( eles ){ - var self = this; - var _p = self._private; - - if( _p.newStyle ){ // clear style caches - _p.contextStyles = {}; - _p.propDiffs = {}; - - self.cleanElements( eles, true ); - } - - for( var ie = 0; ie < eles.length; ie++ ){ - var ele = eles[ ie ]; - - var cxtMeta = self.getContextMeta( ele ); - var cxtStyle = self.getContextStyle( cxtMeta ); - var app = self.applyContextStyle( cxtMeta, cxtStyle, ele ); - - self.updateTransitions( ele, app.diffProps ); - self.updateStyleHints( ele ); - - } // for elements - - _p.newStyle = false; -}; - -styfn.getPropertiesDiff = function( oldCxtKey, newCxtKey ){ - var self = this; - var cache = self._private.propDiffs = self._private.propDiffs || {}; - var dualCxtKey = oldCxtKey + '-' + newCxtKey; - var cachedVal = cache[ dualCxtKey ]; - - if( cachedVal ){ - return cachedVal; - } - - var diffProps = []; - var addedProp = {}; - - for( var i = 0; i < self.length; i++ ){ - var cxt = self[ i ]; - var oldHasCxt = oldCxtKey[ i ] === 't'; - var newHasCxt = newCxtKey[ i ] === 't'; - var cxtHasDiffed = oldHasCxt !== newHasCxt; - var cxtHasMappedProps = cxt.mappedProperties.length > 0; - - if( cxtHasDiffed || cxtHasMappedProps ){ - var props; - - if( cxtHasDiffed && cxtHasMappedProps ){ - props = cxt.properties; // suffices b/c mappedProperties is a subset of properties - } else if( cxtHasDiffed ){ - props = cxt.properties; // need to check them all - } else if( cxtHasMappedProps ){ - props = cxt.mappedProperties; // only need to check mapped - } - - for( var j = 0; j < props.length; j++ ){ - var prop = props[ j ]; - var name = prop.name; - - // if a later context overrides this property, then the fact that this context has switched/diffed doesn't matter - // (semi expensive check since it makes this function O(n^2) on context length, but worth it since overall result - // is cached) - var laterCxtOverrides = false; - for( var k = i + 1; k < self.length; k++ ){ - var laterCxt = self[ k ]; - var hasLaterCxt = newCxtKey[ k ] === 't'; - - if( !hasLaterCxt ){ continue; } // can't override unless the context is active - - laterCxtOverrides = laterCxt.properties[ prop.name ] != null; - - if( laterCxtOverrides ){ break; } // exit early as long as one later context overrides - } - - if( !addedProp[ name ] && !laterCxtOverrides ){ - addedProp[ name ] = true; - diffProps.push( name ); - } - } // for props - } // if - - } // for contexts - - cache[ dualCxtKey ] = diffProps; - return diffProps; -}; - -styfn.getContextMeta = function( ele ){ - var self = this; - var cxtKey = ''; - var diffProps; - var prevKey = ele._private.styleCxtKey || ''; - - if( self._private.newStyle ){ - prevKey = ''; // since we need to apply all style if a fresh stylesheet - } - - // get the cxt key - for( var i = 0; i < self.length; i++ ){ - var context = self[ i ]; - var contextSelectorMatches = context.selector && context.selector.matches( ele ); // NB: context.selector may be null for 'core' - - if( contextSelectorMatches ){ - cxtKey += 't'; - } else { - cxtKey += 'f'; - } - } // for context - - diffProps = self.getPropertiesDiff( prevKey, cxtKey ); - - ele._private.styleCxtKey = cxtKey; - - return { - key: cxtKey, - diffPropNames: diffProps - }; -}; - -// gets a computed ele style object based on matched contexts -styfn.getContextStyle = function( cxtMeta ){ - var cxtKey = cxtMeta.key; - var self = this; - var cxtStyles = this._private.contextStyles = this._private.contextStyles || {}; - - // if already computed style, returned cached copy - if( cxtStyles[ cxtKey ] ){ return cxtStyles[ cxtKey ]; } - - var style = { - _private: { - key: cxtKey - } - }; - - for( var i = 0; i < self.length; i++ ){ - var cxt = self[ i ]; - var hasCxt = cxtKey[ i ] === 't'; - - if( !hasCxt ){ continue; } - - for( var j = 0; j < cxt.properties.length; j++ ){ - var prop = cxt.properties[ j ]; - var styProp = style[ prop.name ] = prop; - - styProp.context = cxt; - } - } - - cxtStyles[ cxtKey ] = style; - return style; -}; - -styfn.applyContextStyle = function( cxtMeta, cxtStyle, ele ){ - var self = this; - var diffProps = cxtMeta.diffPropNames; - var retDiffProps = {}; - - for( var i = 0; i < diffProps.length; i++ ){ - var diffPropName = diffProps[ i ]; - var cxtProp = cxtStyle[ diffPropName ]; - var eleProp = ele.pstyle( diffPropName ); - - if( !cxtProp ){ // no context prop means delete - if( eleProp.bypass ){ - cxtProp = { name: diffPropName, deleteBypassed: true }; - } else { - cxtProp = { name: diffPropName, delete: true }; - } - } - - // save cycles when the context prop doesn't need to be applied - if( eleProp === cxtProp ){ continue; } - - var retDiffProp = retDiffProps[ diffPropName ] = { - prev: eleProp - }; - - self.applyParsedProperty( ele, cxtProp ); - - retDiffProp.next = ele.pstyle( diffPropName ); - - if( retDiffProp.next && retDiffProp.next.bypass ){ - retDiffProp.next = retDiffProp.next.bypassed; - } - } - - return { - diffProps: retDiffProps - }; -}; - -styfn.updateStyleHints = function(ele){ - var _p = ele._private; - var self = this; - - if( ele.removed() ){ return; } - - // set whether has pie or not; for greater efficiency - var hasPie = false; - if( _p.group === 'nodes' ){ - for( var i = 1; i <= self.pieBackgroundN; i++ ){ // 1..N - var size = ele.pstyle( 'pie-' + i + '-background-size' ).value; - - if( size > 0 ){ - hasPie = true; - break; - } - } - } - - _p.hasPie = hasPie; - - var transform = ele.pstyle( 'text-transform' ).strValue; - var content = ele.pstyle( 'label' ).strValue; - var srcContent = ele.pstyle( 'source-label' ).strValue; - var tgtContent = ele.pstyle( 'target-label' ).strValue; - var fStyle = ele.pstyle( 'font-style' ).strValue; - var size = ele.pstyle( 'font-size' ).pfValue + 'px'; - var family = ele.pstyle( 'font-family' ).strValue; - // var variant = style['font-variant'].strValue; - var weight = ele.pstyle( 'font-weight' ).strValue; - var valign = ele.pstyle( 'text-valign' ).strValue; - var halign = ele.pstyle( 'text-valign' ).strValue; - var oWidth = ele.pstyle( 'text-outline-width' ).pfValue; - var wrap = ele.pstyle( 'text-wrap' ).strValue; - var wrapW = ele.pstyle( 'text-max-width' ).pfValue; - var labelStyleKey = fStyle + '$' + size + '$' + family + '$' + weight + '$' + transform + '$' + valign + '$' + halign + '$' + oWidth + '$' + wrap + '$' + wrapW; - _p.labelStyleKey = labelStyleKey; - _p.sourceLabelKey = labelStyleKey + '$' + srcContent; - _p.targetLabelKey = labelStyleKey + '$' + tgtContent; - _p.labelKey = labelStyleKey + '$' + content; - _p.fontKey = fStyle + '$' + weight + '$' + size + '$' + family; - - _p.styleKey = Date.now(); -}; - -// apply a property to the style (for internal use) -// returns whether application was successful -// -// now, this function flattens the property, and here's how: -// -// for parsedProp:{ bypass: true, deleteBypass: true } -// no property is generated, instead the bypass property in the -// element's style is replaced by what's pointed to by the `bypassed` -// field in the bypass property (i.e. restoring the property the -// bypass was overriding) -// -// for parsedProp:{ mapped: truthy } -// the generated flattenedProp:{ mapping: prop } -// -// for parsedProp:{ bypass: true } -// the generated flattenedProp:{ bypassed: parsedProp } -styfn.applyParsedProperty = function( ele, parsedProp ){ - var self = this; - var prop = parsedProp; - var style = ele._private.style; - var fieldVal, flatProp; - var types = self.types; - var type = self.properties[ prop.name ].type; - var propIsBypass = prop.bypass; - var origProp = style[ prop.name ]; - var origPropIsBypass = origProp && origProp.bypass; - var _p = ele._private; - - // edges connected to compound nodes can not be haystacks - if( - parsedProp.name === 'curve-style' - && parsedProp.value === 'haystack' - && ele.isEdge() - && ( ele.isLoop() || ele.source().isParent() || ele.target().isParent() ) - ){ - prop = parsedProp = this.parse( parsedProp.name, 'bezier', propIsBypass ); - } - - if( prop.delete ){ // delete the property and use the default value on falsey value - style[ prop.name ] = undefined; - - return true; - } - - if( prop.deleteBypassed ){ // delete the property that the - if( !origProp ){ - return true; // can't delete if no prop - - } else if( origProp.bypass ){ // delete bypassed - origProp.bypassed = undefined; - return true; - - } else { - return false; // we're unsuccessful deleting the bypassed - } - } - - // check if we need to delete the current bypass - if( prop.deleteBypass ){ // then this property is just here to indicate we need to delete - if( !origProp ){ - return true; // property is already not defined - - } else if( origProp.bypass ){ // then replace the bypass property with the original - // because the bypassed property was already applied (and therefore parsed), we can just replace it (no reapplying necessary) - style[ prop.name ] = origProp.bypassed; - return true; - - } else { - return false; // we're unsuccessful deleting the bypass - } - } - - var printMappingErr = function(){ - util.error( 'Do not assign mappings to elements without corresponding data (e.g. ele `' + ele.id() + '` for property `' + prop.name + '` with data field `' + prop.field + '`); try a `[' + prop.field + ']` selector to limit scope to elements with `' + prop.field + '` defined' ); - }; - - // put the property in the style objects - switch( prop.mapped ){ // flatten the property if mapped - case types.mapData: - case types.mapLayoutData: - case types.mapScratch: - - var isLayout = prop.mapped === types.mapLayoutData; - var isScratch = prop.mapped === types.mapScratch; - - // flatten the field (e.g. data.foo.bar) - var fields = prop.field.split( '.' ); - var fieldVal; - - if( isScratch || isLayout ){ - fieldVal = _p.scratch; - } else { - fieldVal = _p.data; - } - - for( var i = 0; i < fields.length && fieldVal; i++ ){ - var field = fields[ i ]; - fieldVal = fieldVal[ field ]; - } - - var percent; - if( !is.number( fieldVal ) ){ // then keep the mapping but assume 0% for now - percent = 0; - } else { - percent = (fieldVal - prop.fieldMin) / (prop.fieldMax - prop.fieldMin); - } - - // make sure to bound percent value - if( percent < 0 ){ - percent = 0; - } else if( percent > 1 ){ - percent = 1; - } - - if( type.color ){ - var r1 = prop.valueMin[0]; - var r2 = prop.valueMax[0]; - var g1 = prop.valueMin[1]; - var g2 = prop.valueMax[1]; - var b1 = prop.valueMin[2]; - var b2 = prop.valueMax[2]; - var a1 = prop.valueMin[3] == null ? 1 : prop.valueMin[3]; - var a2 = prop.valueMax[3] == null ? 1 : prop.valueMax[3]; - - var clr = [ - Math.round( r1 + (r2 - r1) * percent ), - Math.round( g1 + (g2 - g1) * percent ), - Math.round( b1 + (b2 - b1) * percent ), - Math.round( a1 + (a2 - a1) * percent ) - ]; - - flatProp = { // colours are simple, so just create the flat property instead of expensive string parsing - bypass: prop.bypass, // we're a bypass if the mapping property is a bypass - name: prop.name, - value: clr, - strValue: 'rgb(' + clr[0] + ', ' + clr[1] + ', ' + clr[2] + ')' - }; - - } else if( type.number ){ - var calcValue = prop.valueMin + (prop.valueMax - prop.valueMin) * percent; - flatProp = this.parse( prop.name, calcValue, prop.bypass, true ); - - } else { - return false; // can only map to colours and numbers - } - - if( !flatProp ){ // if we can't flatten the property, then use the origProp so we still keep the mapping itself - flatProp = this.parse( prop.name, origProp.strValue, prop.bypass, true ); - } - - if( !flatProp ){ printMappingErr(); } - flatProp.mapping = prop; // keep a reference to the mapping - prop = flatProp; // the flattened (mapped) property is the one we want - - break; - - // direct mapping - case types.data: - case types.layoutData: - case types.scratch: - var isLayout = prop.mapped === types.layoutData; - var isScratch = prop.mapped === types.scratch; - - // flatten the field (e.g. data.foo.bar) - var fields = prop.field.split( '.' ); - var fieldVal; - - if( isScratch || isLayout ){ - fieldVal = _p.scratch; - } else { - fieldVal = _p.data; - } - - if( fieldVal ){ for( var i = 0; i < fields.length; i++ ){ - var field = fields[ i ]; - fieldVal = fieldVal[ field ]; - } } - - flatProp = this.parse( prop.name, fieldVal, prop.bypass, true ); - - if( !flatProp ){ // if we can't flatten the property, then use the origProp so we still keep the mapping itself - var flatPropVal = origProp ? origProp.strValue : ''; - - flatProp = this.parse( prop.name, flatPropVal, prop.bypass, true ); - } - - if( !flatProp ){ printMappingErr(); } - flatProp.mapping = prop; // keep a reference to the mapping - prop = flatProp; // the flattened (mapped) property is the one we want - - break; - - case types.fn: - var fn = prop.value; - var fnRetVal = fn( ele ); - - flatProp = this.parse( prop.name, fnRetVal, prop.bypass, true ); - flatProp.mapping = prop; // keep a reference to the mapping - prop = flatProp; // the flattened (mapped) property is the one we want - - break; - - case undefined: - break; // just set the property - - default: - return false; // not a valid mapping - } - - // if the property is a bypass property, then link the resultant property to the original one - if( propIsBypass ){ - if( origPropIsBypass ){ // then this bypass overrides the existing one - prop.bypassed = origProp.bypassed; // steal bypassed prop from old bypass - } else { // then link the orig prop to the new bypass - prop.bypassed = origProp; - } - - style[ prop.name ] = prop; // and set - - } else { // prop is not bypass - if( origPropIsBypass ){ // then keep the orig prop (since it's a bypass) and link to the new prop - origProp.bypassed = prop; - } else { // then just replace the old prop with the new one - style[ prop.name ] = prop; - } - } - - return true; -}; - -styfn.cleanElements = function( eles, keepBypasses ){ - var self = this; - var props = self.properties; - - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[i]; - - if( !keepBypasses ){ - ele._private.style = {}; - } else { - var style = ele._private.style; - - for( var j = 0; j < props.length; j++ ){ - var prop = props[j]; - var eleProp = style[ prop.name ]; - - if( eleProp ){ - if( eleProp.bypass ){ - eleProp.bypassed = null; - } else { - style[ prop.name ] = null; - } - } - } - } - } -}; - -// updates the visual style for all elements (useful for manual style modification after init) -styfn.update = function(){ - var cy = this._private.cy; - var eles = cy.mutableElements(); - - eles.updateStyle(); -}; - -// just update the functional properties (i.e. mappings) in the elements' -// styles (less expensive than recalculation) -styfn.updateMappers = function( eles ){ - var self = this; - - for( var i = 0; i < eles.length; i++ ){ // for each ele - var ele = eles[ i ]; - var style = ele._private.style; - - for( var j = 0; j < self.properties.length; j++ ){ // for each prop - var prop = self.properties[ j ]; - var propInStyle = style[ prop.name ]; - - if( propInStyle && propInStyle.mapping ){ - var mapping = propInStyle.mapping; - this.applyParsedProperty( ele, mapping ); // reapply the mapping property - } - } - - this.updateStyleHints( ele ); - } -}; - -// diffProps : { name => { prev, next } } -styfn.updateTransitions = function( ele, diffProps, isBypass ){ - var self = this; - var _p = ele._private; - var props = ele.pstyle( 'transition-property' ).value; - var duration = ele.pstyle( 'transition-duration' ).pfValue; - var delay = ele.pstyle( 'transition-delay' ).pfValue; - - if( props.length > 0 && duration > 0 ){ - - var css = {}; - - // build up the style to animate towards - var anyPrev = false; - for( var i = 0; i < props.length; i++ ){ - var prop = props[ i ]; - var styProp = ele.pstyle( prop ); - var diffProp = diffProps[ prop ]; - - if( !diffProp ){ continue; } - - var prevProp = diffProp.prev; - var fromProp = prevProp; - var toProp = diffProp.next != null ? diffProp.next : styProp; - var diff = false; - var initVal; - var initDt = 0.000001; // delta time % value for initVal (allows animating out of init zero opacity) - - if( !fromProp ){ continue; } - - // consider px values - if( is.number( fromProp.pfValue ) && is.number( toProp.pfValue ) ){ - diff = toProp.pfValue - fromProp.pfValue; // nonzero is truthy - initVal = fromProp.pfValue + initDt * diff; - - // consider numerical values - } else if( is.number( fromProp.value ) && is.number( toProp.value ) ){ - diff = toProp.value - fromProp.value; // nonzero is truthy - initVal = fromProp.value + initDt * diff; - - // consider colour values - } else if( is.array( fromProp.value ) && is.array( toProp.value ) ){ - diff = fromProp.value[0] !== toProp.value[0] - || fromProp.value[1] !== toProp.value[1] - || fromProp.value[2] !== toProp.value[2] - ; - - initVal = fromProp.strValue; - } - - // the previous value is good for an animation only if it's different - if( diff ){ - css[ prop ] = toProp.strValue; // to val - this.applyBypass( ele, prop, initVal ); // from val - anyPrev = true; - } - - } // end if props allow ani - - // can't transition if there's nothing previous to transition from - if( !anyPrev ){ return; } - - _p.transitioning = true; - - ele.stop(); - - if( delay > 0 ){ - ele.delay( delay ); - } - - ele.animate( { - css: css - }, { - duration: duration, - easing: ele.pstyle( 'transition-timing-function' ).value, - queue: false, - complete: function(){ - if( !isBypass ){ - self.removeBypasses( ele, props ); - } - - _p.transitioning = false; - } - } ); - - } else if( _p.transitioning ){ - ele.stop(); - - this.removeBypasses( ele, props ); - - _p.transitioning = false; - } -}; - -module.exports = styfn; - -},{"../is":83,"../util":100}],89:[function(_dereq_,module,exports){ -'use strict'; - -var is = _dereq_( '../is' ); -var util = _dereq_( '../util' ); - -var styfn = {}; - -// bypasses are applied to an existing style on an element, and just tacked on temporarily -// returns true iff application was successful for at least 1 specified property -styfn.applyBypass = function( eles, name, value, updateTransitions ){ - var self = this; - var props = []; - var isBypass = true; - - // put all the properties (can specify one or many) in an array after parsing them - if( name === '*' || name === '**' ){ // apply to all property names - - if( value !== undefined ){ - for( var i = 0; i < self.properties.length; i++ ){ - var prop = self.properties[ i ]; - var name = prop.name; - - var parsedProp = this.parse( name, value, true ); - - if( parsedProp ){ - props.push( parsedProp ); - } - } - } - - } else if( is.string( name ) ){ // then parse the single property - var parsedProp = this.parse( name, value, true ); - - if( parsedProp ){ - props.push( parsedProp ); - } - } else if( is.plainObject( name ) ){ // then parse each property - var specifiedProps = name; - updateTransitions = value; - - for( var i = 0; i < self.properties.length; i++ ){ - var prop = self.properties[ i ]; - var name = prop.name; - var value = specifiedProps[ name ]; - - if( value === undefined ){ // try camel case name too - value = specifiedProps[ util.dash2camel( name ) ]; - } - - if( value !== undefined ){ - var parsedProp = this.parse( name, value, true ); - - if( parsedProp ){ - props.push( parsedProp ); - } - } - } - } else { // can't do anything without well defined properties - return false; - } - - // we've failed if there are no valid properties - if( props.length === 0 ){ return false; } - - // now, apply the bypass properties on the elements - var ret = false; // return true if at least one succesful bypass applied - for( var i = 0; i < eles.length; i++ ){ // for each ele - var ele = eles[ i ]; - var diffProps = {}; - var diffProp; - - for( var j = 0; j < props.length; j++ ){ // for each prop - var prop = props[ j ]; - - if( updateTransitions ){ - var prevProp = ele.pstyle( prop.name ); - diffProp = diffProps[ prop.name ] = { prev: prevProp }; - } - - ret = this.applyParsedProperty( ele, prop ) || ret; - - if( updateTransitions ){ - diffProp.next = ele.pstyle( prop.name ); - } - - } // for props - - if( ret ){ - this.updateStyleHints( ele ); - } - - if( updateTransitions ){ - this.updateTransitions( ele, diffProps, isBypass ); - } - } // for eles - - return ret; -}; - -// only useful in specific cases like animation -styfn.overrideBypass = function( eles, name, value ){ - name = util.camel2dash( name ); - - for( var i = 0; i < eles.length; i++ ){ - var ele = eles[ i ]; - var prop = ele._private.style[ name ]; - var type = this.properties[ name ].type; - var isColor = type.color; - var isMulti = type.mutiple; - - if( !prop || !prop.bypass ){ // need a bypass if one doesn't exist - this.applyBypass( ele, name, value ); - continue; - } - - prop.value = value; - - if( prop.pfValue != null ){ - prop.pfValue = value; - } - - if( isColor ){ - prop.strValue = 'rgb(' + value.join( ',' ) + ')'; - } else if( isMulti ){ - prop.strValue = value.join( ' ' ); - } else { - prop.strValue = '' + value; - } - } -}; - -styfn.removeAllBypasses = function( eles, updateTransitions ){ - return this.removeBypasses( eles, this.propertyNames, updateTransitions ); -}; - -styfn.removeBypasses = function( eles, props, updateTransitions ){ - var isBypass = true; - - for( var j = 0; j < eles.length; j++ ){ - var ele = eles[ j ]; - var diffProps = {}; - - for( var i = 0; i < props.length; i++ ){ - var name = props[ i ]; - var prop = this.properties[ name ]; - var prevProp = ele.pstyle( prop.name ); - - if( !prevProp || !prevProp.bypass ){ - // if a bypass doesn't exist for the prop, nothing needs to be removed - continue; - } - - var value = ''; // empty => remove bypass - var parsedProp = this.parse( name, value, true ); - var diffProp = diffProps[ prop.name ] = { prev: prevProp }; - - this.applyParsedProperty( ele, parsedProp ); - - diffProp.next = ele.pstyle( prop.name ); - } // for props - - this.updateStyleHints( ele ); - - if( updateTransitions ){ - this.updateTransitions( ele, diffProps, isBypass ); - } - } // for eles -}; - -module.exports = styfn; - -},{"../is":83,"../util":100}],90:[function(_dereq_,module,exports){ -'use strict'; - -var window = _dereq_( '../window' ); - -var styfn = {}; - -// gets what an em size corresponds to in pixels relative to a dom element -styfn.getEmSizeInPixels = function(){ - var px = this.containerCss( 'font-size' ); - - if( px != null ){ - return parseFloat( px ); - } else { - return 1; // for headless - } -}; - -// gets css property from the core container -styfn.containerCss = function( propName ){ - var cy = this._private.cy; - var domElement = cy.container(); - - if( window && domElement && window.getComputedStyle ){ - return window.getComputedStyle( domElement ).getPropertyValue( propName ); - } -}; - -module.exports = styfn; - -},{"../window":107}],91:[function(_dereq_,module,exports){ -'use strict'; - -var util = _dereq_( '../util' ); -var is = _dereq_( '../is' ); - -var styfn = {}; - -// gets the rendered style for an element -styfn.getRenderedStyle = function( ele ){ - return this.getRawStyle( ele, true ); -}; - -// gets the raw style for an element -styfn.getRawStyle = function( ele, isRenderedVal ){ - var self = this; - var ele = ele[0]; // insure it's an element - - if( ele ){ - var rstyle = {}; - - for( var i = 0; i < self.properties.length; i++ ){ - var prop = self.properties[ i ]; - var val = self.getStylePropertyValue( ele, prop.name, isRenderedVal ); - - if( val ){ - rstyle[ prop.name ] = val; - rstyle[ util.dash2camel( prop.name ) ] = val; - } - } - - return rstyle; - } -}; - -styfn.getStylePropertyValue = function( ele, propName, isRenderedVal ){ - var self = this; - var ele = ele[0]; // insure it's an element - - if( ele ){ - var prop = self.properties[ propName ]; - var type = prop.type; - var styleProp = ele.pstyle( prop.name ); - var zoom = ele.cy().zoom(); - - if( styleProp ){ - var units = styleProp.units ? type.implicitUnits || 'px' : null; - var val = units ? [].concat( styleProp.pfValue ).map( function( pfValue ){ - return ( pfValue * (isRenderedVal ? zoom : 1) ) + units; - } ).join( ' ' ) : styleProp.strValue; - - return val; - } - } -}; - -styfn.getAnimationStartStyle = function( ele, aniProps ){ - var rstyle = {}; - - for( var i = 0; i < aniProps.length; i++ ){ - var aniProp = aniProps[ i ]; - var name = aniProp.name; - - var styleProp = ele.pstyle( name ); - - if( styleProp !== undefined ){ // then make a prop of it - if( is.plainObject( styleProp ) ){ - styleProp = this.parse( name, styleProp.strValue ); - } else { - styleProp = this.parse( name, styleProp ); - } - } - - if( styleProp ){ - rstyle[ name ] = styleProp; - } - } - - return rstyle; -}; - -styfn.getPropsList = function( propsObj ){ - var self = this; - var rstyle = []; - var style = propsObj; - var props = self.properties; - - if( style ){ - var names = Object.keys( style ); - - for( var i = 0; i < names.length; i++ ){ - var name = names[i]; - var val = style[ name ]; - var prop = props[ name ] || props[ util.camel2dash( name ) ]; - var styleProp = this.parse( prop.name, val ); - - rstyle.push( styleProp ); - } - } - - return rstyle; -}; - -module.exports = styfn; - -},{"../is":83,"../util":100}],92:[function(_dereq_,module,exports){ -'use strict'; - -var is = _dereq_( '../is' ); -var util = _dereq_( '../util' ); -var Selector = _dereq_( '../selector' ); - -var Style = function( cy ){ - - if( !(this instanceof Style) ){ - return new Style( cy ); - } - - if( !is.core( cy ) ){ - util.error( 'A style must have a core reference' ); - return; - } - - this._private = { - cy: cy, - coreStyle: {} - }; - - this.length = 0; - - this.resetToDefault(); -}; - -var styfn = Style.prototype; - -styfn.instanceString = function(){ - return 'style'; -}; - -// remove all contexts -styfn.clear = function(){ - for( var i = 0; i < this.length; i++ ){ - this[ i ] = undefined; - } - this.length = 0; - - var _p = this._private; - - _p.newStyle = true; - - return this; // chaining -}; - -styfn.resetToDefault = function(){ - this.clear(); - this.addDefaultStylesheet(); - - return this; -}; - -// builds a style object for the 'core' selector -styfn.core = function(){ - return this._private.coreStyle; -}; - -// create a new context from the specified selector string and switch to that context -styfn.selector = function( selectorStr ){ - // 'core' is a special case and does not need a selector - var selector = selectorStr === 'core' ? null : new Selector( selectorStr ); - - var i = this.length++; // new context means new index - this[ i ] = { - selector: selector, - properties: [], - mappedProperties: [], - index: i - }; - - return this; // chaining -}; - -// add one or many css rules to the current context -styfn.css = function(){ - var self = this; - var args = arguments; - - switch( args.length ){ - case 1: - var map = args[0]; - - for( var i = 0; i < self.properties.length; i++ ){ - var prop = self.properties[ i ]; - var mapVal = map[ prop.name ]; - - if( mapVal === undefined ){ - mapVal = map[ util.dash2camel( prop.name ) ]; - } - - if( mapVal !== undefined ){ - this.cssRule( prop.name, mapVal ); - } - } - - break; - - case 2: - this.cssRule( args[0], args[1] ); - break; - - default: - break; // do nothing if args are invalid - } - - return this; // chaining -}; -styfn.style = styfn.css; - -// add a single css rule to the current context -styfn.cssRule = function( name, value ){ - // name-value pair - var property = this.parse( name, value ); - - // add property to current context if valid - if( property ){ - var i = this.length - 1; - this[ i ].properties.push( property ); - this[ i ].properties[ property.name ] = property; // allow access by name as well - - if( property.name.match( /pie-(\d+)-background-size/ ) && property.value ){ - this._private.hasPie = true; - } - - if( property.mapped ){ - this[ i ].mappedProperties.push( property ); - } - - // add to core style if necessary - var currentSelectorIsCore = !this[ i ].selector; - if( currentSelectorIsCore ){ - this._private.coreStyle[ property.name ] = property; - } - } - - return this; // chaining -}; - -// static function -Style.fromJson = function( cy, json ){ - var style = new Style( cy ); - - style.fromJson( json ); - - return style; -}; - -Style.fromString = function( cy, string ){ - return new Style( cy ).fromString( string ); -}; - -[ - _dereq_( './apply' ), - _dereq_( './bypass' ), - _dereq_( './container' ), - _dereq_( './get-for-ele' ), - _dereq_( './json' ), - _dereq_( './string-sheet' ), - _dereq_( './properties' ), - _dereq_( './parse' ) -].forEach( function( props ){ - util.extend( styfn, props ); -} ); - - -Style.types = styfn.types; -Style.properties = styfn.properties; - -module.exports = Style; - -},{"../is":83,"../selector":87,"../util":100,"./apply":88,"./bypass":89,"./container":90,"./get-for-ele":91,"./json":93,"./parse":94,"./properties":95,"./string-sheet":96}],93:[function(_dereq_,module,exports){ -'use strict'; - -var styfn = {}; - -styfn.applyFromJson = function( json ){ - var style = this; - - for( var i = 0; i < json.length; i++ ){ - var context = json[ i ]; - var selector = context.selector; - var props = context.style || context.css; - var names = Object.keys( props ); - - style.selector( selector ); // apply selector - - for( var j = 0; j < names.length; j++ ){ - var name = names[j]; - var value = props[ name ]; - - style.css( name, value ); // apply property - } - } - - return style; -}; - -// accessible cy.style() function -styfn.fromJson = function( json ){ - var style = this; - - style.resetToDefault(); - style.applyFromJson( json ); - - return style; -}; - -// get json from cy.style() api -styfn.json = function(){ - var json = []; - - for( var i = this.defaultLength; i < this.length; i++ ){ - var cxt = this[ i ]; - var selector = cxt.selector; - var props = cxt.properties; - var css = {}; - - for( var j = 0; j < props.length; j++ ){ - var prop = props[ j ]; - css[ prop.name ] = prop.strValue; - } - - json.push( { - selector: !selector ? 'core' : selector.toString(), - style: css - } ); - } - - return json; -}; - -module.exports = styfn; - -},{}],94:[function(_dereq_,module,exports){ -'use strict'; - -var util = _dereq_( '../util' ); -var is = _dereq_( '../is' ); -var math = _dereq_( '../math' ); - -var styfn = {}; - -// a caching layer for property parsing -styfn.parse = function( name, value, propIsBypass, propIsFlat ){ - var self = this; - - // function values can't be cached in all cases, and there isn't much benefit of caching them anyway - if( is.fn( value ) ){ - return self.parseImpl( name, value, propIsBypass, propIsFlat ); - } - - var argHash = [ name, value, propIsBypass, propIsFlat ].join( '$' ); - var propCache = self.propCache = self.propCache || {}; - var ret; - - if( !(ret = propCache[ argHash ]) ){ - ret = propCache[ argHash ] = self.parseImpl( name, value, propIsBypass, propIsFlat ); - } - - // always need a copy since props are mutated later in their lifecycles - ret = util.copy( ret ); - - if( ret ){ - ret.value = util.copy( ret.value ); // because it could be an array, e.g. colour - } - - return ret; -}; - -// parse a property; return null on invalid; return parsed property otherwise -// fields : -// - name : the name of the property -// - value : the parsed, native-typed value of the property -// - strValue : a string value that represents the property value in valid css -// - bypass : true iff the property is a bypass property -var parseImpl = function( name, value, propIsBypass, propIsFlat ){ - var self = this; - - name = util.camel2dash( name ); // make sure the property name is in dash form (e.g. 'property-name' not 'propertyName') - - var property = self.properties[ name ]; - var passedValue = value; - var types = self.types; - - if( !property ){ return null; } // return null on property of unknown name - if( value === undefined || value === null ){ return null; } // can't assign null - - // the property may be an alias - if( property.alias ){ - property = property.pointsTo; - name = property.name; - } - - var valueIsString = is.string( value ); - if( valueIsString ){ // trim the value to make parsing easier - value = value.trim(); - } - - var type = property.type; - if( !type ){ return null; } // no type, no luck - - // check if bypass is null or empty string (i.e. indication to delete bypass property) - if( propIsBypass && (value === '' || value === null) ){ - return { - name: name, - value: value, - bypass: true, - deleteBypass: true - }; - } - - // check if value is a function used as a mapper - if( is.fn( value ) ){ - return { - name: name, - value: value, - strValue: 'fn', - mapped: types.fn, - bypass: propIsBypass - }; - } - - // check if value is mapped - var data, mapData, layoutData, mapLayoutData, scratch, mapScratch; - if( !valueIsString || propIsFlat ){ - // then don't bother to do the expensive regex checks - - } else if( - ( data = new RegExp( types.data.regex ).exec( value ) ) || - ( layoutData = new RegExp( types.layoutData.regex ).exec( value ) ) || - ( scratch = new RegExp( types.scratch.regex ).exec( value ) ) - ){ - if( propIsBypass ){ return false; } // mappers not allowed in bypass - - var mapped; - if( data ){ - mapped = types.data; - } else if( layoutData ){ - mapped = types.layoutData; - } else { - mapped = types.scratch; - } - - data = data || layoutData || scratch; - - return { - name: name, - value: data, - strValue: '' + value, - mapped: mapped, - field: data[1], - bypass: propIsBypass - }; - - } else if( - ( mapData = new RegExp( types.mapData.regex ).exec( value ) ) || - ( mapLayoutData = new RegExp( types.mapLayoutData.regex ).exec( value ) ) || - ( mapScratch = new RegExp( types.mapScratch.regex ).exec( value ) ) - ){ - if( propIsBypass ){ return false; } // mappers not allowed in bypass - if( type.multiple ){ return false; } // impossible to map to num - - var mapped; - if( mapData ){ - mapped = types.mapData; - } else if( mapLayoutData ){ - mapped = types.mapLayoutData; - } else { - mapped = types.mapScratch; - } - - mapData = mapData || mapLayoutData || mapScratch; - - // we can map only if the type is a colour or a number - if( !(type.color || type.number) ){ return false; } - - var valueMin = this.parse( name, mapData[4] ); // parse to validate - if( !valueMin || valueMin.mapped ){ return false; } // can't be invalid or mapped - - var valueMax = this.parse( name, mapData[5] ); // parse to validate - if( !valueMax || valueMax.mapped ){ return false; } // can't be invalid or mapped - - // check if valueMin and valueMax are the same - if( valueMin.value === valueMax.value ){ - return false; // can't make much of a mapper without a range - - } else if( type.color ){ - var c1 = valueMin.value; - var c2 = valueMax.value; - - var same = c1[0] === c2[0] // red - && c1[1] === c2[1] // green - && c1[2] === c2[2] // blue - && ( // optional alpha - c1[3] === c2[3] // same alpha outright - || ( - (c1[3] == null || c1[3] === 1) // full opacity for colour 1? - && - (c2[3] == null || c2[3] === 1) // full opacity for colour 2? - ) - ) - ; - - if( same ){ return false; } // can't make a mapper without a range - } - - return { - name: name, - value: mapData, - strValue: '' + value, - mapped: mapped, - field: mapData[1], - fieldMin: parseFloat( mapData[2] ), // min & max are numeric - fieldMax: parseFloat( mapData[3] ), - valueMin: valueMin.value, - valueMax: valueMax.value, - bypass: propIsBypass - }; - } - - if( type.multiple && propIsFlat !== 'multiple' ){ - var vals; - - if( valueIsString ){ - vals = value.split( /\s+/ ); - } else if( is.array( value ) ){ - vals = value; - } else { - vals = [ value ]; - } - - if( type.evenMultiple && vals.length % 2 !== 0 ){ return null; } - - var valArr = vals.map( function( v ){ - var p = self.parse( name, v, propIsBypass, 'multiple' ); - - if( p.pfValue != null ){ - return p.pfValue; - } else { - return p.value; - } - } ); - - return { - name: name, - value: valArr, - pfValue: valArr, - strValue: valArr.join( ' ' ), - bypass: propIsBypass, - units: type.number && !type.unitless ? type.implicitUnits || 'px' : undefined - }; - } - - // several types also allow enums - var checkEnums = function(){ - for( var i = 0; i < type.enums.length; i++ ){ - var en = type.enums[ i ]; - - if( en === value ){ - return { - name: name, - value: value, - strValue: '' + value, - bypass: propIsBypass - }; - } - } - - return null; - }; - - // check the type and return the appropriate object - if( type.number ){ - var units; - var implicitUnits = 'px'; // not set => px - - if( type.units ){ // use specified units if set - units = type.units; - } - - if( type.implicitUnits ){ - implicitUnits = type.implicitUnits; - } - - if( !type.unitless ){ - if( valueIsString ){ - var unitsRegex = 'px|em' + (type.allowPercent ? '|\\%' : ''); - if( units ){ unitsRegex = units; } // only allow explicit units if so set - var match = value.match( '^(' + util.regex.number + ')(' + unitsRegex + ')?' + '$' ); - - if( match ){ - value = match[1]; - units = match[2] || implicitUnits; - } - - } else if( !units || type.implicitUnits ){ - units = implicitUnits; // implicitly px if unspecified - } - } - - value = parseFloat( value ); - - // if not a number and enums not allowed, then the value is invalid - if( isNaN( value ) && type.enums === undefined ){ - return null; - } - - // check if this number type also accepts special keywords in place of numbers - // (i.e. `left`, `auto`, etc) - if( isNaN( value ) && type.enums !== undefined ){ - value = passedValue; - - return checkEnums(); - } - - // check if value must be an integer - if( type.integer && !is.integer( value ) ){ - return null; - } - - // check value is within range - if( (type.min !== undefined && value < type.min) - || (type.max !== undefined && value > type.max) - ){ - return null; - } - - var ret = { - name: name, - value: value, - strValue: '' + value + (units ? units : ''), - units: units, - bypass: propIsBypass - }; - - // normalise value in pixels - if( type.unitless || (units !== 'px' && units !== 'em') ){ - ret.pfValue = value; - } else { - ret.pfValue = ( units === 'px' || !units ? (value) : (this.getEmSizeInPixels() * value) ); - } - - // normalise value in ms - if( units === 'ms' || units === 's' ){ - ret.pfValue = units === 'ms' ? value : 1000 * value; - } - - // normalise value in rad - if( units === 'deg' || units === 'rad' ){ - ret.pfValue = units === 'rad' ? value : math.deg2rad( value ); - } - - return ret; - - } else if( type.propList ){ - - var props = []; - var propsStr = '' + value; - - if( propsStr === 'none' ){ - // leave empty - - } else { // go over each prop - - var propsSplit = propsStr.split( ',' ); - for( var i = 0; i < propsSplit.length; i++ ){ - var propName = propsSplit[ i ].trim(); - - if( self.properties[ propName ] ){ - props.push( propName ); - } - } - - if( props.length === 0 ){ return null; } - } - - return { - name: name, - value: props, - strValue: props.length === 0 ? 'none' : props.join( ', ' ), - bypass: propIsBypass - }; - - } else if( type.color ){ - var tuple = util.color2tuple( value ); - - if( !tuple ){ return null; } - - return { - name: name, - value: tuple, - strValue: '' + value, - bypass: propIsBypass, - roundValue: true - }; - - } else if( type.regex || type.regexes ){ - - // first check enums - if( type.enums ){ - var enumProp = checkEnums(); - - if( enumProp ){ return enumProp; } - } - - var regexes = type.regexes ? type.regexes : [ type.regex ]; - - for( var i = 0; i < regexes.length; i++ ){ - var regex = new RegExp( regexes[ i ] ); // make a regex from the type string - var m = regex.exec( value ); - - if( m ){ // regex matches - return { - name: name, - value: m, - strValue: '' + value, - bypass: propIsBypass - }; - - } - } - - return null; // didn't match any - - } else if( type.string ){ - // just return - return { - name: name, - value: value, - strValue: '' + value, - bypass: propIsBypass - }; - - } else if( type.enums ){ // check enums last because it's a combo type in others - return checkEnums(); - - } else { - return null; // not a type we can handle - } - -}; -styfn.parseImpl = parseImpl; - -module.exports = styfn; - -},{"../is":83,"../math":85,"../util":100}],95:[function(_dereq_,module,exports){ -'use strict'; - -var util = _dereq_( '../util' ); - -var styfn = {}; - -(function(){ - var number = util.regex.number; - var rgba = util.regex.rgbaNoBackRefs; - var hsla = util.regex.hslaNoBackRefs; - var hex3 = util.regex.hex3; - var hex6 = util.regex.hex6; - var data = function( prefix ){ return '^' + prefix + '\\s*\\(\\s*([\\w\\.]+)\\s*\\)$'; }; - var mapData = function( prefix ){ - var mapArg = number + '|\\w+|' + rgba + '|' + hsla + '|' + hex3 + '|' + hex6; - return '^' + prefix + '\\s*\\(([\\w\\.]+)\\s*\\,\\s*(' + number + ')\\s*\\,\\s*(' + number + ')\\s*,\\s*(' + mapArg + ')\\s*\\,\\s*(' + mapArg + ')\\)$'; - }; - - // each visual style property has a type and needs to be validated according to it - styfn.types = { - time: { number: true, min: 0, units: 's|ms', implicitUnits: 'ms' }, - percent: { number: true, min: 0, max: 100, units: '%', implicitUnits: '%' }, - zeroOneNumber: { number: true, min: 0, max: 1, unitless: true }, - nOneOneNumber: { number: true, min: -1, max: 1, unitless: true }, - nonNegativeInt: { number: true, min: 0, integer: true, unitless: true }, - position: { enums: [ 'parent', 'origin' ] }, - nodeSize: { number: true, min: 0, enums: [ 'label' ] }, - number: { number: true, unitless: true }, - numbers: { number: true, unitless: true, multiple: true }, - size: { number: true, min: 0 }, - bidirectionalSize: { number: true }, // allows negative - bidirectionalSizes: { number: true, multiple: true }, // allows negative - bgSize: { number: true, min: 0, allowPercent: true }, - bgWH: { number: true, min: 0, allowPercent: true, enums: [ 'auto' ] }, - bgPos: { number: true, allowPercent: true }, - bgRepeat: { enums: [ 'repeat', 'repeat-x', 'repeat-y', 'no-repeat' ] }, - bgFit: { enums: [ 'none', 'contain', 'cover' ] }, - bgClip: { enums: [ 'none', 'node' ] }, - color: { color: true }, - bool: { enums: [ 'yes', 'no' ] }, - lineStyle: { enums: [ 'solid', 'dotted', 'dashed' ] }, - borderStyle: { enums: [ 'solid', 'dotted', 'dashed', 'double' ] }, - curveStyle: { enums: [ 'bezier', 'unbundled-bezier', 'haystack', 'segments' ] }, - fontFamily: { regex: '^([\\w- \\"]+(?:\\s*,\\s*[\\w- \\"]+)*)$' }, - fontVariant: { enums: [ 'small-caps', 'normal' ] }, - fontStyle: { enums: [ 'italic', 'normal', 'oblique' ] }, - fontWeight: { enums: [ 'normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '800', '900', 100, 200, 300, 400, 500, 600, 700, 800, 900 ] }, - textDecoration: { enums: [ 'none', 'underline', 'overline', 'line-through' ] }, - textTransform: { enums: [ 'none', 'uppercase', 'lowercase' ] }, - textWrap: { enums: [ 'none', 'wrap' ] }, - textBackgroundShape: { enums: [ 'rectangle', 'roundrectangle' ]}, - nodeShape: { enums: [ 'rectangle', 'roundrectangle', 'ellipse', 'triangle', 'square', 'pentagon', 'hexagon', 'heptagon', 'octagon', 'star', 'diamond', 'vee', 'rhomboid', 'polygon' ] }, - compoundIncludeLabels: { enums: [ 'include', 'exclude' ] }, - arrowShape: { enums: [ 'tee', 'triangle', 'triangle-tee', 'triangle-backcurve', 'half-triangle-overshot', 'vee', 'square', 'circle', 'diamond', 'none' ] }, - arrowFill: { enums: [ 'filled', 'hollow' ] }, - display: { enums: [ 'element', 'none' ] }, - visibility: { enums: [ 'hidden', 'visible' ] }, - valign: { enums: [ 'top', 'center', 'bottom' ] }, - halign: { enums: [ 'left', 'center', 'right' ] }, - text: { string: true }, - data: { mapping: true, regex: data( 'data' ) }, - layoutData: { mapping: true, regex: data( 'layoutData' ) }, - scratch: { mapping: true, regex: data( 'scratch' ) }, - mapData: { mapping: true, regex: mapData( 'mapData' ) }, - mapLayoutData: { mapping: true, regex: mapData( 'mapLayoutData' ) }, - mapScratch: { mapping: true, regex: mapData( 'mapScratch' ) }, - fn: { mapping: true, fn: true }, - url: { regex: '^url\\s*\\(\\s*([^\\s]+)\\s*\\s*\\)|none|(.+)$' }, - propList: { propList: true }, - angle: { number: true, units: 'deg|rad', implicitUnits: 'rad' }, - textRotation: { number: true, units: 'deg|rad', implicitUnits: 'rad', enums: [ 'none', 'autorotate' ] }, - polygonPointList: { number: true, multiple: true, evenMultiple: true, min: -1, max: 1, unitless: true }, - edgeDistances: { enums: ['intersection', 'node-position'] }, - easing: { - regexes: [ - '^(spring)\\s*\\(\\s*(' + number + ')\\s*,\\s*(' + number + ')\\s*\\)$', - '^(cubic-bezier)\\s*\\(\\s*(' + number + ')\\s*,\\s*(' + number + ')\\s*,\\s*(' + number + ')\\s*,\\s*(' + number + ')\\s*\\)$' - ], - enums: [ - 'linear', - 'ease', 'ease-in', 'ease-out', 'ease-in-out', - 'ease-in-sine', 'ease-out-sine', 'ease-in-out-sine', - 'ease-in-quad', 'ease-out-quad', 'ease-in-out-quad', - 'ease-in-cubic', 'ease-out-cubic', 'ease-in-out-cubic', - 'ease-in-quart', 'ease-out-quart', 'ease-in-out-quart', - 'ease-in-quint', 'ease-out-quint', 'ease-in-out-quint', - 'ease-in-expo', 'ease-out-expo', 'ease-in-out-expo', - 'ease-in-circ', 'ease-out-circ', 'ease-in-out-circ' - ] - } - }; - - // define visual style properties - var t = styfn.types; - var props = styfn.properties = [ - // main label - { name: 'label', type: t.text }, - { name: 'text-rotation', type: t.textRotation }, - { name: 'text-margin-x', type: t.bidirectionalSize }, - { name: 'text-margin-y', type: t.bidirectionalSize }, - - // source label - { name: 'source-label', type: t.text }, - { name: 'source-text-rotation', type: t.textRotation }, - { name: 'source-text-margin-x', type: t.bidirectionalSize }, - { name: 'source-text-margin-y', type: t.bidirectionalSize }, - { name: 'source-text-offset', type: t.size }, - - // target label - { name: 'target-label', type: t.text }, - { name: 'target-text-rotation', type: t.textRotation }, - { name: 'target-text-margin-x', type: t.bidirectionalSize }, - { name: 'target-text-margin-y', type: t.bidirectionalSize }, - { name: 'target-text-offset', type: t.size }, - - // common label style - { name: 'text-valign', type: t.valign }, - { name: 'text-halign', type: t.halign }, - { name: 'color', type: t.color }, - { name: 'text-outline-color', type: t.color }, - { name: 'text-outline-width', type: t.size }, - { name: 'text-outline-opacity', type: t.zeroOneNumber }, - { name: 'text-opacity', type: t.zeroOneNumber }, - { name: 'text-background-color', type: t.color }, - { name: 'text-background-margin', type: t.size }, - { name: 'text-background-opacity', type: t.zeroOneNumber }, - { name: 'text-border-opacity', type: t.zeroOneNumber }, - { name: 'text-border-color', type: t.color }, - { name: 'text-border-width', type: t.size }, - { name: 'text-border-style', type: t.borderStyle }, - { name: 'text-background-shape', type: t.textBackgroundShape}, - // { name: 'text-decoration', type: t.textDecoration }, // not supported in canvas - { name: 'text-transform', type: t.textTransform }, - { name: 'text-wrap', type: t.textWrap }, - { name: 'text-max-width', type: t.size }, - { name: 'text-events', type: t.bool }, - { name: 'font-family', type: t.fontFamily }, - { name: 'font-style', type: t.fontStyle }, - // { name: 'font-variant', type: t.fontVariant }, // not useful - { name: 'font-weight', type: t.fontWeight }, - { name: 'font-size', type: t.size }, - { name: 'min-zoomed-font-size', type: t.size }, - - // behaviour - { name: 'events', type: t.bool }, - - // visibility - { name: 'display', type: t.display }, - { name: 'visibility', type: t.visibility }, - { name: 'opacity', type: t.zeroOneNumber }, - { name: 'z-index', type: t.nonNegativeInt }, - - // overlays - { name: 'overlay-padding', type: t.size }, - { name: 'overlay-color', type: t.color }, - { name: 'overlay-opacity', type: t.zeroOneNumber }, - - // shadows - { name: 'shadow-blur', type: t.size }, - { name: 'shadow-color', type: t.color }, - { name: 'shadow-opacity', type: t.zeroOneNumber }, - { name: 'shadow-offset-x', type: t.bidirectionalSize }, - { name: 'shadow-offset-y', type: t.bidirectionalSize }, - - // label shadows - { name: 'text-shadow-blur', type: t.size }, - { name: 'text-shadow-color', type: t.color }, - { name: 'text-shadow-opacity', type: t.zeroOneNumber }, - { name: 'text-shadow-offset-x', type: t.bidirectionalSize }, - { name: 'text-shadow-offset-y', type: t.bidirectionalSize }, - - // transition anis - { name: 'transition-property', type: t.propList }, - { name: 'transition-duration', type: t.time }, - { name: 'transition-delay', type: t.time }, - { name: 'transition-timing-function', type: t.easing }, - - // node body - { name: 'height', type: t.nodeSize }, - { name: 'width', type: t.nodeSize }, - { name: 'shape', type: t.nodeShape }, - { name: 'shape-polygon-points', type: t.polygonPointList }, - { name: 'background-color', type: t.color }, - { name: 'background-opacity', type: t.zeroOneNumber }, - { name: 'background-blacken', type: t.nOneOneNumber }, - { name: 'padding-left', type: t.size }, - { name: 'padding-right', type: t.size }, - { name: 'padding-top', type: t.size }, - { name: 'padding-bottom', type: t.size }, - - // node border - { name: 'border-color', type: t.color }, - { name: 'border-opacity', type: t.zeroOneNumber }, - { name: 'border-width', type: t.size }, - { name: 'border-style', type: t.borderStyle }, - - // node background images - { name: 'background-image', type: t.url }, - { name: 'background-image-opacity', type: t.zeroOneNumber }, - { name: 'background-position-x', type: t.bgPos }, - { name: 'background-position-y', type: t.bgPos }, - { name: 'background-repeat', type: t.bgRepeat }, - { name: 'background-fit', type: t.bgFit }, - { name: 'background-clip', type: t.bgClip }, - { name: 'background-width', type: t.bgWH }, - { name: 'background-height', type: t.bgWH }, - - // compound props - { name: 'position', type: t.position }, - { name: 'compound-sizing-wrt-labels', type: t.compoundIncludeLabels }, - - // edge line - { name: 'line-style', type: t.lineStyle }, - { name: 'line-color', type: t.color }, - { name: 'curve-style', type: t.curveStyle }, - { name: 'haystack-radius', type: t.zeroOneNumber }, - { name: 'control-point-step-size', type: t.size }, - { name: 'control-point-distances', type: t.bidirectionalSizes }, - { name: 'control-point-weights', type: t.numbers }, - { name: 'segment-distances', type: t.bidirectionalSizes }, - { name: 'segment-weights', type: t.numbers }, - { name: 'edge-distances', type: t.edgeDistances }, - - // these are just for the core - { name: 'selection-box-color', type: t.color }, - { name: 'selection-box-opacity', type: t.zeroOneNumber }, - { name: 'selection-box-border-color', type: t.color }, - { name: 'selection-box-border-width', type: t.size }, - { name: 'active-bg-color', type: t.color }, - { name: 'active-bg-opacity', type: t.zeroOneNumber }, - { name: 'active-bg-size', type: t.size }, - { name: 'outside-texture-bg-color', type: t.color }, - { name: 'outside-texture-bg-opacity', type: t.zeroOneNumber } - ]; - - // define aliases - var aliases = styfn.aliases = [ - { name: 'content', pointsTo: 'label' }, - { name: 'control-point-distance', pointsTo: 'control-point-distances' }, - { name: 'control-point-weight', pointsTo: 'control-point-weights' }, - { name: 'edge-text-rotation', pointsTo: 'text-rotation' } - ]; - - // pie backgrounds for nodes - styfn.pieBackgroundN = 16; // because the pie properties are numbered, give access to a constant N (for renderer use) - props.push( { name: 'pie-size', type: t.bgSize } ); - for( var i = 1; i <= styfn.pieBackgroundN; i++ ){ - props.push( { name: 'pie-' + i + '-background-color', type: t.color } ); - props.push( { name: 'pie-' + i + '-background-size', type: t.percent } ); - props.push( { name: 'pie-' + i + '-background-opacity', type: t.zeroOneNumber } ); - } - - // edge arrows - var arrowPrefixes = styfn.arrowPrefixes = [ 'source', 'mid-source', 'target', 'mid-target' ]; - [ - { name: 'arrow-shape', type: t.arrowShape }, - { name: 'arrow-color', type: t.color }, - { name: 'arrow-fill', type: t.arrowFill } - ].forEach( function( prop ){ - arrowPrefixes.forEach( function( prefix ){ - var name = prefix + '-' + prop.name; - var type = prop.type; - - props.push( { name: name, type: type } ); - } ); - }, {} ); - - // list of property names - styfn.propertyNames = props.map( function( p ){ return p.name; } ); - - // allow access of properties by name ( e.g. style.properties.height ) - for( var i = 0; i < props.length; i++ ){ - var prop = props[ i ]; - - props[ prop.name ] = prop; // allow lookup by name - } - - // map aliases - for( var i = 0; i < aliases.length; i++ ){ - var alias = aliases[ i ]; - var pointsToProp = props[ alias.pointsTo ]; - var aliasProp = { - name: alias.name, - alias: true, - pointsTo: pointsToProp - }; - - // add alias prop for parsing - props.push( aliasProp ); - - props[ alias.name ] = aliasProp; // allow lookup by name - } -})(); - -styfn.getDefaultProperty = function( name ){ - return this.getDefaultProperties()[ name ]; -}; - -styfn.getDefaultProperties = util.memoize( function(){ - var rawProps = util.extend( { - 'events': 'yes', - 'text-events': 'no', - 'text-valign': 'top', - 'text-halign': 'center', - 'color': '#000', - 'text-outline-color': '#000', - 'text-outline-width': 0, - 'text-outline-opacity': 1, - 'text-opacity': 1, - 'text-decoration': 'none', - 'text-transform': 'none', - 'text-wrap': 'none', - 'text-max-width': 9999, - 'text-background-color': '#000', - 'text-background-opacity': 0, - 'text-background-margin': 0, - 'text-border-opacity': 0, - 'text-border-width': 0, - 'text-border-style': 'solid', - 'text-border-color': '#000', - 'text-background-shape': 'rectangle', - 'font-family': 'Helvetica Neue, Helvetica, sans-serif', - 'font-style': 'normal', - // 'font-variant': fontVariant, - 'font-weight': 'normal', - 'font-size': 16, - 'min-zoomed-font-size': 0, - 'text-rotation': 'none', - 'source-text-rotation': 'none', - 'target-text-rotation': 'none', - 'visibility': 'visible', - 'display': 'element', - 'opacity': 1, - 'z-index': 0, - 'label': '', - 'text-margin-x': 0, - 'text-margin-y': 0, - 'source-label': '', - 'source-text-offset': 0, - 'source-text-margin-x': 0, - 'source-text-margin-y': 0, - 'target-label': '', - 'target-text-offset': 0, - 'target-text-margin-x': 0, - 'target-text-margin-y': 0, - 'overlay-opacity': 0, - 'overlay-color': '#000', - 'overlay-padding': 10, - 'shadow-opacity': 0, - 'shadow-color': '#000', - 'shadow-blur': 10, - 'shadow-offset-x': 0, - 'shadow-offset-y': 0, - 'text-shadow-opacity': 0, - 'text-shadow-color': '#000', - 'text-shadow-blur': 5, - 'text-shadow-offset-x': 0, - 'text-shadow-offset-y': 0, - 'transition-property': 'none', - 'transition-duration': 0, - 'transition-delay': 0, - 'transition-timing-function': 'linear', - - // node props - 'background-blacken': 0, - 'background-color': '#999', - 'background-opacity': 1, - 'background-image': 'none', - 'background-image-opacity': 1, - 'background-position-x': '50%', - 'background-position-y': '50%', - 'background-repeat': 'no-repeat', - 'background-fit': 'none', - 'background-clip': 'node', - 'background-width': 'auto', - 'background-height': 'auto', - 'border-color': '#000', - 'border-opacity': 1, - 'border-width': 0, - 'border-style': 'solid', - 'height': 30, - 'width': 30, - 'shape': 'ellipse', - 'shape-polygon-points': '-1, -1, 1, -1, 1, 1, -1, 1', - - // compound props - 'padding-top': 0, - 'padding-bottom': 0, - 'padding-left': 0, - 'padding-right': 0, - 'position': 'origin', - 'compound-sizing-wrt-labels': 'include' - }, { - // node pie bg - 'pie-size': '100%' - }, [ - { name: 'pie-{{i}}-background-color', value: 'black' }, - { name: 'pie-{{i}}-background-size', value: '0%' }, - { name: 'pie-{{i}}-background-opacity', value: 1 } - ].reduce( function( css, prop ){ - for( var i = 1; i <= styfn.pieBackgroundN; i++ ){ - var name = prop.name.replace( '{{i}}', i ); - var val = prop.value; - - css[ name ] = val; - } - - return css; - }, {} ), { - // edge props - 'line-style': 'solid', - 'line-color': '#999', - 'control-point-step-size': 40, - 'control-point-weights': 0.5, - 'segment-weights': 0.5, - 'segment-distances': 20, - 'edge-distances': 'intersection', - 'curve-style': 'bezier', - 'haystack-radius': 0 - }, [ - { name: 'arrow-shape', value: 'none' }, - { name: 'arrow-color', value: '#999' }, - { name: 'arrow-fill', value: 'filled' } - ].reduce( function( css, prop ){ - styfn.arrowPrefixes.forEach( function( prefix ){ - var name = prefix + '-' + prop.name; - var val = prop.value; - - css[ name ] = val; - } ); - - return css; - }, {} ) ); - - var parsedProps = {}; - - for( var i = 0; i < this.properties.length; i++ ){ - var prop = this.properties[i]; - - if( prop.pointsTo ){ continue; } - - var name = prop.name; - var val = rawProps[ name ]; - var parsedProp = this.parse( name, val ); - - parsedProps[ name ] = parsedProp; - } - - return parsedProps; -} ); - -styfn.addDefaultStylesheet = function(){ - this - .selector( '$node > node' ) // compound (parent) node properties - .css( { - 'shape': 'rectangle', - 'padding-top': 10, - 'padding-right': 10, - 'padding-left': 10, - 'padding-bottom': 10, - 'background-color': '#eee', - 'border-color': '#ccc', - 'border-width': 1 - } ) - .selector( 'edge' ) // just edge properties - .css( { - 'width': 3, - 'curve-style': 'haystack' - } ) - .selector( ':selected' ) - .css( { - 'background-color': '#0169D9', - 'line-color': '#0169D9', - 'source-arrow-color': '#0169D9', - 'target-arrow-color': '#0169D9', - 'mid-source-arrow-color': '#0169D9', - 'mid-target-arrow-color': '#0169D9' - } ) - .selector( 'node:parent:selected' ) - .css( { - 'background-color': '#CCE1F9', - 'border-color': '#aec8e5' - } ) - .selector( ':active' ) - .css( { - 'overlay-color': 'black', - 'overlay-padding': 10, - 'overlay-opacity': 0.25 - } ) - .selector( 'core' ) // just core properties - .css( { - 'selection-box-color': '#ddd', - 'selection-box-opacity': 0.65, - 'selection-box-border-color': '#aaa', - 'selection-box-border-width': 1, - 'active-bg-color': 'black', - 'active-bg-opacity': 0.15, - 'active-bg-size': 30, - 'outside-texture-bg-color': '#000', - 'outside-texture-bg-opacity': 0.125 - } ) - ; - - this.defaultLength = this.length; -}; - -module.exports = styfn; - -},{"../util":100}],96:[function(_dereq_,module,exports){ -'use strict'; - -var util = _dereq_( '../util' ); -var Selector = _dereq_( '../selector' ); - -var styfn = {}; - -styfn.applyFromString = function( string ){ - var self = this; - var style = this; - var remaining = '' + string; - var selAndBlockStr; - var blockRem; - var propAndValStr; - - // remove comments from the style string - remaining = remaining.replace( /[/][*](\s|.)+?[*][/]/g, '' ); - - function removeSelAndBlockFromRemaining(){ - // remove the parsed selector and block from the remaining text to parse - if( remaining.length > selAndBlockStr.length ){ - remaining = remaining.substr( selAndBlockStr.length ); - } else { - remaining = ''; - } - } - - function removePropAndValFromRem(){ - // remove the parsed property and value from the remaining block text to parse - if( blockRem.length > propAndValStr.length ){ - blockRem = blockRem.substr( propAndValStr.length ); - } else { - blockRem = ''; - } - } - - while( true ){ - var nothingLeftToParse = remaining.match( /^\s*$/ ); - if( nothingLeftToParse ){ break; } - - var selAndBlock = remaining.match( /^\s*((?:.|\s)+?)\s*\{((?:.|\s)+?)\}/ ); - - if( !selAndBlock ){ - util.error( 'Halting stylesheet parsing: String stylesheet contains more to parse but no selector and block found in: ' + remaining ); - break; - } - - selAndBlockStr = selAndBlock[0]; - - // parse the selector - var selectorStr = selAndBlock[1]; - if( selectorStr !== 'core' ){ - var selector = new Selector( selectorStr ); - if( selector._private.invalid ){ - util.error( 'Skipping parsing of block: Invalid selector found in string stylesheet: ' + selectorStr ); - - // skip this selector and block - removeSelAndBlockFromRemaining(); - continue; - } - } - - // parse the block of properties and values - var blockStr = selAndBlock[2]; - var invalidBlock = false; - blockRem = blockStr; - var props = []; - - while( true ){ - var nothingLeftToParse = blockRem.match( /^\s*$/ ); - if( nothingLeftToParse ){ break; } - - var propAndVal = blockRem.match( /^\s*(.+?)\s*:\s*(.+?)\s*;/ ); - - if( !propAndVal ){ - util.error( 'Skipping parsing of block: Invalid formatting of style property and value definitions found in:' + blockStr ); - invalidBlock = true; - break; - } - - propAndValStr = propAndVal[0]; - var propStr = propAndVal[1]; - var valStr = propAndVal[2]; - - var prop = self.properties[ propStr ]; - if( !prop ){ - util.error( 'Skipping property: Invalid property name in: ' + propAndValStr ); - - // skip this property in the block - removePropAndValFromRem(); - continue; - } - - var parsedProp = style.parse( propStr, valStr ); - - if( !parsedProp ){ - util.error( 'Skipping property: Invalid property definition in: ' + propAndValStr ); - - // skip this property in the block - removePropAndValFromRem(); - continue; - } - - props.push( { - name: propStr, - val: valStr - } ); - removePropAndValFromRem(); - } - - if( invalidBlock ){ - removeSelAndBlockFromRemaining(); - break; - } - - // put the parsed block in the style - style.selector( selectorStr ); - for( var i = 0; i < props.length; i++ ){ - var prop = props[ i ]; - style.css( prop.name, prop.val ); - } - - removeSelAndBlockFromRemaining(); - } - - return style; -}; - -styfn.fromString = function( string ){ - var style = this; - - style.resetToDefault(); - style.applyFromString( string ); - - return style; -}; - -module.exports = styfn; - -},{"../selector":87,"../util":100}],97:[function(_dereq_,module,exports){ -'use strict'; - -var is = _dereq_( './is' ); -var util = _dereq_( './util' ); -var Style = _dereq_( './style' ); +var is = __webpack_require__(0); +var util = __webpack_require__(1); +var Style = __webpack_require__(18); // a dummy stylesheet object that doesn't need a reference to the core // (useful for init) -var Stylesheet = function(){ - if( !(this instanceof Stylesheet) ){ +var Stylesheet = function Stylesheet() { + if (!(this instanceof Stylesheet)) { return new Stylesheet(); } @@ -25603,15 +29845,15 @@ var Stylesheet = function(){ var sheetfn = Stylesheet.prototype; -sheetfn.instanceString = function(){ +sheetfn.instanceString = function () { return 'stylesheet'; }; // just store the selector to be parsed later -sheetfn.selector = function( selector ){ +sheetfn.selector = function (selector) { var i = this.length++; - this[ i ] = { + this[i] = { selector: selector, properties: [] }; @@ -25620,33 +29862,34 @@ sheetfn.selector = function( selector ){ }; // just store the property to be parsed later -sheetfn.css = function( name, value ){ +sheetfn.css = function (name, value) { var i = this.length - 1; - if( is.string( name ) ){ - this[ i ].properties.push( { + if (is.string(name)) { + this[i].properties.push({ name: name, value: value - } ); - } else if( is.plainObject( name ) ){ + }); + } else if (is.plainObject(name)) { var map = name; - for( var j = 0; j < Style.properties.length; j++ ){ - var prop = Style.properties[ j ]; - var mapVal = map[ prop.name ]; + for (var j = 0; j < Style.properties.length; j++) { + var prop = Style.properties[j]; + var mapVal = map[prop.name]; - if( mapVal === undefined ){ // also try camel case name - mapVal = map[ util.dash2camel( prop.name ) ]; + if (mapVal === undefined) { + // also try camel case name + mapVal = map[util.dash2camel(prop.name)]; } - if( mapVal !== undefined ){ - var name = prop.name; - var value = mapVal; + if (mapVal !== undefined) { + var _name = prop.name; + var _value = mapVal; - this[ i ].properties.push( { - name: name, - value: value - } ); + this[i].properties.push({ + name: _name, + value: _value + }); } } } @@ -25657,20 +29900,25 @@ sheetfn.css = function( name, value ){ sheetfn.style = sheetfn.css; // generate a real style object from the dummy stylesheet -sheetfn.generateStyle = function( cy ){ - var style = new Style( cy ); +sheetfn.generateStyle = function (cy) { + var style = new Style(cy); - for( var i = 0; i < this.length; i++ ){ - var context = this[ i ]; + return this.appendToStyle(style); +}; + +// append a dummy stylesheet object on a real style object +sheetfn.appendToStyle = function (style) { + for (var i = 0; i < this.length; i++) { + var context = this[i]; var selector = context.selector; var props = context.properties; - style.selector( selector ); // apply selector + style.selector(selector); // apply selector - for( var j = 0; j < props.length; j++ ){ - var prop = props[ j ]; + for (var j = 0; j < props.length; j++) { + var prop = props[j]; - style.css( prop.name, prop.value ); // apply property + style.css(prop.name, prop.value); // apply property } } @@ -25679,1320 +29927,15 @@ sheetfn.generateStyle = function( cy ){ module.exports = Stylesheet; -},{"./is":83,"./style":92,"./util":100}],98:[function(_dereq_,module,exports){ -/*! Weaver licensed under MIT (https://tldrlegal.com/license/mit-license), copyright Max Franz */ +/***/ }), +/* 138 */ +/***/ (function(module, exports, __webpack_require__) { -// cross-env thread/worker -// NB : uses (heavyweight) processes on nodejs so best not to create too many threads +"use strict"; -'use strict'; -var window = _dereq_('./window'); -var util = _dereq_('./util'); -var Promise = _dereq_('./promise'); -var Event = _dereq_('./event'); -var define = _dereq_('./define'); -var is = _dereq_('./is'); - -var Thread = function( opts ){ - if( !(this instanceof Thread) ){ - return new Thread( opts ); - } - - var _p = this._private = { - requires: [], - files: [], - queue: null, - pass: [], - disabled: false - }; - - if( is.plainObject(opts) ){ - if( opts.disabled != null ){ - _p.disabled = !!opts.disabled; - } - } - -}; - -var thdfn = Thread.prototype; // short alias - -var stringifyFieldVal = function( val ){ - var valStr = is.fn( val ) ? val.toString() : "JSON.parse('" + JSON.stringify(val) + "')"; - - return valStr; -}; - -// allows for requires with prototypes and subobjs etc -var fnAsRequire = function( fn ){ - var req; - var fnName; - - if( is.object(fn) && fn.fn ){ // manual fn - req = fnAs( fn.fn, fn.name ); - fnName = fn.name; - fn = fn.fn; - } else if( is.fn(fn) ){ // auto fn - req = fn.toString(); - fnName = fn.name; - } else if( is.string(fn) ){ // stringified fn - req = fn; - } else if( is.object(fn) ){ // plain object - if( fn.proto ){ - req = ''; - } else { - req = fn.name + ' = {};'; - } - - fnName = fn.name; - fn = fn.obj; - } - - req += '\n'; - - var protoreq = function( val, subname ){ - if( val.prototype ){ - var protoNonempty = false; - for( var prop in val.prototype ){ protoNonempty = true; break; } // jshint ignore:line - - if( protoNonempty ){ - req += fnAsRequire( { - name: subname, - obj: val, - proto: true - }, val ); - } - } - }; - - // pull in prototype - if( fn.prototype && fnName != null ){ - - for( var name in fn.prototype ){ - var protoStr = ''; - - var val = fn.prototype[ name ]; - var valStr = stringifyFieldVal( val ); - var subname = fnName + '.prototype.' + name; - - protoStr += subname + ' = ' + valStr + ';\n'; - - if( protoStr ){ - req += protoStr; - } - - protoreq( val, subname ); // subobject with prototype - } - - } - - // pull in properties for obj/fns - if( !is.string(fn) ){ for( var name in fn ){ - var propsStr = ''; - - if( fn.hasOwnProperty(name) ){ - var val = fn[ name ]; - var valStr = stringifyFieldVal( val ); - var subname = fnName + '["' + name + '"]'; - - propsStr += subname + ' = ' + valStr + ';\n'; - } - - if( propsStr ){ - req += propsStr; - } - - protoreq( val, subname ); // subobject with prototype - } } - - return req; -}; - -var isPathStr = function( str ){ - return is.string(str) && str.match(/\.js$/); -}; - -util.extend(thdfn, { - - instanceString: function(){ return 'thread'; }, - - require: function( fn, as ){ - var requires = this._private.requires; - - if( isPathStr(fn) ){ - this._private.files.push( fn ); - - return this; - } - - if( as ){ - if( is.fn(fn) ){ - fn = { name: as, fn: fn }; - } else { - fn = { name: as, obj: fn }; - } - } else { - if( is.fn(fn) ){ - if( !fn.name ){ - throw 'The function name could not be automatically determined. Use thread.require( someFunction, "someFunction" )'; - } - - fn = { name: fn.name, fn: fn }; - } - } - - requires.push( fn ); - - return this; // chaining - }, - - pass: function( data ){ - this._private.pass.push( data ); - - return this; // chaining - }, - - run: function( fn, pass ){ // fn used like main() - var self = this; - var _p = this._private; - pass = pass || _p.pass.shift(); - - if( _p.stopped ){ - throw 'Attempted to run a stopped thread! Start a new thread or do not stop the existing thread and reuse it.'; - } - - if( _p.running ){ - return ( _p.queue = _p.queue.then(function(){ // inductive step - return self.run( fn, pass ); - }) ); - } - - var useWW = window != null && !_p.disabled; - var useNode = !window && typeof module !== 'undefined' && !_p.disabled; - - self.trigger('run'); - - var runP = new Promise(function( resolve, reject ){ - - _p.running = true; - - var threadTechAlreadyExists = _p.ran; - - var fnImplStr = is.string( fn ) ? fn : fn.toString(); - - // worker code to exec - var fnStr = '\n' + ( _p.requires.map(function( r ){ - return fnAsRequire( r ); - }) ).concat( _p.files.map(function( f ){ - if( useWW ){ - var wwifyFile = function( file ){ - if( file.match(/^\.\//) || file.match(/^\.\./) ){ - return window.location.origin + window.location.pathname + file; - } else if( file.match(/^\//) ){ - return window.location.origin + '/' + file; - } - return file; - }; - - return 'importScripts("' + wwifyFile(f) + '");'; - } else if( useNode ) { - return 'eval( require("fs").readFileSync("' + f + '", { encoding: "utf8" }) );'; - } else { - throw 'External file `' + f + '` can not be required without any threading technology.'; - } - }) ).concat([ - '( function(){', - 'var ret = (' + fnImplStr + ')(' + JSON.stringify(pass) + ');', - 'if( ret !== undefined ){ resolve(ret); }', // assume if ran fn returns defined value (incl. null), that we want to resolve to it - '} )()\n' - ]).join('\n'); - - // because we've now consumed the requires, empty the list so we don't dupe on next run() - _p.requires = []; - _p.files = []; - - if( useWW ){ - var fnBlob, fnUrl; - - // add normalised thread api functions - if( !threadTechAlreadyExists ){ - var fnPre = fnStr + ''; - - fnStr = [ - 'function _ref_(o){ return eval(o); };', - 'function broadcast(m){ return message(m); };', // alias - 'function message(m){ postMessage(m); };', - 'function listen(fn){', - ' self.addEventListener("message", function(m){ ', - ' if( typeof m === "object" && (m.data.$$eval || m.data === "$$start") ){', - ' } else { ', - ' fn( m.data );', - ' }', - ' });', - '};', - 'self.addEventListener("message", function(m){ if( m.data.$$eval ){ eval( m.data.$$eval ); } });', - 'function resolve(v){ postMessage({ $$resolve: v }); };', - 'function reject(v){ postMessage({ $$reject: v }); };' - ].join('\n'); - - fnStr += fnPre; - - fnBlob = new Blob([ fnStr ], { - type: 'application/javascript' - }); - fnUrl = window.URL.createObjectURL( fnBlob ); - } - // create webworker and let it exec the serialised code - var ww = _p.webworker = _p.webworker || new Worker( fnUrl ); - - if( threadTechAlreadyExists ){ // then just exec new run() code - ww.postMessage({ - $$eval: fnStr - }); - } - - // worker messages => events - var cb; - ww.addEventListener('message', cb = function( m ){ - var isObject = is.object(m) && is.object( m.data ); - - if( isObject && ('$$resolve' in m.data) ){ - ww.removeEventListener('message', cb); // done listening b/c resolve() - - resolve( m.data.$$resolve ); - } else if( isObject && ('$$reject' in m.data) ){ - ww.removeEventListener('message', cb); // done listening b/c reject() - - reject( m.data.$$reject ); - } else { - self.trigger( new Event(m, { type: 'message', message: m.data }) ); - } - }, false); - - if( !threadTechAlreadyExists ){ - ww.postMessage('$$start'); // start up the worker - } - - } else if( useNode ){ - // create a new process - - if( !_p.child ){ - _p.child = ( _dereq_('child_process').fork( _dereq_('path').join(__dirname, 'thread-node-fork') ) ); - } - - var child = _p.child; - - // child process messages => events - var cb; - child.on('message', cb = function( m ){ - if( is.object(m) && ('$$resolve' in m) ){ - child.removeListener('message', cb); // done listening b/c resolve() - - resolve( m.$$resolve ); - } else if( is.object(m) && ('$$reject' in m) ){ - child.removeListener('message', cb); // done listening b/c reject() - - reject( m.$$reject ); - } else { - self.trigger( new Event({}, { type: 'message', message: m }) ); - } - }); - - // ask the child process to eval the worker code - child.send({ - $$eval: fnStr - }); - - } else { // use a fallback mechanism using a timeout - - var promiseResolve = resolve; - var promiseReject = reject; - - var timer = _p.timer = _p.timer || { - - listeners: [], - - exec: function(){ - // as a string so it can't be mangled by minifiers and processors - fnStr = [ - 'function _ref_(o){ return eval(o); };', - 'function broadcast(m){ return message(m); };', - 'function message(m){ self.trigger( new Event({}, { type: "message", message: m }) ); };', - 'function listen(fn){ timer.listeners.push( fn ); };', - 'function resolve(v){ promiseResolve(v); };', - 'function reject(v){ promiseReject(v); };' - ].join('\n') + fnStr; - - // the .run() code - eval( fnStr ); // jshint ignore:line - }, - - message: function( m ){ - var ls = timer.listeners; - - for( var i = 0; i < ls.length; i++ ){ - var fn = ls[i]; - - fn( m ); - } - } - - }; - - timer.exec(); - } - - }).then(function( v ){ - _p.running = false; - _p.ran = true; - - self.trigger('ran'); - - return v; - }); - - if( _p.queue == null ){ - _p.queue = runP; // i.e. first step of inductive promise chain (for queue) - } - - return runP; - }, - - // send the thread a message - message: function( m ){ - var _p = this._private; - - if( _p.webworker ){ - _p.webworker.postMessage( m ); - } - - if( _p.child ){ - _p.child.send( m ); - } - - if( _p.timer ){ - _p.timer.message( m ); - } - - return this; // chaining - }, - - stop: function(){ - var _p = this._private; - - if( _p.webworker ){ - _p.webworker.terminate(); - } - - if( _p.child ){ - _p.child.kill(); - } - - if( _p.timer ){ - // nothing we can do if we've run a timeout - } - - _p.stopped = true; - - return this.trigger('stop'); // chaining - }, - - stopped: function(){ - return this._private.stopped; - } - -}); - -// turns a stringified function into a (re)named function -var fnAs = function( fn, name ){ - var fnStr = fn.toString(); - fnStr = fnStr.replace(/function\s*?\S*?\s*?\(/, 'function ' + name + '('); - - return fnStr; -}; - -var defineFnal = function( opts ){ - opts = opts || {}; - - return function fnalImpl( fn, arg1 ){ - var fnStr = fnAs( fn, '_$_$_' + opts.name ); - - this.require( fnStr ); - - return this.run( [ - 'function( data ){', - ' var origResolve = resolve;', - ' var res = [];', - ' ', - ' resolve = function( val ){', - ' res.push( val );', - ' };', - ' ', - ' var ret = data.' + opts.name + '( _$_$_' + opts.name + ( arguments.length > 1 ? ', ' + JSON.stringify(arg1) : '' ) + ' );', - ' ', - ' resolve = origResolve;', - ' resolve( res.length > 0 ? res : ret );', - '}' - ].join('\n') ); - }; -}; - -util.extend(thdfn, { - reduce: defineFnal({ name: 'reduce' }), - - reduceRight: defineFnal({ name: 'reduceRight' }), - - map: defineFnal({ name: 'map' }) -}); - -// aliases -var fn = thdfn; -fn.promise = fn.run; -fn.terminate = fn.halt = fn.stop; -fn.include = fn.require; - -// pull in event apis -util.extend(thdfn, { - on: define.on(), - one: define.on({ unbindSelfOnTrigger: true }), - off: define.off(), - trigger: define.trigger() -}); - -define.eventAliasesOn( thdfn ); - -module.exports = Thread; - -},{"./define":44,"./event":45,"./is":83,"./promise":86,"./util":100,"./window":107,"child_process":undefined,"path":undefined}],99:[function(_dereq_,module,exports){ -'use strict'; - -var is = _dereq_( '../is' ); - -module.exports = { - // get [r, g, b] from #abc or #aabbcc - hex2tuple: function( hex ){ - if( !(hex.length === 4 || hex.length === 7) || hex[0] !== '#' ){ return; } - - var shortHex = hex.length === 4; - var r, g, b; - var base = 16; - - if( shortHex ){ - r = parseInt( hex[1] + hex[1], base ); - g = parseInt( hex[2] + hex[2], base ); - b = parseInt( hex[3] + hex[3], base ); - } else { - r = parseInt( hex[1] + hex[2], base ); - g = parseInt( hex[3] + hex[4], base ); - b = parseInt( hex[5] + hex[6], base ); - } - - return [ r, g, b ]; - }, - - // get [r, g, b, a] from hsl(0, 0, 0) or hsla(0, 0, 0, 0) - hsl2tuple: function( hsl ){ - var ret; - var h, s, l, a, r, g, b; - function hue2rgb( p, q, t ){ - if( t < 0 ) t += 1; - if( t > 1 ) t -= 1; - if( t < 1 / 6 ) return p + (q - p) * 6 * t; - if( t < 1 / 2 ) return q; - if( t < 2 / 3 ) return p + (q - p) * (2 / 3 - t) * 6; - return p; - } - - var m = new RegExp( '^' + this.regex.hsla + '$' ).exec( hsl ); - if( m ){ - - // get hue - h = parseInt( m[1] ); - if( h < 0 ){ - h = ( 360 - (-1 * h % 360) ) % 360; - } else if( h > 360 ){ - h = h % 360; - } - h /= 360; // normalise on [0, 1] - - s = parseFloat( m[2] ); - if( s < 0 || s > 100 ){ return; } // saturation is [0, 100] - s = s / 100; // normalise on [0, 1] - - l = parseFloat( m[3] ); - if( l < 0 || l > 100 ){ return; } // lightness is [0, 100] - l = l / 100; // normalise on [0, 1] - - a = m[4]; - if( a !== undefined ){ - a = parseFloat( a ); - - if( a < 0 || a > 1 ){ return; } // alpha is [0, 1] - } - - // now, convert to rgb - // code from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript - if( s === 0 ){ - r = g = b = Math.round( l * 255 ); // achromatic - } else { - var q = l < 0.5 ? l * (1 + s) : l + s - l * s; - var p = 2 * l - q; - r = Math.round( 255 * hue2rgb( p, q, h + 1 / 3 ) ); - g = Math.round( 255 * hue2rgb( p, q, h ) ); - b = Math.round( 255 * hue2rgb( p, q, h - 1 / 3 ) ); - } - - ret = [ r, g, b, a ]; - } - - return ret; - }, - - // get [r, g, b, a] from rgb(0, 0, 0) or rgba(0, 0, 0, 0) - rgb2tuple: function( rgb ){ - var ret; - - var m = new RegExp( '^' + this.regex.rgba + '$' ).exec( rgb ); - if( m ){ - ret = []; - - var isPct = []; - for( var i = 1; i <= 3; i++ ){ - var channel = m[ i ]; - - if( channel[ channel.length - 1 ] === '%' ){ - isPct[ i ] = true; - } - channel = parseFloat( channel ); - - if( isPct[ i ] ){ - channel = channel / 100 * 255; // normalise to [0, 255] - } - - if( channel < 0 || channel > 255 ){ return; } // invalid channel value - - ret.push( Math.floor( channel ) ); - } - - var atLeastOneIsPct = isPct[1] || isPct[2] || isPct[3]; - var allArePct = isPct[1] && isPct[2] && isPct[3]; - if( atLeastOneIsPct && !allArePct ){ return; } // must all be percent values if one is - - var alpha = m[4]; - if( alpha !== undefined ){ - alpha = parseFloat( alpha ); - - if( alpha < 0 || alpha > 1 ){ return; } // invalid alpha value - - ret.push( alpha ); - } - } - - return ret; - }, - - colorname2tuple: function( color ){ - return this.colors[ color.toLowerCase() ]; - }, - - color2tuple: function( color ){ - return ( is.array( color ) ? color : null ) - || this.colorname2tuple( color ) - || this.hex2tuple( color ) - || this.rgb2tuple( color ) - || this.hsl2tuple( color ); - }, - - colors: { - // special colour names - transparent: [0, 0, 0, 0], // NB alpha === 0 - - // regular colours - aliceblue: [ 240, 248, 255 ], - antiquewhite: [ 250, 235, 215 ], - aqua: [0, 255, 255 ], - aquamarine: [ 127, 255, 212 ], - azure: [ 240, 255, 255 ], - beige: [ 245, 245, 220 ], - bisque: [ 255, 228, 196 ], - black: [0, 0, 0], - blanchedalmond: [ 255, 235, 205 ], - blue: [0, 0, 255 ], - blueviolet: [ 138, 43, 226 ], - brown: [ 165, 42, 42 ], - burlywood: [ 222, 184, 135 ], - cadetblue: [ 95, 158, 160 ], - chartreuse: [ 127, 255, 0], - chocolate: [ 210, 105, 30 ], - coral: [ 255, 127, 80 ], - cornflowerblue: [ 100, 149, 237 ], - cornsilk: [ 255, 248, 220 ], - crimson: [ 220, 20, 60 ], - cyan: [0, 255, 255 ], - darkblue: [0, 0, 139 ], - darkcyan: [0, 139, 139 ], - darkgoldenrod: [ 184, 134, 11 ], - darkgray: [ 169, 169, 169 ], - darkgreen: [0, 100, 0], - darkgrey: [ 169, 169, 169 ], - darkkhaki: [ 189, 183, 107 ], - darkmagenta: [ 139, 0, 139 ], - darkolivegreen: [ 85, 107, 47 ], - darkorange: [ 255, 140, 0], - darkorchid: [ 153, 50, 204 ], - darkred: [ 139, 0, 0], - darksalmon: [ 233, 150, 122 ], - darkseagreen: [ 143, 188, 143 ], - darkslateblue: [ 72, 61, 139 ], - darkslategray: [ 47, 79, 79 ], - darkslategrey: [ 47, 79, 79 ], - darkturquoise: [0, 206, 209 ], - darkviolet: [ 148, 0, 211 ], - deeppink: [ 255, 20, 147 ], - deepskyblue: [0, 191, 255 ], - dimgray: [ 105, 105, 105 ], - dimgrey: [ 105, 105, 105 ], - dodgerblue: [ 30, 144, 255 ], - firebrick: [ 178, 34, 34 ], - floralwhite: [ 255, 250, 240 ], - forestgreen: [ 34, 139, 34 ], - fuchsia: [ 255, 0, 255 ], - gainsboro: [ 220, 220, 220 ], - ghostwhite: [ 248, 248, 255 ], - gold: [ 255, 215, 0], - goldenrod: [ 218, 165, 32 ], - gray: [ 128, 128, 128 ], - grey: [ 128, 128, 128 ], - green: [0, 128, 0], - greenyellow: [ 173, 255, 47 ], - honeydew: [ 240, 255, 240 ], - hotpink: [ 255, 105, 180 ], - indianred: [ 205, 92, 92 ], - indigo: [ 75, 0, 130 ], - ivory: [ 255, 255, 240 ], - khaki: [ 240, 230, 140 ], - lavender: [ 230, 230, 250 ], - lavenderblush: [ 255, 240, 245 ], - lawngreen: [ 124, 252, 0], - lemonchiffon: [ 255, 250, 205 ], - lightblue: [ 173, 216, 230 ], - lightcoral: [ 240, 128, 128 ], - lightcyan: [ 224, 255, 255 ], - lightgoldenrodyellow: [ 250, 250, 210 ], - lightgray: [ 211, 211, 211 ], - lightgreen: [ 144, 238, 144 ], - lightgrey: [ 211, 211, 211 ], - lightpink: [ 255, 182, 193 ], - lightsalmon: [ 255, 160, 122 ], - lightseagreen: [ 32, 178, 170 ], - lightskyblue: [ 135, 206, 250 ], - lightslategray: [ 119, 136, 153 ], - lightslategrey: [ 119, 136, 153 ], - lightsteelblue: [ 176, 196, 222 ], - lightyellow: [ 255, 255, 224 ], - lime: [0, 255, 0], - limegreen: [ 50, 205, 50 ], - linen: [ 250, 240, 230 ], - magenta: [ 255, 0, 255 ], - maroon: [ 128, 0, 0], - mediumaquamarine: [ 102, 205, 170 ], - mediumblue: [0, 0, 205 ], - mediumorchid: [ 186, 85, 211 ], - mediumpurple: [ 147, 112, 219 ], - mediumseagreen: [ 60, 179, 113 ], - mediumslateblue: [ 123, 104, 238 ], - mediumspringgreen: [0, 250, 154 ], - mediumturquoise: [ 72, 209, 204 ], - mediumvioletred: [ 199, 21, 133 ], - midnightblue: [ 25, 25, 112 ], - mintcream: [ 245, 255, 250 ], - mistyrose: [ 255, 228, 225 ], - moccasin: [ 255, 228, 181 ], - navajowhite: [ 255, 222, 173 ], - navy: [0, 0, 128 ], - oldlace: [ 253, 245, 230 ], - olive: [ 128, 128, 0], - olivedrab: [ 107, 142, 35 ], - orange: [ 255, 165, 0], - orangered: [ 255, 69, 0], - orchid: [ 218, 112, 214 ], - palegoldenrod: [ 238, 232, 170 ], - palegreen: [ 152, 251, 152 ], - paleturquoise: [ 175, 238, 238 ], - palevioletred: [ 219, 112, 147 ], - papayawhip: [ 255, 239, 213 ], - peachpuff: [ 255, 218, 185 ], - peru: [ 205, 133, 63 ], - pink: [ 255, 192, 203 ], - plum: [ 221, 160, 221 ], - powderblue: [ 176, 224, 230 ], - purple: [ 128, 0, 128 ], - red: [ 255, 0, 0], - rosybrown: [ 188, 143, 143 ], - royalblue: [ 65, 105, 225 ], - saddlebrown: [ 139, 69, 19 ], - salmon: [ 250, 128, 114 ], - sandybrown: [ 244, 164, 96 ], - seagreen: [ 46, 139, 87 ], - seashell: [ 255, 245, 238 ], - sienna: [ 160, 82, 45 ], - silver: [ 192, 192, 192 ], - skyblue: [ 135, 206, 235 ], - slateblue: [ 106, 90, 205 ], - slategray: [ 112, 128, 144 ], - slategrey: [ 112, 128, 144 ], - snow: [ 255, 250, 250 ], - springgreen: [0, 255, 127 ], - steelblue: [ 70, 130, 180 ], - tan: [ 210, 180, 140 ], - teal: [0, 128, 128 ], - thistle: [ 216, 191, 216 ], - tomato: [ 255, 99, 71 ], - turquoise: [ 64, 224, 208 ], - violet: [ 238, 130, 238 ], - wheat: [ 245, 222, 179 ], - white: [ 255, 255, 255 ], - whitesmoke: [ 245, 245, 245 ], - yellow: [ 255, 255, 0], - yellowgreen: [ 154, 205, 50 ] - } -}; - -},{"../is":83}],100:[function(_dereq_,module,exports){ -'use strict'; - -/*global console */ - -var is = _dereq_( '../is' ); -var math = _dereq_( '../math' ); - -var util = { - - trueify: function(){ return true; }, - - falsify: function(){ return false; }, - - zeroify: function(){ return 0; }, - - noop: function(){}, - - error: function( msg ){ - /* eslint-disable */ - if( console.error ){ - console.error.apply( console, arguments ); - - if( console.trace ){ console.trace(); } - } else { - console.log.apply( console, arguments ); - - if( console.trace ){ console.trace(); } - } - /* eslint-enable */ - }, - - clone: function( obj ){ - return this.extend( {}, obj ); - }, - - // gets a shallow copy of the argument - copy: function( obj ){ - if( obj == null ){ - return obj; - } if( is.array( obj ) ){ - return obj.slice(); - } else if( is.plainObject( obj ) ){ - return this.clone( obj ); - } else { - return obj; - } - }, - - uuid: function( - a,b // placeholders - ){ - for( // loop :) - b=a=''; // b - result , a - numeric variable - a++<36; // - b+=a*51&52 // if "a" is not 9 or 14 or 19 or 24 - ? // return a random number or 4 - ( - a^15 // if "a" is not 15 - ? // genetate a random number from 0 to 15 - 8^Math.random()* - (a^20?16:4) // unless "a" is 20, in which case a random number from 8 to 11 - : - 4 // otherwise 4 - ).toString(16) - : - '-' // in other cases (if "a" is 9,14,19,24) insert "-" - ); - return b; - } - -}; - -util.makeBoundingBox = math.makeBoundingBox.bind( math ); - -util._staticEmptyObject = {}; - -util.staticEmptyObject = function(){ - return util._staticEmptyObject; -}; - -util.extend = Object.assign != null ? Object.assign : function( tgt ){ - var args = arguments; - - for( var i = 1; i < args.length; i++ ){ - var obj = args[ i ]; - - if( !obj ){ continue; } - - var keys = Object.keys( obj ); - - for( var j = 0; j < keys.length; j++ ){ - var k = keys[j]; - - tgt[ k ] = obj[ k ]; - } - } - - return tgt; -}; - -util.default = function( val, def ){ - if( val === undefined ){ - return def; - } else { - return val; - } -}; - -util.removeFromArray = function( arr, ele, manyCopies ){ - for( var i = arr.length; i >= 0; i-- ){ - if( arr[i] === ele ){ - arr.splice( i, 1 ); - - if( !manyCopies ){ break; } - } - } -}; - -util.clearArray = function( arr ){ - arr.splice( 0, arr.length ); -}; - -util.getPrefixedProperty = function( obj, propName, prefix ){ - if( prefix ){ - propName = this.prependCamel( prefix, propName ); // e.g. (labelWidth, source) => sourceLabelWidth - } - - return obj[ propName ]; -}; - -util.setPrefixedProperty = function( obj, propName, prefix, value ){ - if( prefix ){ - propName = this.prependCamel( prefix, propName ); // e.g. (labelWidth, source) => sourceLabelWidth - } - - obj[ propName ] = value; -}; - -[ - _dereq_( './colors' ), - _dereq_( './maps' ), - { memoize: _dereq_( './memoize' ) }, - _dereq_( './regex' ), - _dereq_( './strings' ), - _dereq_( './timing' ) -].forEach( function( req ){ - util.extend( util, req ); -} ); - -module.exports = util; - -},{"../is":83,"../math":85,"./colors":99,"./maps":101,"./memoize":102,"./regex":103,"./strings":104,"./timing":105}],101:[function(_dereq_,module,exports){ -'use strict'; - -var is = _dereq_( '../is' ); - -module.exports = { - // has anything been set in the map - mapEmpty: function( map ){ - var empty = true; - - if( map != null ){ - return Object.keys( map ).length === 0; - } - - return empty; - }, - - // pushes to the array at the end of a map (map may not be built) - pushMap: function( options ){ - var array = this.getMap( options ); - - if( array == null ){ // if empty, put initial array - this.setMap( this.extend( {}, options, { - value: [ options.value ] - } ) ); - } else { - array.push( options.value ); - } - }, - - // sets the value in a map (map may not be built) - setMap: function( options ){ - var obj = options.map; - var key; - var keys = options.keys; - var l = keys.length; - - for( var i = 0; i < l; i++ ){ - var key = keys[ i ]; - - if( is.plainObject( key ) ){ - this.error( 'Tried to set map with object key' ); - } - - if( i < keys.length - 1 ){ - - // extend the map if necessary - if( obj[ key ] == null ){ - obj[ key ] = {}; - } - - obj = obj[ key ]; - } else { - // set the value - obj[ key ] = options.value; - } - } - }, - - // gets the value in a map even if it's not built in places - getMap: function( options ){ - var obj = options.map; - var keys = options.keys; - var l = keys.length; - - for( var i = 0; i < l; i++ ){ - var key = keys[ i ]; - - if( is.plainObject( key ) ){ - this.error( 'Tried to get map with object key' ); - } - - obj = obj[ key ]; - - if( obj == null ){ - return obj; - } - } - - return obj; - }, - - // deletes the entry in the map - deleteMap: function( options ){ - var obj = options.map; - var keys = options.keys; - var l = keys.length; - var keepChildren = options.keepChildren; - - for( var i = 0; i < l; i++ ){ - var key = keys[ i ]; - - if( is.plainObject( key ) ){ - this.error( 'Tried to delete map with object key' ); - } - - var lastKey = i === options.keys.length - 1; - if( lastKey ){ - - if( keepChildren ){ // then only delete child fields not in keepChildren - var children = Object.keys( obj ); - - for( var j = 0; j < children.length; j++ ){ - var child = children[j]; - - if( !keepChildren[ child ] ){ - obj[ child ] = undefined; - } - } - } else { - obj[ key ] = undefined; - } - - } else { - obj = obj[ key ]; - } - } - } -}; - -},{"../is":83}],102:[function(_dereq_,module,exports){ -'use strict'; - -module.exports = function memoize( fn, keyFn ){ - if( !keyFn ){ - keyFn = function(){ - if( arguments.length === 1 ){ - return arguments[0]; - } else if( arguments.length === 0 ){ - return 'undefined'; - } - - var args = []; - - for( var i = 0; i < arguments.length; i++ ){ - args.push( arguments[ i ] ); - } - - return args.join( '$' ); - }; - } - - var memoizedFn = function(){ - var self = this; - var args = arguments; - var ret; - var k = keyFn.apply( self, args ); - var cache = memoizedFn.cache; - - if( !(ret = cache[ k ]) ){ - ret = cache[ k ] = fn.apply( self, args ); - } - - return ret; - }; - - memoizedFn.cache = {}; - - return memoizedFn; -}; - -},{}],103:[function(_dereq_,module,exports){ -'use strict'; - -var number = '(?:[-+]?(?:(?:\\d+|\\d*\\.\\d+)(?:[Ee][+-]?\\d+)?))'; - -var rgba = 'rgb[a]?\\((' + number + '[%]?)\\s*,\\s*(' + number + '[%]?)\\s*,\\s*(' + number + '[%]?)(?:\\s*,\\s*(' + number + '))?\\)'; -var rgbaNoBackRefs = 'rgb[a]?\\((?:' + number + '[%]?)\\s*,\\s*(?:' + number + '[%]?)\\s*,\\s*(?:' + number + '[%]?)(?:\\s*,\\s*(?:' + number + '))?\\)'; - -var hsla = 'hsl[a]?\\((' + number + ')\\s*,\\s*(' + number + '[%])\\s*,\\s*(' + number + '[%])(?:\\s*,\\s*(' + number + '))?\\)'; -var hslaNoBackRefs = 'hsl[a]?\\((?:' + number + ')\\s*,\\s*(?:' + number + '[%])\\s*,\\s*(?:' + number + '[%])(?:\\s*,\\s*(?:' + number + '))?\\)'; - -var hex3 = '\\#[0-9a-fA-F]{3}'; -var hex6 = '\\#[0-9a-fA-F]{6}'; - -module.exports = { - regex: { - number: number, - rgba: rgba, - rgbaNoBackRefs: rgbaNoBackRefs, - hsla: hsla, - hslaNoBackRefs: hslaNoBackRefs, - hex3: hex3, - hex6: hex6 - } -}; - -},{}],104:[function(_dereq_,module,exports){ -'use strict'; - -var memoize = _dereq_( './memoize' ); -var is = _dereq_( '../is' ); - -module.exports = { - - camel2dash: memoize( function( str ){ - return str.replace( /([A-Z])/g, function( v ){ - return '-' + v.toLowerCase(); - } ); - } ), - - dash2camel: memoize( function( str ){ - return str.replace( /(-\w)/g, function( v ){ - return v[1].toUpperCase(); - } ); - } ), - - prependCamel: memoize( function( prefix, str ){ - return prefix + str[0].toUpperCase() + str.substring(1); - }, function( prefix, str ){ - return prefix + '$' + str; - } ), - - capitalize: function( str ){ - if( is.emptyString( str ) ){ - return str; - } - - return str.charAt( 0 ).toUpperCase() + str.substring( 1 ); - } - -}; - -},{"../is":83,"./memoize":102}],105:[function(_dereq_,module,exports){ -'use strict'; - -var window = _dereq_( '../window' ); -var is = _dereq_( '../is' ); -var performance = window ? window.performance : null; - -var util = {}; - -var raf = !window ? null : ( window.requestAnimationFrame || window.mozRequestAnimationFrame || - window.webkitRequestAnimationFrame || window.msRequestAnimationFrame ); - -raf = raf || function( fn ){ - if( fn ){ - setTimeout( function(){ - fn( pnow() ); - }, 1000 / 60 ); - } -}; - -util.requestAnimationFrame = function( fn ){ - raf( fn ); -}; - -var pnow = performance && performance.now ? function(){ return performance.now(); } : function(){ return Date.now(); }; - -util.performanceNow = pnow; - -// ported lodash throttle function -util.throttle = function( func, wait, options ){ - var leading = true, - trailing = true; - - if( options === false ){ - leading = false; - } else if( is.plainObject( options ) ){ - leading = 'leading' in options ? options.leading : leading; - trailing = 'trailing' in options ? options.trailing : trailing; - } - options = options || {}; - options.leading = leading; - options.maxWait = wait; - options.trailing = trailing; - - return util.debounce( func, wait, options ); -}; - -util.now = function(){ - return Date.now(); -}; - -util.debounce = function( func, wait, options ){ // ported lodash debounce function - var util = this; - var args, - maxTimeoutId, - result, - stamp, - thisArg, - timeoutId, - trailingCall, - lastCalled = 0, - maxWait = false, - trailing = true; - - if( !is.fn( func ) ){ - return; - } - wait = Math.max( 0, wait ) || 0; - if( options === true ){ - var leading = true; - trailing = false; - } else if( is.plainObject( options ) ){ - leading = options.leading; - maxWait = 'maxWait' in options && (Math.max( wait, options.maxWait ) || 0); - trailing = 'trailing' in options ? options.trailing : trailing; - } - var delayed = function(){ - var remaining = wait - (util.now() - stamp); - if( remaining <= 0 ){ - if( maxTimeoutId ){ - clearTimeout( maxTimeoutId ); - } - var isCalled = trailingCall; - maxTimeoutId = timeoutId = trailingCall = undefined; - if( isCalled ){ - lastCalled = util.now(); - result = func.apply( thisArg, args ); - if( !timeoutId && !maxTimeoutId ){ - args = thisArg = null; - } - } - } else { - timeoutId = setTimeout( delayed, remaining ); - } - }; - - var maxDelayed = function(){ - if( timeoutId ){ - clearTimeout( timeoutId ); - } - maxTimeoutId = timeoutId = trailingCall = undefined; - if( trailing || (maxWait !== wait) ){ - lastCalled = util.now(); - result = func.apply( thisArg, args ); - if( !timeoutId && !maxTimeoutId ){ - args = thisArg = null; - } - } - }; - - return function(){ - args = arguments; - stamp = util.now(); - thisArg = this; - trailingCall = trailing && (timeoutId || !leading); - - if( maxWait === false ){ - var leadingCall = leading && !timeoutId; - } else { - if( !maxTimeoutId && !leading ){ - lastCalled = stamp; - } - var remaining = maxWait - (stamp - lastCalled), - isCalled = remaining <= 0; - - if( isCalled ){ - if( maxTimeoutId ){ - maxTimeoutId = clearTimeout( maxTimeoutId ); - } - lastCalled = stamp; - result = func.apply( thisArg, args ); - } - else if( !maxTimeoutId ){ - maxTimeoutId = setTimeout( maxDelayed, remaining ); - } - } - if( isCalled && timeoutId ){ - timeoutId = clearTimeout( timeoutId ); - } - else if( !timeoutId && wait !== maxWait ){ - timeoutId = setTimeout( delayed, wait ); - } - if( leadingCall ){ - isCalled = true; - result = func.apply( thisArg, args ); - } - if( isCalled && !timeoutId && !maxTimeoutId ){ - args = thisArg = null; - } - return result; - }; -}; - -module.exports = util; - -},{"../is":83,"../window":107}],106:[function(_dereq_,module,exports){ -module.exports="2.7.8" -},{}],107:[function(_dereq_,module,exports){ -module.exports = ( typeof window === 'undefined' ? null : window ); // eslint-disable-line no-undef - -},{}]},{},[82])(82) -}); +module.exports = "3.2.20"; +/***/ }) +/******/ ]); +}); \ No newline at end of file diff --git a/styles/bootstrap/cytoscape/cytoscape.min.js b/styles/bootstrap/cytoscape/cytoscape.min.js index fb608c6d4..78fecacd7 100644 --- a/styles/bootstrap/cytoscape/cytoscape.min.js +++ b/styles/bootstrap/cytoscape/cytoscape.min.js @@ -1,62 +1,23 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.cytoscape=e()}}(function(){var define,module,exports;return function e(t,r,n){function i(o,s){if(!r[o]){if(!t[o]){var l="function"==typeof require&&require;if(!s&&l)return l(o,!0);if(a)return a(o,!0);var u=new Error("Cannot find module '"+o+"'");throw u.code="MODULE_NOT_FOUND",u}var c=r[o]={exports:{}};t[o][0].call(c.exports,function(e){var r=t[o][1][e];return i(r?r:e)},c,c.exports,e,t,r,n)}return r[o].exports}for(var a="function"==typeof require&&require,o=0;oa&&(n=a,r=i)}return r}},a=this._private.cy;if(null!=e&&null!=e.root){var o=n.string(e.root)?this.filter(e.root)[0]:e.root[0];if(null!=e.goal){var s=n.string(e.goal)?this.filter(e.goal)[0]:e.goal[0];if(null!=e.heuristic&&n.fn(e.heuristic))var l=e.heuristic;else var l=function(){return 0};if(null!=e.weight&&n.fn(e.weight))var u=e.weight;else var u=function(e){return 1};if(null!=e.directed)var c=e.directed;else var c=!1;var d=[],h=[o.id()],p={},f={},v={},g={};v[o.id()]=0,g[o.id()]=l(o);for(var y=this.edges().stdFilter(function(e){return!e.isLoop()}),m=this.nodes(),b=0;h.length>0;){var x=i(h,g),w=a.getElementById(h[x]);if(b++,w.id()==s.id()){var E=r(o.id(),s.id(),p,[]);return E.reverse(),{found:!0,distance:v[w.id()],path:t.spawn(E),steps:b}}d.push(w.id()),h.splice(x,1);var _=w.connectedEdges();c&&(_=_.stdFilter(function(e){return e.data("source")===w.id()})),_=_.intersect(y);for(var P=0;P<_.length;P++){var S=_[P],k=S.connectedNodes().stdFilter(function(e){return e.id()!==w.id()}).intersect(m);if(-1==d.indexOf(k.id())){var T=v[w.id()]+u.apply(S,[S]);-1!=h.indexOf(k.id())?Th;h++)d[u[h].id()]=h;for(var p=[],f=[],v=[],h=0;c>h;h++)u[h].id()===o.id()?p[h]=0:p[h]=1/0,f[h]=void 0;for(var g=!1,h=1;c>h;h++){g=!1;for(var y=0;yh;h++)E.push(u[h].id());var _={distanceTo:function(e){if(n.string(e))var t=s.filter(e)[0].id();else var t=e.id();return p[d[t]]},pathTo:function(e){var r=function(e,t,r,n,i,a){for(;;){if(i.push(s.getElementById(n[r])),i.push(a[r]),t===r)return i;var o=e[r];if("undefined"==typeof o)return;r=o}};if(n.string(e))var i=s.filter(e)[0].id();else var i=e.id();var a=[],l=r(f,d[o.id()],d[i],E,a,v);return null!=l&&l.reverse(),t.spawn(l)},hasNegativeWeightCycle:!1};return _}}};t.exports=a},{"../../is":83,"../../util":100}],5:[function(e,t,r){"use strict";var n=e("../../is"),i=e("../../heap"),a={betweennessCentrality:function(e){e=e||{};var t,r;n.fn(e.weight)?(r=e.weight,t=!0):t=!1;for(var a,o=null!=e.directed?e.directed:!1,s=this._private.cy,l=this.nodes(),u={},c={},d={set:function(e,t){c[e]=t,t>a&&(a=t)},get:function(e){return c[e]}},h=0;h0?S.edgesTo(P)[0]:P.edgesTo(S)[0];var k=r.apply(_,[_]);P=P.id(),x[P]>x[p]+k&&(x[P]=x[p]+k,w.nodes.indexOf(P)<0?w.push(P):w.updateItem(P),b[P]=0,m[P]=[]),x[P]==x[p]+k&&(b[P]=b[P]+b[p],m[P].push(p))}else for(var E=0;E0;)for(var P=y.pop(),E=0;Ea&&(a=u),i[o[l].id()]=u}return{closeness:function(e){if(n.string(e))var e=t.filter(e)[0].id();else var e=e.id();return i[e]/a}}},closenessCentrality:function(e){if(e=e||{},null!=e.root){if(n.string(e.root))var t=this.filter(e.root)[0];else var t=e.root[0];if(null!=e.weight&&n.fn(e.weight))var r=e.weight;else var r=function(){return 1};if(null!=e.directed&&n.bool(e.directed))var i=e.directed;else var i=!1;var a=e.harmonic;void 0===a&&(a=!0);for(var o=this.dijkstra({root:t,weight:r,directed:i}),s=0,l=this.nodes(),u=0;ud;d++){var h=a[d],p=this.degreeCentrality(i.extend({},e,{root:h}));ud;d++){var h=a[d],p=this.degreeCentrality(i.extend({},e,{root:h}));vu||!i)&&(o=u,i=l)}return{edge:i,dist:o}};v.size()>0;){var b=v.pop(),x=p(b),w=b.id();if(c[w]=x,x===Math.Infinite)break;for(var E=b.neighborhood().intersect(h),g=0;g0)for(r.unshift(t);u[i.id()];){var a=u[i.id()];r.unshift(a.edge),r.unshift(a.node),i=a.node}return o.collection(r)}}}};t.exports=a},{"../../heap":81,"../../is":83}],10:[function(e,t,r){"use strict";var n=e("../../is"),i={floydWarshall:function(e){e=e||{};var t=this.cy();if(null!=e.weight&&n.fn(e.weight))var r=e.weight;else var r=function(e){return 1};if(null!=e.directed)var i=e.directed;else var i=!1;for(var a=this.edges().stdFilter(function(e){return!e.isLoop()}),o=this.nodes(),s=o.length,l={},u=0;s>u;u++)l[o[u].id()]=u;for(var c=[],u=0;s>u;u++){for(var d=new Array(s),h=0;s>h;h++)u==h?d[h]=0:d[h]=1/0;c.push(d)}var p=[],f=[],v=function(e){for(var t=0;s>t;t++){for(var r=new Array(s),n=0;s>n;n++)r[n]=void 0;e.push(r)}};v(p),v(f);for(var u=0;um&&(c[g][y]=m,p[g][y]=y,f[g][y]=a[u])}if(!i)for(var u=0;um&&(c[g][y]=m,p[g][y]=y,f[g][y]=a[u])}for(var b=0;s>b;b++)for(var u=0;s>u;u++)for(var h=0;s>h;h++)c[u][b]+c[b][h]u;u++)x.push(o[u].id());var w={distance:function(e,r){if(n.string(e))var i=t.filter(e)[0].id();else var i=e.id();if(n.string(r))var a=t.filter(r)[0].id();else var a=r.id();return c[l[i]][l[a]]},path:function(e,r){var i=function(e,r,n,i,a){if(e===r)return t.getElementById(i[e]);if(void 0!==n[e][r]){for(var o=[t.getElementById(i[e])],s=e;e!==r;){s=e,e=n[e][r];var l=a[s][e];o.push(l),o.push(t.getElementById(i[e]))}return o}};if(n.string(e))var a=t.filter(e)[0].id();else var a=e.id();if(n.string(r))var o=t.filter(r)[0].id();else var o=r.id();var s=i(l[a],l[o],p,x,f);return t.collection(s)}};return w}};t.exports=i},{"../../is":83}],11:[function(e,t,r){"use strict";var n=e("../../util"),i={};[e("./bfs-dfs"),e("./dijkstra"),e("./kruskal"),e("./a-star"),e("./floyd-warshall"),e("./bellman-ford"),e("./kerger-stein"),e("./page-rank"),e("./degree-centrality"),e("./closeness-centrality"),e("./betweenness-centrality")].forEach(function(e){n.extend(i,e)}),t.exports=i},{"../../util":100,"./a-star":3,"./bellman-ford":4,"./betweenness-centrality":5,"./bfs-dfs":6,"./closeness-centrality":7,"./degree-centrality":8,"./dijkstra":9,"./floyd-warshall":10,"./kerger-stein":12,"./kruskal":13,"./page-rank":14}],12:[function(e,t,r){"use strict";var n=e("../../util"),i={kargerStein:function(e){var t=this;e=e||{};var r=function(e,t,r){for(var n=r[e],i=n[1],a=n[2],o=t[i],s=t[a],l=r.filter(function(e){return t[e[1]]===o&&t[e[2]]===s?!1:t[e[1]]!==s||t[e[2]]!==o}),u=0;u=n)return t;var o=Math.floor(Math.random()*t.length),s=r(o,e,t);return i(e,s,n-1,a)},a=this._private.cy,o=this.edges().stdFilter(function(e){return!e.isLoop()}),s=this.nodes(),l=s.length,u=o.length,c=Math.ceil(Math.pow(Math.log(l)/Math.LN2,2)),d=Math.floor(l/Math.sqrt(2));if(2>l)return void n.error("At least 2 nodes are required for Karger-Stein algorithm");for(var h={},p=0;l>p;p++)h[s[p].id()]=p;for(var f=[],p=0;u>p;p++){var v=o[p];f.push([p,h[v.source().id()],h[v.target().id()]])}for(var g,y=1/0,m=[],p=0;l>p;p++)m.push(p);for(var b=0;c>=b;b++){var x=m.slice(0),w=i(x,f,l,d),E=x.slice(0),_=i(x,w,d,2),P=i(E,w,d,2);_.length<=P.length&&_.lengthn;n++)r+=e[n];for(var n=0;t>n;n++)e[n]=e[n]/r};if(null!=e&&null!=e.dampingFactor)var r=e.dampingFactor;else var r=.8;if(null!=e&&null!=e.precision)var i=e.precision;else var i=1e-6;if(null!=e&&null!=e.iterations)var a=e.iterations;else var a=200;if(null!=e&&null!=e.weight&&n.fn(e.weight))var o=e.weight;else var o=function(e){return 1};for(var s=this._private.cy,l=this.edges().stdFilter(function(e){return!e.isLoop()}),u=this.nodes(),c=u.length,d=l.length,h={},p=0;c>p;p++)h[u[p].id()]=p;for(var f=[],v=[],g=(1-r)/c,p=0;c>p;p++){for(var y=[],m=0;c>m;m++)y.push(0);f.push(y),v.push(0)}for(var p=0;d>p;p++){var b=l[p],x=h[b.source().id()],w=h[b.target().id()],E=o.apply(b,[b]);f[w][x]+=E,v[x]+=E}for(var _=1/c+g,m=0;c>m;m++)if(0===v[m])for(var p=0;c>p;p++)f[p][m]=_;else for(var p=0;c>p;p++)f[p][m]=f[p][m]/v[m]+g;for(var P,S=[],k=[],p=0;c>p;p++)S.push(1),k.push(0);for(var T=0;a>T;T++){for(var D=k.slice(0),p=0;c>p;p++)for(var m=0;c>m;m++)D[p]+=f[p][m]*S[m];t(D),P=S,S=D;for(var C=0,p=0;c>p;p++)C+=Math.pow(P[p]-S[p],2);if(i>C)break}var M={rank:function(e){if(n.string(e))var t=s.filter(e)[0].id();else var t=e.id();return S[h[t]]}};return M}};t.exports=i},{"../../is":83}],15:[function(e,t,r){"use strict";var n=e("../define"),i={animate:n.animate(),animation:n.animation(),animated:n.animated(),clearQueue:n.clearQueue(),delay:n.delay(),delayAnimation:n.delayAnimation(),stop:n.stop()};t.exports=i},{"../define":44}],16:[function(e,t,r){"use strict";var n=e("../util"),i={classes:function(e){e=e.match(/\S+/g)||[];for(var t=this,r=[],i={},a=0;a0&&this.spawn(r).updateStyle().trigger("class"),t},addClass:function(e){return this.toggleClass(e,!0)},hasClass:function(e){var t=this[0];return!(null==t||!t._private.classes[e])},toggleClass:function(e,t){for(var r=e.match(/\S+/g)||[],n=this,i=[],a=0,o=n.length;o>a;a++)for(var s=n[a],l=!1,u=0;u0&&this.spawn(i).updateStyle().trigger("class"),n},removeClass:function(e){return this.toggleClass(e,!1)},flashClass:function(e,t){var r=this;if(null==t)t=250;else if(0===t)return r;return r.addClass(e),setTimeout(function(){r.removeClass(e)},t),r}};t.exports=i},{"../util":100}],17:[function(e,t,r){"use strict";var n={allAre:function(e){return this.filter(e).length===this.length},is:function(e){return this.filter(e).length>0},some:function(e,t){for(var r=0;r0},allAreNeighbors:function(e){return e=this.cy().collection(e),this.neighborhood().intersect(e).length===e.length}};n.allAreNeighbours=n.allAreNeighbors,t.exports=n},{}],18:[function(e,t,r){"use strict";var n={parent:function(e){for(var t=[],r=this._private.cy,n=0;n0&&t.push(a)}return this.spawn(t,{unique:!0}).filter(e)},parents:function(e){for(var t=[],r=this.parent();r.nonempty();){for(var n=0;ne}),maxDegree:i("degree",function(e,t){return e>t}),minIndegree:i("indegree",function(e,t){return t>e}),maxIndegree:i("indegree",function(e,t){return e>t}),minOutdegree:i("outdegree",function(e,t){return t>e}),maxOutdegree:i("outdegree",function(e,t){return e>t})}),a.extend(o,{totalDegree:function(e){for(var t=0,r=this.nodes(),n=0;n0?this.add(s):this;t?l.trigger("position"):l.rtrigger("position")}return this},silentPositions:function(e){return this.positions(e,!0)},renderedPosition:function(e,t){var r=this[0],n=this.cy(),i=n.zoom(),a=n.pan(),s=o.plainObject(e)?e:void 0,l=void 0!==s||void 0!==t&&o.string(e);if(r&&r.isNode()){if(!l){var u=r._private.position;return s={x:u.x*i+a.x,y:u.y*i+a.y},void 0===e?s:s[e]}for(var c=0;c0,d=c;c&&(u=u[0]);var h=d?u._private.position:{x:0,y:0};return i={x:l.x-h.x,y:l.y-h.y},void 0===e?i:i[e]}for(var p=0;p0,d=c;c&&(u=u[0]);var h=d?u._private.position:{x:0,y:0};void 0!==t?r._private.position[e]=t+h[e]:void 0!==i&&(r._private.position={x:i.x+h.x,y:i.y+h.y})}this.rtrigger("position")}else if(!a)return;return this},renderedBoundingBox:function(e){var t=this.boundingBox(e),r=this.cy(),n=r.zoom(),i=r.pan(),a=t.x1*n+i.x,o=t.x2*n+i.x,s=t.y1*n+i.y,l=t.y2*n+i.y;return{x1:a,x2:o,y1:s,y2:l,w:o-a,h:l-s}},updateCompoundBounds:function(){function e(e){if(e.isParent()){var t=e._private,n=e.children(),i="include"===e.pstyle("compound-sizing-wrt-labels").value,a=n.boundingBox({includeLabels:i,includeShadows:!1,includeOverlays:!1,useCache:!1}),o={top:e.pstyle("padding-top").pfValue,bottom:e.pstyle("padding-bottom").pfValue,left:e.pstyle("padding-left").pfValue,right:e.pstyle("padding-right").pfValue},s=t.position;t.autoWidth=a.w,s.x=(a.x1+a.x2-o.left+o.right)/2,t.autoHeight=a.h,s.y=(a.y1+a.y2-o.top+o.bottom)/2,r.push(e)}}var t=this.cy();if(!t.styleEnabled()||!t.hasCompoundNodes())return t.collection();for(var r=[],n=this;n.nonempty();){for(var i=0;ie.x2?n:e.x2,e.y1=re.y2?i:e.y2)},d=function(e,t){return c(e,t.x1,t.y1,t.x2,t.y2)},h=function(e,t,r){return s.getPrefixedProperty(e,t,r)},p=function(e,t,r,n){var i,a,o=t._private,s=o.rstyle,l=s.arrowWidth/2,u=t.pstyle(r+"-arrow-shape").value;"none"!==u&&("source"===r?(i=s.srcX,a=s.srcY):"target"===r?(i=s.tgtX,a=s.tgtY):(i=s.midX,a=s.midY),c(e,i-l,a-l,i+l,a+l))},f=function(e,t,r,n){var i;i=r?r+"-":"";var a=t._private,o=a.rstyle,s=t.pstyle(i+"label").strValue;if(s){var l,u,d,p,f=t.pstyle("text-halign"),v=t.pstyle("text-valign"),g=h(o,"labelWidth",r),y=h(o,"labelHeight",r),m=h(o,"labelX",r),b=h(o,"labelY",r),x=t.pstyle(i+"text-margin-x").pfValue,w=t.pstyle(i+"text-margin-y").pfValue,E=t.isEdge(),_=t.pstyle(i+"text-rotation"),P=t.pstyle("text-shadow-blur").pfValue/2,S=t.pstyle("text-shadow-offset-x").pfValue,k=t.pstyle("text-shadow-offset-y").pfValue,T=t.pstyle("text-shadow-opacity").value,D=t.pstyle("text-outline-width").pfValue,C=t.pstyle("text-border-width").pfValue,M=C/2,N=y,B=g,z=B/2,I=N/2;if(E)l=m-z,u=m+z,d=b-I,p=b+I;else{switch(f.value){case"left":l=m-B,u=m;break;case"center":l=m-z,u=m+z;break;case"right":l=m,u=m+B}switch(v.value){case"top":d=b-N,p=b;break;case"center":d=b-I,p=b+I;break;case"bottom":d=b,p=b+N}}var L=E&&"autorotate"===_.strValue,O=null!=_.pfValue&&0!==_.pfValue;if(L||O){var A=L?h(a.rstyle,"labelAngle",r):_.pfValue,R=Math.cos(A),q=Math.sin(A),V=function(e,t){return e-=m,t-=b,{x:e*R-t*q+m,y:e*q+t*R+b}},F=V(l,d),j=V(l,p),X=V(u,d),Y=V(u,p);l=Math.min(F.x,j.x,X.x,Y.x),u=Math.max(F.x,j.x,X.x,Y.x),d=Math.min(F.y,j.y,X.y,Y.y),p=Math.max(F.y,j.y,X.y,Y.y)}l+=x-Math.max(D,M),u+=x+Math.max(D,M),d+=w-Math.max(D,M),p+=w+Math.max(D,M),c(e,l,d,u,p),n.includeShadows&&T>0&&(l+=-P+S,u+=+P+S,d+=-P+k,p+=+P+k,c(e,l,d,u,p))}return e},v=function(e,t){var r,n,i,a,o,s,d=e._private.cy,h=d._private,v=h.styleEnabled,g={x1:1/0,y1:1/0,x2:-(1/0),y2:-(1/0)},y=e._private,m=v?e.pstyle("display").value:"element",b=e.isNode(),x=e.isEdge(),w="none"!==m;if(w){var E=0,_=0;v&&t.includeOverlays&&(E=e.pstyle("overlay-opacity").value,0!==E&&(_=e.pstyle("overlay-padding").value));var P=0,S=0;if(v&&(P=e.pstyle("width").pfValue,S=P/2),b&&t.includeNodes){var k=y.position;o=k.x,s=k.y;var P=e.outerWidth(),T=P/2,D=e.outerHeight(),C=D/2;r=o-T-_,n=o+T+_,i=s-C-_,a=s+C+_,c(g,r,i,n,a)}else if(x&&t.includeEdges){var M=y.rstyle||{};if(v&&(r=Math.min(M.srcX,M.midX,M.tgtX),n=Math.max(M.srcX,M.midX,M.tgtX),i=Math.min(M.srcY,M.midY,M.tgtY),a=Math.max(M.srcY,M.midY,M.tgtY),r-=S,n+=S,i-=S,a+=S,c(g,r,i,n,a)),v&&"haystack"===e.pstyle("curve-style").strValue){var N=M.haystackPts;if(r=N[0].x,i=N[0].y,n=N[1].x,a=N[1].y,r>n){var B=r;r=n,n=B}if(i>a){var B=i;i=a,a=B}c(g,r-S,i-S,n+S,a+S)}else{for(var z=M.bezierPts||M.linePts||[],I=0;In){var B=r;r=n,n=B}if(i>a){var B=i;i=a,a=B}r-=S,n+=S,i-=S,a+=S,c(g,r,i,n,a)}}}if(v){if(r=g.x1,n=g.x2,i=g.y1,a=g.y2,t.includeShadows&&e.pstyle("shadow-opacity").value>0){var j=e.pstyle("shadow-blur").pfValue/2,X=e.pstyle("shadow-offset-x").pfValue,Y=e.pstyle("shadow-offset-y").pfValue;c(g,r-j+X,i-j+Y,n+j+X,a+j+Y)}c(g,r-_,i-_,n+_,a+_)}v&&t.includeEdges&&x&&(p(g,e,"mid-source",t),p(g,e,"mid-target",t),p(g,e,"source",t),p(g,e,"target",t)),v&&t.includeLabels&&(f(g,e,null,t),x&&(f(g,e,"source",t),f(g,e,"target",t)))}return g.x1=u(g.x1),g.y1=u(g.y1),g.x2=u(g.x2),g.y2=u(g.y2),g.w=u(g.x2-g.x1),g.h=u(g.y2-g.y1),g.w>0&&g.h>0&&w&&l.expandBoundingBox(g,1),g},g=function(e){return e?"t":"f"},y=function(e){var t="";return t+=g(e.incudeNodes),t+=g(e.includeEdges),t+=g(e.includeLabels),t+=g(e.includeShadows),t+=g(e.includeOverlays)},m=function(e,t){var r,n=e._private,i=e.cy().headless(),a=t===b?x:y(t);return t.useCache&&!i&&n.bbCache&&n.bbCache[a]?r=n.bbCache[a]:(r=v(e,t),i||(n.bbCache=n.bbCache||{},n.bbCache[a]=r)),r},b={includeNodes:!0,includeEdges:!0,includeLabels:!0,includeShadows:!0,includeOverlays:!0,useCache:!0},x=y(b);i.boundingBox=function(e){if(1===this.length&&this[0]._private.bbCache&&(void 0===e||void 0===e.useCache||e.useCache===!0))return void 0===e&&(e=b),m(this[0],e);var t={x1:1/0,y1:1/0,x2:-(1/0),y2:-(1/0)};e=e||s.staticEmptyObject();var r={includeNodes:s["default"](e.includeNodes,b.includeNodes),includeEdges:s["default"](e.includeEdges,b.includeEdges),includeLabels:s["default"](e.includeLabels,b.includeLabels),includeShadows:s["default"](e.includeShadows,b.includeShadows),includeOverlays:s["default"](e.includeOverlays,b.includeOverlays),useCache:s["default"](e.useCache,b.useCache)},n=this,i=n.cy(),a=n.cy().renderer(),o=i.styleEnabled(); -o&&a.recalculateRenderedStyle(n,r.useCache);for(var l=0;ld;d++){var p=c[d];p&&""!==p&&(a._private.classes[p]=!0)}(t.style||t.css)&&e.style().applyBypass(this,t.style||t.css),(void 0===r||r)&&this.restore()};t.exports=a},{"../is":83,"../util":100}],23:[function(e,t,r){"use strict";var n=e("../define"),i={on:n.on(),one:n.on({unbindSelfOnTrigger:!0}),once:n.on({unbindAllBindersOnTrigger:!0}),off:n.off(),trigger:n.trigger(),rtrigger:function(e,t){return 0!==this.length?(this.cy().notify({type:e,eles:this}),this.trigger(e,t),this):void 0}};n.eventAliasesOn(i),t.exports=i},{"../define":44}],24:[function(e,t,r){"use strict";var n=e("../is"),i=e("../selector"),a={nodes:function(e){return this.filter(function(e,t){return t.isNode()}).filter(e)},edges:function(e){return this.filter(function(e,t){return t.isEdge()}).filter(e)},filter:function(e){if(void 0===e)return this;if(n.string(e)||n.elementOrCollection(e))return i(e).filter(this);if(n.fn(e)){for(var t=[],r=0;r1&&!i){var a=this.length-1,o=this[a],s=o._private.data.id;this[a]=void 0,this[n]=o,t.indexes[s]=n}return this.length--,this},unmerge:function(e){var t=this._private.cy;if(!e)return this;if(e&&n.string(e)){var r=e;e=t.mutableElements().filter(r)}for(var i=0;in&&(n=s,r=o)}return{value:n,ele:r}},min:function(e,t){for(var r,n=1/0,i=this,a=0;as&&(n=s,r=o)}return{value:n,ele:r}}},o=a;o.u=o["|"]=o["+"]=o.union=o.or=o.add,o["\\"]=o["!"]=o["-"]=o.difference=o.relativeComplement=o.subtract=o.not,o.n=o["&"]=o["."]=o.and=o.intersection=o.intersect,o["^"]=o["(+)"]=o["(-)"]=o.symmetricDifference=o.symdiff=o.xor,o.fnFilter=o.filterFn=o.stdFilter,o.complement=o.abscomp=o.absoluteComplement,t.exports=a},{"../is":83,"../selector":87}],25:[function(e,t,r){"use strict";var n={isNode:function(){return"nodes"===this.group()},isEdge:function(){return"edges"===this.group()},isLoop:function(){return this.isEdge()&&this.source().id()===this.target().id()},isSimple:function(){return this.isEdge()&&this.source().id()!==this.target().id()},group:function(){var e=this[0];return e?e._private.group:void 0}};t.exports=n},{}],26:[function(e,t,r){"use strict";var n=e("../util"),i=e("../is"),a=e("./element"),o={generate:function(e,t,r){for(var i=null!=r?r:n.uuid();e.hasElementWithId(i);)i=n.uuid();return i}},s=function(e,t,r){if(void 0===e||!i.core(e))return void n.error("A collection must have a reference to the core");var s={},l={},u=!1;if(t){if(t.length>0&&i.plainObject(t[0])&&!i.element(t[0])){u=!0;for(var c=[],d={},h=0,p=t.length;p>h;h++){var f=t[h];null==f.data&&(f.data={});var v=f.data;if(null==v.id)v.id=o.generate(e,f);else if(e.hasElementWithId(v.id)||d[v.id])continue;var g=new a(e,f,!1);c.push(g),d[v.id]=!0}t=c}}else t=[];this.length=0;for(var h=0,p=t.length;p>h;h++){var y=t[h];if(y){var m=y._private.data.id;(!r||r.unique&&!s[m])&&(s[m]=y,l[m]=this.length,this[this.length]=y,this.length++)}}this._private={cy:e,ids:s,indexes:l},u&&this.restore()},l=a.prototype=s.prototype;l.instanceString=function(){return"collection"},l.spawn=function(e,t,r){return i.core(e)||(r=t,t=e,e=this.cy()),new s(e,t,r)},l.spawnSelf=function(){return this.spawn(this)},l.cy=function(){return this._private.cy},l.element=function(){return this[0]},l.collection=function(){return i.collection(this)?this:new s(this._private.cy,[this])},l.unique=function(){return new s(this._private.cy,this,{unique:!0})},l.hasElementWithId=function(e){return!!this._private.ids[e]},l.getElementById=function(e){var t=this._private.cy,r=this._private.ids[e];return r?r:new s(t)},l.poolIndex=function(){var e=this._private.cy,t=e._private.elements,r=this._private.data.id;return t._private.indexes[r]},l.json=function(e){var t=this.element(),r=this.cy();if(null==t&&e)return this;if(null!=t){var a=t._private;if(i.plainObject(e)){r.startBatch(),e.data&&t.data(e.data),e.position&&t.position(e.position);var o=function(r,n,i){var o=e[r];null!=o&&o!==a[r]&&(o?t[n]():t[i]())};return o("removed","remove","restore"),o("selected","select","unselect"),o("selectable","selectify","unselectify"),o("locked","lock","unlock"),o("grabbable","grabify","ungrabify"),null!=e.classes&&t.classes(e.classes),r.endBatch(),this}if(void 0===e){var s={data:n.copy(a.data),position:n.copy(a.position),group:a.group,removed:a.removed,selected:a.selected,selectable:a.selectable,locked:a.locked,grabbable:a.grabbable,classes:null};return s.classes=Object.keys(a.classes).filter(function(e){return a.classes[e]}).join(" "),s}}},l.jsons=function(){for(var e=[],t=0;td;d++){var p=t[d];p.removed()&&(p.isNode()?u.push(p):c.push(p))}l=u.concat(c);var d,f=function(){l.splice(d,1),d--};for(d=0;dP;P++){var S=w[P],k=g[S];i.number(k)&&(k=g[S]=""+g[S]),null==k||""===k?(n.error("Can not create edge `"+y+"` with unspecified "+S),_=!0):r.hasElementWithId(k)||(n.error("Can not create edge `"+y+"` with nonexistant "+S+" `"+k+"`"),_=!0)}if(_){f();continue}var T=r.getElementById(g.source),D=r.getElementById(g.target);T._private.edges.push(x),D._private.edges.push(x),x._private.source=T,x._private.target=D}v.ids={},v.ids[y]=p,v.indexes={},v.indexes[y]=p,v.removed=!1,r.addToPool(p)}for(var d=0;d0){for(var I=new s(r,l),d=0;df;f++){var g=u[f];i(g)}var y=[];y.ids={},p.removeFromPool(d);for(var f=0;f0&&(e&&this.cy().notify({type:"remove",eles:E}),E.trigger("remove"));for(var f=0;fe&&(e=n+e),0>t&&(t=n+t);for(var i=e;i>=0&&t>i&&n>i;i++)r.push(this[i]);return this.spawn(r)},size:function(){return this.length},eq:function(e){return this[e]||this.spawn()},first:function(){return this[0]||this.spawn()},last:function(){return this[this.length-1]||this.spawn()},empty:function(){return 0===this.length},nonempty:function(){return!this.empty()},sort:function(e){if(!n.fn(e))return this;var t=this.toArray().sort(e);return this.spawn(t)},sortByZIndex:function(){return this.sort(i)},zDepth:function(){var e=this[0];if(e){var t=e._private,r=t.group;if("nodes"===r){var n=t.data.parent?e.parents().size():0;return e.isParent()?n:Number.MAX_VALUE}var i=t.source,a=t.target,o=i.zDepth(),s=a.zDepth();return Math.max(o,s,0)}}};t.exports=a},{"../is":83,"./zsort":32}],28:[function(e,t,r){"use strict";var n=e("../is"),i=e("../util"),a=e("../promise"),o={layoutPositions:function(e,t,r){var i=this.nodes(),o=this.cy();if(e.trigger({type:"layoutstart",layout:e}),e.animations=[],t.animate){for(var s=0;s0?this.add(i):this;return e?a.rtrigger("style"):a.trigger("style"),this},updateMappers:function(e){var t=this._private.cy,r=t.style();if(e=!(!e&&void 0!==e),!t.styleEnabled())return this;r.updateMappers(this);var n=this.updateCompoundBounds(),i=n.length>0?this.add(n):this;return e?i.rtrigger("style"):i.trigger("style"),this},parsedStyle:function(e){var t=this[0];if(t.cy().styleEnabled())return t?t._private.style[e]||t.cy().style().getDefaultProperty(e):void 0},renderedStyle:function(e){var t=this.cy();if(!t.styleEnabled())return this;var r=this[0];if(r){var n=r.cy().style().getRenderedStyle(r);return void 0===e?n:n[e]}},style:function(e,t){var r=this.cy();if(!r.styleEnabled())return this;var i=!1,a=r.style();if(n.plainObject(e)){var o=e;a.applyBypass(this,o,i);var s=this.updateCompoundBounds(),l=s.length>0?this.add(s):this;l.rtrigger("style")}else if(n.string(e)){if(void 0===t){var u=this[0];return u?a.getStylePropertyValue(u,e):void 0}a.applyBypass(this,e,t,i);var s=this.updateCompoundBounds(),l=s.length>0?this.add(s):this;l.rtrigger("style")}else if(void 0===e){var u=this[0];return u?a.getRawStyle(u):void 0}return this},removeStyle:function(e){var t=this.cy();if(!t.styleEnabled())return this;var r=!1,n=t.style(),i=this;if(void 0===e)for(var a=0;a0?this.add(s):this;return l.rtrigger("style"),this},show:function(){return this.css("display","element"),this},hide:function(){return this.css("display","none"),this},visible:function(){var e=this.cy();if(!e.styleEnabled())return!0;var t=this[0],r=e.hasCompoundNodes();if(t){if("visible"!==t.pstyle("visibility").value||"element"!==t.pstyle("display").value)return!1;if("nodes"===t._private.group){if(!r)return!0;var n=t._private.data.parent?t.parents():null;if(n)for(var i=0;i0&&t.push(c[0]),t.push(s[0])}return this.spawn(t,{unique:!0}).filter(e)},"neighborhood"),closedNeighborhood:function(e){return this.neighborhood().add(this).filter(e)},openNeighborhood:function(e){return this.neighborhood(e)}}),l.neighbourhood=l.neighborhood,l.closedNeighbourhood=l.closedNeighborhood,l.openNeighbourhood=l.openNeighborhood,o.extend(l,{source:u(function(e){var t,r=this[0];return r&&(t=r._private.source||r.cy().collection()),t&&e?t.filter(e):t},"source"),target:u(function(e){var t,r=this[0];return r&&(t=r._private.target||r.cy().collection()),t&&e?t.filter(e):t},"target"),sources:n({attr:"source"}),targets:n({attr:"target"})}),o.extend(l,{edgesWith:u(i(),"edgesWith",!0),edgesTo:u(i({thisIsSrc:!0}),"edgesTo",!0)}),o.extend(l,{connectedEdges:u(function(e){for(var t=[],r=this,n=0;n0);return i.map(function(e){var t=e.connectedEdges().stdFilter(function(t){return e.anySame(t.source())&&e.anySame(t.target())});return e.union(t)})}}),t.exports=l},{"../is":83,"../util":100}],32:[function(e,t,r){"use strict";var n=function(e,t){var r=e.cy(),n=e.pstyle("z-index").value-t.pstyle("z-index").value,i=0,a=0,o=r.hasCompoundNodes(),s=e.isNode(),l=!s,u=t.isNode(),c=!u;o&&(i=e.zDepth(),a=t.zDepth());var d=i-a,h=0===d;return h?s&&c?1:l&&u?-1:0===n?e.poolIndex()-t.poolIndex():n:d};t.exports=n},{}],33:[function(e,t,r){"use strict";var n=e("../is"),i=e("../util"),a=e("../collection"),o=e("../collection/element"),s={add:function(e){var t,r=this;if(n.elementOrCollection(e)){var s=e;if(s._private.cy===r)t=s.restore();else{for(var l=[],u=0;uu;u++){var f=h[u],v=d[f];if(n.array(v))for(var g=0,y=v.length;y>g;g++){var m=i.extend({group:f},v[g]);l.push(m)}}t=new a(r,l)}else{var m=e;t=new o(r,m).collection()}return t},remove:function(e){if(n.elementOrCollection(e));else if(n.string(e)){var t=e;e=this.$(t)}return e.remove()},load:function(e,t,r){var a=this;a.notifications(!1);var o=a.mutableElements();o.length>0&&o.remove(),null!=e&&(n.plainObject(e)||n.array(e))&&a.add(e),a.one("layoutready",function(e){a.notifications(!0),a.trigger(e),a.notify({type:"load",eles:a.mutableElements()}),a.one("load",t),a.trigger("load")}).one("layoutstop",function(){a.one("done",r),a.trigger("done")});var s=i.extend({},a._private.options.layout);return s.eles=a.elements(),a.layout(s),this}};t.exports=s},{"../collection":26,"../collection/element":22,"../is":83,"../util":100}],34:[function(e,t,r){"use strict";var n=e("../define"),i=e("../util"),a=e("../is"),o={animate:n.animate(),animation:n.animation(),animated:n.animated(),clearQueue:n.clearQueue(),delay:n.delay(),delayAnimation:n.delayAnimation(),stop:n.stop(),addToAnimationPool:function(e){var t=this;t.styleEnabled()&&t._private.aniEles.merge(e)},stopAnimationLoop:function(){this._private.animationsRunning=!1},startAnimationLoop:function(){function e(){c._private.animationsRunning&&i.requestAnimationFrame(function(r){t(r),e()})}function t(e){function t(t,i){var s=t._private,l=s.animation.current,u=s.animation.queue,c=!1;if(0===l.length){var d=u.shift();d&&l.push(d)}for(var h=function(e){for(var t=e.length-1;t>=0;t--){var r=e[t];r()}e.splice(0,e.length)},p=l.length-1;p>=0;p--){var f=l[p],v=f._private;v.stopped?(l.splice(p,1),v.hooked=!1,v.playing=!1,v.started=!1,h(v.frames)):(v.playing||v.applying)&&(v.playing&&v.applying&&(v.applying=!1),v.started||r(t,f,e),n(t,f,e,i),a.fn(v.step)&&v.step.call(t,e),v.applying&&(v.applying=!1),h(v.frames),f.completed()&&(l.splice(p,1),v.hooked=!1,v.playing=!1,v.started=!1,h(v.completes)),c=!0)}return i||0!==l.length||0!==u.length||o.push(t),c}for(var i=c._private.aniEles,o=[],s=!1,l=0;l0){var p=i.updateCompoundBounds().spawnSelf().merge(i);c.notify({type:"draw",eles:p})}else c.notify({type:"draw"});i.unmerge(o),c.trigger("step")}function r(e,t,r){var n=a.core(e),i=!n,o=e,s=c._private.style,l=t._private;if(i){var u=o._private.position;l.startPosition=l.startPosition||{x:u.x,y:u.y},l.startStyle=l.startStyle||s.getAnimationStartStyle(o,l.style)}if(n){var d=c._private.pan;l.startPan=l.startPan||{x:d.x,y:d.y},l.startZoom=null!=l.startZoom?l.startZoom:c._private.zoom}l.started=!0,l.startTime=r-l.progress*l.duration}function n(e,t,r,n){var i=c._private.style,s=!n,l=e._private,d=t._private,h=d.easing,f=d.startTime;if(!d.easingImpl)if(null==h)d.easingImpl=p.linear;else{var v;if(a.string(h)){var g=i.parse("transition-timing-function",h);v=g.value}else v=h;var y,m;a.string(v)?(y=v,m=[]):(y=v[1],m=v.slice(2).map(function(e){return+e})),m.length>0?("spring"===y&&m.push(d.duration),d.easingImpl=p[y].apply(null,m)):d.easingImpl=p[y]}var b,x=d.easingImpl;if(b=0===d.duration?1:(r-f)/d.duration,d.applying&&(b=d.progress),0>b?b=0:b>1&&(b=1),null==d.delay){var w=d.startPosition,E=d.position,_=l.position;E&&s&&(o(w.x,E.x)&&(_.x=u(w.x,E.x,b,x)),o(w.y,E.y)&&(_.y=u(w.y,E.y,b,x)),e.trigger("position"));var P=d.startPan,S=d.pan,k=l.pan,T=null!=S&&n;T&&(o(P.x,S.x)&&(k.x=u(P.x,S.x,b,x)),o(P.y,S.y)&&(k.y=u(P.y,S.y,b,x)),e.trigger("pan"));var D=d.startZoom,C=d.zoom,M=null!=C&&n;M&&(o(D,C)&&(l.zoom=u(D,C,b,x)),e.trigger("zoom")),(T||M)&&e.trigger("viewport");var N=d.style;if(N&&N.length>0&&s){for(var B=0;Br?r=0:r>1&&(r=1);var i,o;if(i=null!=e.pfValue||null!=e.value?null!=e.pfValue?e.pfValue:e.value:e,o=null!=t.pfValue||null!=t.value?null!=t.pfValue?t.pfValue:t.value:t,a.number(i)&&a.number(o))return n(i,o,r);if(a.array(i)&&a.array(o)){for(var s=[],l=0;ld&&Math.abs(s.v)>d))break;return a?function(e){return u[e*(u.length-1)|0]}:c}}(),p={linear:function(e,t,r){return e+(t-e)*r},ease:l(.25,.1,.25,1),"ease-in":l(.42,0,1,1),"ease-out":l(0,0,.58,1),"ease-in-out":l(.42,0,.58,1),"ease-in-sine":l(.47,0,.745,.715),"ease-out-sine":l(.39,.575,.565,1),"ease-in-out-sine":l(.445,.05,.55,.95),"ease-in-quad":l(.55,.085,.68,.53),"ease-out-quad":l(.25,.46,.45,.94),"ease-in-out-quad":l(.455,.03,.515,.955),"ease-in-cubic":l(.55,.055,.675,.19),"ease-out-cubic":l(.215,.61,.355,1),"ease-in-out-cubic":l(.645,.045,.355,1),"ease-in-quart":l(.895,.03,.685,.22),"ease-out-quart":l(.165,.84,.44,1),"ease-in-out-quart":l(.77,0,.175,1),"ease-in-quint":l(.755,.05,.855,.06),"ease-out-quint":l(.23,1,.32,1),"ease-in-out-quint":l(.86,0,.07,1),"ease-in-expo":l(.95,.05,.795,.035),"ease-out-expo":l(.19,1,.22,1),"ease-in-out-expo":l(1,0,0,1),"ease-in-circ":l(.6,.04,.98,.335),"ease-out-circ":l(.075,.82,.165,1),"ease-in-out-circ":l(.785,.135,.15,.86),spring:function(e,t,r){if(0===r)return p.linear;var n=h(e,t,r);return function(e,t,r){return e+(t-e)*n(r)}},"cubic-bezier":function(e,t,r,n){return l(e,t,r,n)}}}}};t.exports=o},{"../define":44,"../is":83,"../util":100}],35:[function(e,t,r){"use strict";var n=e("../define"),i={on:n.on(),one:n.on({unbindSelfOnTrigger:!0}),once:n.on({unbindAllBindersOnTrigger:!0}),off:n.off(),trigger:n.trigger()};n.eventAliasesOn(i),t.exports=i},{"../define":44}],36:[function(e,t,r){"use strict";var n={png:function(e){var t=this._private.renderer;return e=e||{},t.png(e)},jpg:function(e){var t=this._private.renderer;return e=e||{},e.bg=e.bg||"#fff",t.jpg(e)}};n.jpeg=n.jpg,t.exports=n},{}],37:[function(e,t,r){"use strict";var n=e("../window"),i=e("../util"),a=e("../collection"),o=e("../is"),s=e("../promise"),l=e("../define"),u=function(e){var t=this;e=i.extend({},e);var r=e.container;r&&!o.htmlElement(r)&&o.htmlElement(r[0])&&(r=r[0]);var l=r?r._cyreg:null;l=l||{},l&&l.cy&&(l.cy.destroy(),l={});var u=l.readies=l.readies||[];r&&(r._cyreg=l),l.cy=t;var c=void 0!==n&&void 0!==r&&!e.headless,d=e;d.layout=i.extend({name:c?"grid":"null"},d.layout),d.renderer=i.extend({name:c?"canvas":"null"},d.renderer);var h=function(e,t,r){return void 0!==t?t:void 0!==r?r:e},p=this._private={container:r,ready:!1,initrender:!1,options:d,elements:new a(this),listeners:[],aniEles:new a(this),scratch:{},layout:null,renderer:null,notificationsEnabled:!0,minZoom:1e-50,maxZoom:1e50,zoomingEnabled:h(!0,d.zoomingEnabled),userZoomingEnabled:h(!0,d.userZoomingEnabled),panningEnabled:h(!0,d.panningEnabled),userPanningEnabled:h(!0,d.userPanningEnabled),boxSelectionEnabled:h(!0,d.boxSelectionEnabled),autolock:h(!1,d.autolock,d.autolockNodes),autoungrabify:h(!1,d.autoungrabify,d.autoungrabifyNodes),autounselectify:h(!1,d.autounselectify),styleEnabled:void 0===d.styleEnabled?c:d.styleEnabled,zoom:o.number(d.zoom)?d.zoom:1,pan:{x:o.plainObject(d.pan)&&o.number(d.pan.x)?d.pan.x:0,y:o.plainObject(d.pan)&&o.number(d.pan.y)?d.pan.y:0},animation:{current:[],queue:[]},hasCompoundNodes:!1},f=d.selectionType;void 0===f||"additive"!==f&&"single"!==f?p.selectionType="single":p.selectionType=f,o.number(d.minZoom)&&o.number(d.maxZoom)&&d.minZoom0?d.wheelSensitivity:1,motionBlur:void 0===d.motionBlur?!1:d.motionBlur,motionBlurOpacity:void 0===d.motionBlurOpacity?.05:d.motionBlurOpacity,pixelRatio:o.number(d.pixelRatio)&&d.pixelRatio>0?d.pixelRatio:void 0,desktopTapThreshold:void 0===d.desktopTapThreshold?4:d.desktopTapThreshold,touchTapThreshold:void 0===d.touchTapThreshold?8:d.touchTapThreshold},d.renderer)),v([d.style,d.elements],function(e){var r=e[0],n=e[1];p.styleEnabled&&t.setStyle(r),d.initrender&&(t.on("initrender",d.initrender),t.on("initrender",function(){p.initrender=!0})),t.load(n,function(){t.startAnimationLoop(),p.ready=!0,o.fn(d.ready)&&t.on("ready",d.ready);for(var e=0;e0;)t.removeChild(t.childNodes[0]);e._private.renderer=null},onRender:function(e){return this.on("render",e)},offRender:function(e){return this.off("render",e)}};i.invalidateDimensions=i.resize,t.exports=i},{"../util":100}],41:[function(e,t,r){"use strict";var n=e("../is"),i=e("../collection"),a={collection:function(e,t){return n.string(e)?this.$(e):n.elementOrCollection(e)?e.collection():n.array(e)?new i(this,e,t):new i(this)},nodes:function(e){var t=this.$(function(){return this.isNode()});return e?t.filter(e):t},edges:function(e){var t=this.$(function(){return this.isEdge()});return e?t.filter(e):t},$:function(e){var t=this._private.elements;return e?t.filter(e):t.spawnSelf()},mutableElements:function(){return this._private.elements}};a.elements=a.filter=a.$,t.exports=a},{"../collection":26,"../is":83}],42:[function(e,t,r){"use strict";var n=e("../is"),i=e("../style"),a={style:function(e){if(e){var t=this.setStyle(e);t.update()}return this._private.style},setStyle:function(e){var t=this._private;return n.stylesheet(e)?t.style=e.generateStyle(this):n.array(e)?t.style=i.fromJson(this,e):n.string(e)?t.style=i.fromString(this,e):t.style=i(this),t.style}};t.exports=a},{"../is":83,"../style":92}],43:[function(e,t,r){"use strict";var n=e("../is"),i={autolock:function(e){return void 0===e?this._private.autolock:(this._private.autolock=!!e,this)},autoungrabify:function(e){return void 0===e?this._private.autoungrabify:(this._private.autoungrabify=!!e,this)},autounselectify:function(e){return void 0===e?this._private.autounselectify:(this._private.autounselectify=!!e,this)},panningEnabled:function(e){return void 0===e?this._private.panningEnabled:(this._private.panningEnabled=!!e,this)},userPanningEnabled:function(e){return void 0===e?this._private.userPanningEnabled:(this._private.userPanningEnabled=!!e,this)},zoomingEnabled:function(e){return void 0===e?this._private.zoomingEnabled:(this._private.zoomingEnabled=!!e,this)},userZoomingEnabled:function(e){return void 0===e?this._private.userZoomingEnabled:(this._private.userZoomingEnabled=!!e,this)},boxSelectionEnabled:function(e){return void 0===e?this._private.boxSelectionEnabled:(this._private.boxSelectionEnabled=!!e,this)},pan:function(){var e,t,r,i,a,o=arguments,s=this._private.pan;switch(o.length){case 0:return s;case 1:if(n.string(o[0]))return e=o[0],s[e];if(n.plainObject(o[0])){if(!this._private.panningEnabled)return this;r=o[0],i=r.x,a=r.y,n.number(i)&&(s.x=i),n.number(a)&&(s.y=a),this.trigger("pan viewport")}break;case 2:if(!this._private.panningEnabled)return this;e=o[0],t=o[1],"x"!==e&&"y"!==e||!n.number(t)||(s[e]=t),this.trigger("pan viewport")}return this.notify({type:"viewport"}),this},panBy:function(e){var t,r,i,a,o,s=arguments,l=this._private.pan;if(!this._private.panningEnabled)return this;switch(s.length){case 1:n.plainObject(s[0])&&(i=s[0],a=i.x,o=i.y,n.number(a)&&(l.x+=a),n.number(o)&&(l.y+=o),this.trigger("pan viewport"));break;case 2:t=s[0],r=s[1],"x"!==t&&"y"!==t||!n.number(r)||(l[t]+=r),this.trigger("pan viewport")}return this.notify({type:"viewport"}),this},fit:function(e,t){var r=this.getFitViewport(e,t);if(r){var n=this._private;n.zoom=r.zoom,n.pan=r.pan,this.trigger("pan zoom viewport"),this.notify({type:"viewport"})}return this},getFitViewport:function(e,t){if(n.number(e)&&void 0===t&&(t=e,e=void 0),this._private.panningEnabled&&this._private.zoomingEnabled){var r;if(n.string(e)){var i=e;e=this.$(i)}else if(n.boundingBox(e)){var a=e;r={x1:a.x1,y1:a.y1,x2:a.x2,y2:a.y2},r.w=r.x2-r.x1,r.h=r.y2-r.y1}else n.elementOrCollection(e)||(e=this.mutableElements());r=r||e.boundingBox();var o,s=this.width(),l=this.height();if(t=n.number(t)?t:0,!isNaN(s)&&!isNaN(l)&&s>0&&l>0&&!isNaN(r.w)&&!isNaN(r.h)&&r.w>0&&r.h>0){o=Math.min((s-2*t)/r.w,(l-2*t)/r.h),o=o>this._private.maxZoom?this._private.maxZoom:o,o=othis._private.maxZoom?this._private.maxZoom:r,r=rt.maxZoom||!t.zoomingEnabled?o=!0:(t.zoom=l,a.push("zoom"))}if(i&&(!o||!e.cancelOnFailedZoom)&&t.panningEnabled){var u=e.pan;n.number(u.x)&&(t.pan.x=u.x,s=!1),n.number(u.y)&&(t.pan.y=u.y,s=!1),s||a.push("pan")}return a.length>0&&(a.push("viewport"),this.trigger(a.join(" ")),this.notify({type:"viewport"})),this},center:function(e){var t=this.getCenterPan(e);return t&&(this._private.pan=t,this.trigger("pan viewport"),this.notify({type:"viewport"})),this},getCenterPan:function(e,t){if(this._private.panningEnabled){if(n.string(e)){var r=e;e=this.mutableElements().filter(r)}else n.elementOrCollection(e)||(e=this.mutableElements());var i=e.boundingBox(),a=this.width(),o=this.height();t=void 0===t?this._private.zoom:t;var s={x:(a-t*(i.x1+i.x2))/2,y:(o-t*(i.y1+i.y2))/2};return s}},reset:function(){return this._private.panningEnabled&&this._private.zoomingEnabled?(this.viewport({pan:{x:0,y:0},zoom:1}),this):this},invalidateSize:function(){this._private.sizeCache=null},size:function(){var e=this._private,t=e.container;return e.sizeCache=e.sizeCache||(t?{width:t.clientWidth,height:t.clientHeight}:{width:1,height:1})},width:function(){return this.size().width},height:function(){return this.size().height},extent:function(){var e=this._private.pan,t=this._private.zoom,r=this.renderedExtent(),n={x1:(r.x1-e.x)/t,x2:(r.x2-e.x)/t,y1:(r.y1-e.y)/t,y2:(r.y2-e.y)/t};return n.w=n.x2-n.x1,n.h=n.y2-n.y1,n},renderedExtent:function(){var e=this.width(),t=this.height();return{x1:0,y1:0,x2:e,y2:t,w:e,h:t}}};i.centre=i.center,i.autolockNodes=i.autolock,i.autoungrabifyNodes=i.autoungrabify,t.exports=i},{"../is":83}],44:[function(e,t,r){"use strict";var n=e("./util"),i=e("./is"),a=e("./selector"),o=e("./promise"),s=e("./event"),l=e("./animation"),u={data:function(e){var t={field:"data",bindingEvent:"data",allowBinding:!1,allowSetting:!1,allowGetting:!1,settingEvent:"data",settingTriggersEvent:!1,triggerFnName:"trigger",immutableKeys:{},updateStyle:!1,onSet:function(e){},canSet:function(e){return!0}};return e=n.extend({},t,e),function(t,r){var n=e,a=this,o=void 0!==a.length,s=o?a:[a],l=o?a[0]:a;if(i.string(t)){if(n.allowGetting&&void 0===r){var u;return l&&(u=l._private[n.field][t]),u}if(n.allowSetting&&void 0!==r){var c=!n.immutableKeys[t];if(c){for(var d=0,h=s.length;h>d;d++)n.canSet(s[d])&&(s[d]._private[n.field][t]=r);n.updateStyle&&a.updateStyle(),n.onSet(a),n.settingTriggersEvent&&a[n.triggerFnName](n.settingEvent)}}}else if(n.allowSetting&&i.plainObject(t)){for(var p,f,v=t,g=Object.keys(v),d=0;du;u++){var c=s[u];if(!i.emptyString(c)){var d=!r.immutableKeys[c];if(d)for(var h=0,p=o.length;p>h;h++)o[h]._private[r.field][c]=void 0}}r.triggerEvent&&n[r.triggerFnName](r.event)}else if(void 0===t){for(var h=0,p=o.length;p>h;h++)for(var f=o[h]._private[r.field],s=Object.keys(f),u=0;u0:void 0}},clearQueue:function(e){var t={};return e=n.extend({},t,e),function(){var e=this,t=void 0!==e.length,r=t?e:[e],n=this._private.cy||this;if(!n.styleEnabled())return this;for(var i=0;i0;){var g=n.collection();i.bfs({roots:v[0],visit:function(e,t,r,n,i){g=g.add(r)},directed:!1}),v=v.not(g),f.push(g)}e=n.collection();for(var d=0;dD;){for(var C=k.shift(),M=C.neighborhood().nodes(),N=!1,d=0;dd;d++)for(var B=x[d],R=B.length,q=0;R>q;q++){var p=B[q],V=p._private.scratch.breadthfirst,F=I(p);F&&(V.intEle=F,A.push(p))}for(var d=0;dx.length-1;)x.push([]);x[X].push(p),V.depth=X,V.index=x[X].length-1}z()}var Y=0;if(r.avoidOverlap){for(var d=0;du||0===t)&&(n+=l/c,i++)}return i=Math.max(1,i),n/=i,0===i&&(n=void 0),Z[e.id()]=n,n},Q=function(e,t){var r=G(e),n=G(t);return r-n},K=0;3>K;K++){for(var d=0;d0&&x[0].length<=3?c/2:0),h=2*Math.PI/x[i].length*a;return 0===i&&1===x[0].length&&(d=1),{x:ee.x+d*Math.cos(h),y:ee.y+d*Math.sin(h)}}return{x:ee.x+(a+1-(o+1)/2)*s,y:(i+1)*l}}var p={x:ee.x+(a+1-(o+1)/2)*s,y:(i+1)*l};return t?p:p},re={},d=x.length-1;d>=0;d--)for(var B=x[d],q=0;q1&&t.avoidOverlap){p*=1.75;var b=Math.cos(h)-Math.cos(0),x=Math.sin(h)-Math.sin(0),w=Math.sqrt(p*p/(b*b+x*x));l=Math.max(w,l)}var E=function(e,r){var n=t.startAngle+e*h*(i?1:-1),a=l*Math.cos(n),o=l*Math.sin(n),s={x:c.x+a,y:c.y+o};return s};return s.layoutPositions(this,t,E),this},t.exports=n},{"../../is":83,"../../math":85,"../../util":100}],50:[function(e,t,r){"use strict";function n(e){this.options=i.extend({},o,e)}var i=e("../../util"),a=e("../../math"),o={fit:!0,padding:30,startAngle:1.5*Math.PI,sweep:void 0,clockwise:!0,equidistant:!1,minNodeSpacing:10,boundingBox:void 0,avoidOverlap:!0,height:void 0,width:void 0,concentric:function(e){return e.degree()},levelWidth:function(e){return e.maxDegree()/4},animate:!1,animationDuration:500,animationEasing:void 0,ready:void 0,stop:void 0};n.prototype.run=function(){for(var e=this.options,t=e,r=void 0!==t.counterclockwise?!t.counterclockwise:t.clockwise,n=e.cy,i=t.eles,o=i.nodes().not(":parent"),s=a.makeBoundingBox(t.boundingBox?t.boundingBox:{x1:0,y1:0,w:n.width(),h:n.height()}),l={x:s.x1+s.w/2,y:s.y1+s.h/2},u=[],c=t.startAngle,d=0,h=0;h0){var x=Math.abs(m[0].value-b.value);x>=g&&(m=[],y.push(m))}m.push(b)}var w=d+t.minNodeSpacing;if(!t.avoidOverlap){var E=y.length>0&&y[0].length>1,_=Math.min(s.w,s.h)/2-w,P=_/(y.length+E?1:0);w=Math.min(w,P)}for(var S=0,h=0;h1&&t.avoidOverlap){var C=Math.cos(D)-Math.cos(0),M=Math.sin(D)-Math.sin(0),N=Math.sqrt(w*w/(C*C+M*M));S=Math.max(N,S)}k.r=S,S+=w}if(t.equidistant){for(var B=0,S=0,h=0;ha;a++)for(var o=e.layoutNodes[e.idToIndex[n[a]]],l=a+1;i>l;l++){var u=e.layoutNodes[e.idToIndex[n[l]]];s(o,u,e,t)}},s=function(e,t,r,n){var i=e.cmptId,a=t.cmptId;if(i===a||r.isCompound){var o=t.positionX-e.positionX,s=t.positionY-e.positionY;if(0!==o||0!==s){var c=l(e,t,o,s);if(c>0)var d=n.nodeOverlap*c,h=Math.sqrt(o*o+s*s),p=d*o/h,f=d*s/h;else var v=u(e,o,s),g=u(t,-1*o,-1*s),y=g.x-v.x,m=g.y-v.y,b=y*y+m*m,h=Math.sqrt(b),d=(e.nodeRepulsion+t.nodeRepulsion)/b,p=d*y/h,f=d*m/h;e.isLocked||(e.offsetX-=p,e.offsetY-=f),t.isLocked||(t.offsetX+=p,t.offsetY+=f)}}},l=function(e,t,r,n){if(r>0)var i=e.maxX-t.minX;else var i=t.maxX-e.minX;if(n>0)var a=e.maxY-t.minY;else var a=t.maxY-e.minY;return i>=0&&a>=0?Math.sqrt(i*i+a*a):0},u=function(e,t,r){var n=e.positionX,i=e.positionY,a=e.height||1,o=e.width||1,s=r/t,l=a/o,u={};do{if(0===t&&r>0){u.x=n,u.y=i+a/2;break}if(0===t&&0>r){u.x=n,u.y=i+a/2;break}if(t>0&&s>=-1*l&&l>=s){u.x=n+o/2,u.y=i+o*r/2/t;break}if(0>t&&s>=-1*l&&l>=s){u.x=n-o/2,u.y=i-o*r/2/t;break}if(r>0&&(-1*l>=s||s>=l)){u.x=n+a*t/2/r,u.y=i+a/2;break}if(0>r&&(-1*l>=s||s>=l)){u.x=n-a*t/2/r,u.y=i-a/2;break}}while(!1);return u},c=function(e,t){for(var r=0;rc;c++){var d=e.layoutNodes[e.idToIndex[i[c]]];if(!d.isLocked){var h=o-d.positionX,p=s-d.positionY,f=Math.sqrt(h*h+p*p);if(f>r){var v=t.gravity*h/f,g=t.gravity*p/f;d.offsetX+=v,d.offsetY+=g}}}}},h=function(e,t){var r=[],n=0,i=-1;for(r.push.apply(r,e.graphSet[0]),i+=e.graphSet[0].length;i>=n;){var a=r[n++],o=e.idToIndex[a],s=e.layoutNodes[o],l=s.children;if(0r)var i={x:r*e/n,y:r*t/n};else var i={x:e,y:t};return i},v=function(e,t){var r=e.parentId;if(null!=r){var n=t.layoutNodes[t.idToIndex[r]],i=!1;return(null==n.maxX||e.maxX+n.padRight>n.maxX)&&(n.maxX=e.maxX+n.padRight,i=!0),(null==n.minX||e.minX-n.padLeftn.maxY)&&(n.maxY=e.maxY+n.padBottom,i=!0),(null==n.minY||e.minY-n.padTopy&&(f+=g+t.componentSpacing,p=0,v=0,g=0)}}},y=function(e){return i?!1:(a(r,n,e),r.temperature=r.temperature*n.coolingFactor,!(r.temperature=b;){var _=m[b++],P=a.idToIndex[_],f=a.layoutNodes[P],S=f.children;if(S.length>0){a.graphSet.push(S);for(var c=0;cn.count?0:n.graph},h=function(e,t,r,n){var i=n.graphSet[r];if(-1s){var v=d(),g=h();(v-1)*g>=s?d(v-1):(g-1)*v>=s&&h(g-1)}else for(;s>c*u;){var v=d(),g=h();(g+1)*v>=s?h(g+1):d(v+1)}var y=o.w/c,m=o.h/u;if(t.condense&&(y=0,m=0),t.avoidOverlap)for(var b=0;b=c&&(M=0,C++)},B={},b=0;b=o&&s>=e&&t>=l&&u>=t;return c},o=function(e,t,r,n,i){var a=e*Math.cos(n)-t*Math.sin(n),o=e*Math.sin(n)+t*Math.cos(n),s=a*r,l=o*r,u=s+i.x,c=l+i.y;return{x:u,y:c}},s=function(e,t,r,n){for(var i=[],a=0;at))if(d){if(d.pstyle("z-index").value===e.pstyle("z-index").value)for(var r=0;r(l=i.sqdistToFiniteLine(e,t,_[P],_[P+1],_[P+2],_[P+3]))&&a(n,l);else if("bezier"===c.edgeType||"multibezier"===c.edgeType||"self"===c.edgeType||"compound"===c.edgeType)for(var _=c.allpts,P=0;P+5(l=i.sqdistToQuadraticBezier(e,t,_[P],_[P+1],_[P+2],_[P+3],_[P+4],_[P+5]))&&a(n,l);if(w&&E())for(var y=y||o.source,x=x||o.target,S=n.pstyle("width").pfValue,k=p.getArrowWidth(S),T=[{name:"source",x:c.arrowStartX,y:c.arrowStartY,angle:c.srcArrowAngle},{name:"target",x:c.arrowEndX,y:c.arrowEndY,angle:c.tgtArrowAngle},{name:"mid-source",x:c.midX,y:c.midY,angle:c.midsrcArrowAngle},{name:"mid-target",x:c.midX,y:c.midY,angle:c.midtgtArrowAngle}],P=0;P0&&(s(y),s(x))}}function u(e,t,r){return o.getPrefixedProperty(e,t,r)}function c(r,n){var o,s=r._private,l=w;if(o=n?n+"-":"","no"!==r.pstyle("text-events").strValue){var c=r.pstyle(o+"text-rotation");if("autorotate"===c.strValue||c.pfValue){var d=s.rstyle,h=r.pstyle("text-border-width").pfValue,p=u(d,"labelWidth",n)+h/2+2*l,f=u(d,"labelHeight",n)+h/2+2*l,v=u(d,"labelX",n),g=u(d,"labelY",n),y=u(s.rscratch,"labelAngle",n),m=Math.cos(y),b=Math.sin(y),x=function(e,t){return e-=v,t-=g,{x:e*m-t*b+v,y:e*b+t*m+g}},E=v-p/2,_=v+p/2,P=g-f/2,S=g+f/2,k=x(E,P),T=x(E,S),D=x(_,P),C=x(_,S),M=[k.x,k.y,D.x,D.y,C.x,C.y,T.x,T.y];i.pointInsidePolygonPoints(e,t,M)&&a(r)}else{var N=r.boundingBox({includeLabels:!0,includeNodes:!1,includeEdges:!1});N.x1-=l,N.y1-=l,N.x2+=l,N.y2+=l,N.w=N.x2-N.x1,N.h=N.y2-N.y1,i.inBoundingBox(N,e,t)&&a(r)}}}for(var d,h,p=this,f=this,v=f.getCachedZSortedEles(),g=[],y=f.cy.zoom(),m=f.cy.hasCompoundNodes(),b=(n?24:8)/y,x=(n?8:2)/y,w=(n?8:2)/y,E=1/0,_=v.length-1;_>=0;_--){var P=v[_];P.isNode()?(s(P),c(P)):(l(P),c(P),c(P,"source"),c(P,"target"))}return g},l.getAllInBox=function(e,t,r,n){var a=this.getCachedZSortedEles(),o=a.nodes,s=a.edges,l=[],u=Math.min(e,r),c=Math.max(e,r),d=Math.min(t,n),h=Math.max(t,n);e=u,r=c,t=d,n=h;for(var p=i.makeBoundingBox({x1:e,y1:t,x2:r,y2:n}),f=0;fv;v++)e(p,d[o*h+v],d[o*h+v+1],a.bezierProjPcts[v],a.bezierProjPcts[v+1]);e(p,d[o*h+h-1],p.p2,a.bezierProjPcts[h-1],1)}return u.cache=t},c=function(r){var a,o="source"===r;if(s[r]){var c=e.pstyle(r+"-text-offset").pfValue,d=function(e,t){var r=t.x-e.x,n=t.y-e.y;return Math.atan(n/r)},h=function(e,t,r,n){var a=i.bound(0,n-.001,1),o=i.bound(0,n+.001,1),s=i.qbezierPtAt(e,t,r,a),l=i.qbezierPtAt(e,t,r,o);return d(s,l)};switch(n.edgeType){case"self":case"compound":case"bezier":case"multibezier":for(var p,f=u(),v=0,g=0,y=0;y=c||w){p={cp:m,segment:x};break}}if(p)break}var m=p.cp,x=p.segment,E=(c-v)/x.length,_=x.t1-x.t0,P=o?x.t0+_*E:x.t1-_*E;P=i.bound(0,P,1),t=i.qbezierPtAt(m.p0,m.p1,m.p2,P),a=h(m.p0,m.p1,m.p2,P,t);break;case"straight":case"segments":case"haystack":for(var S,k,T,D,C=0,M=n.allpts.length,y=0;M>y+3&&(o?(T={x:n.allpts[y],y:n.allpts[y+1]},D={x:n.allpts[y+2],y:n.allpts[y+3]}):(T={x:n.allpts[M-2-y],y:n.allpts[M-1-y]},D={x:n.allpts[M-4-y],y:n.allpts[M-3-y]}),S=i.dist(T,D),k=C,C+=S,!(C>=c));y+=2);var N=c-k,P=N/S;P=i.bound(0,P,1),t=i.lineAt(T,D,P),a=d(T,D)}l("labelX",r,t.x),l("labelY",r,t.y),l("labelAutoAngle",r,a)}};c("source"),c("target"),this.applyLabelDimensions(e)}},l.applyLabelDimensions=function(e){this.applyPrefixedLabelDimensions(e),e.isEdge()&&(this.applyPrefixedLabelDimensions(e,"source"),this.applyPrefixedLabelDimensions(e,"target"))},l.applyPrefixedLabelDimensions=function(e,t){var r=e._private,n=this.getLabelText(e,t),i=this.calculateLabelDimensions(e,n);o.setPrefixedProperty(r.rstyle,"labelWidth",t,i.width),o.setPrefixedProperty(r.rscratch,"labelWidth",t,i.width),o.setPrefixedProperty(r.rstyle,"labelHeight",t,i.height),o.setPrefixedProperty(r.rscratch,"labelHeight",t,i.height)},l.getLabelText=function(e,t){var r=e._private,n=t?t+"-":"",i=e.pstyle(n+"label").strValue,a=e.pstyle("text-transform").value,s=function(e,n){return n?(o.setPrefixedProperty(r.rscratch,e,t,n),n):o.getPrefixedProperty(r.rscratch,e,t)};if("none"==a||("uppercase"==a?i=i.toUpperCase():"lowercase"==a&&(i=i.toLowerCase())),"wrap"===e.pstyle("text-wrap").value){var l=s("labelKey");if(l&&s("labelWrapKey")===l)return s("labelWrapCachedText");for(var u=i.split("\n"),c=e.pstyle("text-max-width").pfValue,d=[],h=0;hc){for(var g=p.split(/\s+/),y="",m=0;m=E?y+=b+" ":(d.push(y),y=b+" ")}y.match(/^\s+$/)||d.push(y)}else d.push(p)}s("labelWrapCachedLines",d),i=s("labelWrapCachedText",d.join("\n")),s("labelWrapKey",l)}return i},l.calculateLabelDimensions=function(e,t,r){var n=this,i=e._private.labelStyleKey+"$@$"+t;r&&(i+="$@$"+r);var a=n.labelDimCache||(n.labelDimCache={});if(a[i])return a[i];var o=1,s=e.pstyle("font-style").strValue,l=o*e.pstyle("font-size").pfValue+"px",u=e.pstyle("font-family").strValue,c=e.pstyle("font-weight").strValue,d=this.labelCalcDiv;d||(d=this.labelCalcDiv=document.createElement("div"),document.body.appendChild(d));var h=d.style;return h.fontFamily=u,h.fontStyle=s,h.fontSize=l,h.fontWeight=c,h.position="absolute",h.left="-9999px",h.top="-9999px",h.zIndex="-1",h.visibility="hidden",h.pointerEvents="none",h.padding="0",h.lineHeight="1","wrap"===e.pstyle("text-wrap").value?h.whiteSpace="pre":h.whiteSpace="normal",d.textContent=t,a[i]={width:Math.ceil(d.clientWidth/o),height:Math.ceil(d.clientHeight/o)},a[i]},l.recalculateLabelProjections=function(e,t){for(var r=0;ry?y+"$-$"+g:g+"$-$"+y,v&&(t="unbundled$-$"+p.id),null==s[t]&&(s[t]=[],l.push(t)),s[t].push(d),v&&(s[t].hasUnbundled=!0)}else u.push(d)}for(var m,b,x,w,E,_,P,S,k,T,D,C,M,N,B=0;Bb.id()){var I=m;m=b,b=I}if(x=m._private,w=b._private,E=x.position,_=w.position,P=m.outerWidth(),S=m.outerHeight(),k=b.outerWidth(),T=b.outerHeight(),D=r.nodeShapes[this.getNodeShape(m)],C=r.nodeShapes[this.getNodeShape(b)],N=!1,z.length>1&&m!==b||z.hasUnbundled){var L=D.intersectLine(E.x,E.y,P,S,_.x,_.y,0),O=C.intersectLine(_.x,_.y,k,T,E.x,E.y,0),A={x1:L[0],x2:O[0],y1:L[1],y2:O[1]},R={x1:E.x,x2:_.x,y1:E.y,y2:_.y},q=O[1]-L[1],V=O[0]-L[0],F=Math.sqrt(V*V+q*q),j={x:V,y:q},X={x:j.x/F,y:j.y/F};M={x:-X.y,y:X.x},C.checkPoint(L[0],L[1],0,k,T,_.x,_.y)&&D.checkPoint(O[0],O[1],0,P,S,E.x,E.y)&&(M={},N=!0)}for(var d,Y,W,c=0;cze;ze++){var Ie=Me[ze],Le=Ne[ze],Oe=1-Ie,Ae=Ie,Re="node-position"===xe?R:A,qe={x:Re.x1*Oe+Re.x2*Ae,y:Re.y1*Oe+Re.y2*Ae};W.segpts.push(qe.x+M.x*Le,qe.y+M.y*Le)}}else if(z.length%2!==1||c!==Math.floor(z.length/2)||v){var Ve=v;W.edgeType=Ve?"multibezier":"bezier",W.ctrlpts=[];for(var Fe=0;K>Fe;Fe++){var je,Xe=(.5-z.length/2+c)*J,Ye=i.signum(Xe);Ve&&(ee=G?G.pfValue[Fe]:J,te=Q.value[Fe]),je=v?ee:void 0!==ee?Ye*ee:void 0;var We=void 0!==je?je:Xe,Oe=1-te,Ae=te,Re="node-position"===xe?R:A,qe={x:Re.x1*Oe+Re.x2*Ae,y:Re.y1*Oe+Re.y2*Ae};W.ctrlpts.push(qe.x+M.x*We,qe.y+M.y*We)}}else W.edgeType="straight";this.findEndpoints(d);var $e=!a.number(W.startX)||!a.number(W.startY),He=!a.number(W.arrowStartX)||!a.number(W.arrowStartY),Ue=!a.number(W.endX)||!a.number(W.endY),Ze=!a.number(W.arrowEndX)||!a.number(W.arrowEndY),Ge=3,Qe=this.getArrowWidth(d.pstyle("width").pfValue)*this.arrowShapeWidth,Ke=Ge*Qe;if("bezier"===W.edgeType){var Je=i.dist({x:W.ctrlpts[0],y:W.ctrlpts[1]},{x:W.startX,y:W.startY}),et=Ke>Je,tt=i.dist({x:W.ctrlpts[0],y:W.ctrlpts[1]},{x:W.endX,y:W.endY}),rt=Ke>tt,nt=!1;if($e||He||et){nt=!0;var it={x:W.ctrlpts[0]-E.x,y:W.ctrlpts[1]-E.y},at=Math.sqrt(it.x*it.x+it.y*it.y),ot={x:it.x/at,y:it.y/at},st=Math.max(P,S),lt={x:W.ctrlpts[0]+2*ot.x*st,y:W.ctrlpts[1]+2*ot.y*st},ut=D.intersectLine(E.x,E.y,P,S,lt.x,lt.y,0);et?(W.ctrlpts[0]=W.ctrlpts[0]+ot.x*(Ke-Je),W.ctrlpts[1]=W.ctrlpts[1]+ot.y*(Ke-Je)):(W.ctrlpts[0]=ut[0]+ot.x*Ke,W.ctrlpts[1]=ut[1]+ot.y*Ke)}if(Ue||Ze||rt){nt=!0;var it={x:W.ctrlpts[0]-_.x,y:W.ctrlpts[1]-_.y},at=Math.sqrt(it.x*it.x+it.y*it.y),ot={x:it.x/at,y:it.y/at},st=Math.max(P,S),lt={x:W.ctrlpts[0]+2*ot.x*st,y:W.ctrlpts[1]+2*ot.y*st},ct=C.intersectLine(_.x,_.y,k,T,lt.x,lt.y,0);rt?(W.ctrlpts[0]=W.ctrlpts[0]+ot.x*(Ke-tt),W.ctrlpts[1]=W.ctrlpts[1]+ot.y*(Ke-tt)):(W.ctrlpts[0]=ct[0]+ot.x*Ke,W.ctrlpts[1]=ct[1]+ot.y*Ke)}nt&&this.findEndpoints(d)}if("multibezier"===W.edgeType||"bezier"===W.edgeType||"self"===W.edgeType||"compound"===W.edgeType){W.allpts=[],W.allpts.push(W.startX,W.startY);for(var Fe=0;Fe+1c[0]&&i.clientXc[1]&&i.clientY=e.desktopTapThreshold2}var I=r(i);P&&(e.hoverData.tapholdCancelled=!0);var L=function(){var t=e.hoverData.dragDelta=e.hoverData.dragDelta||[];0===t.length?(t.push(T[0]),t.push(T[1])):(t[0]+=T[0],t[1]+=T[1])};if(l=!0,t(_,["mousemove","vmousemove","tapdrag"],i,{cyPosition:{x:b[0],y:b[1]}}),3===e.hoverData.which){if(P){var O=new o(i,{type:"cxtdrag",cyPosition:{x:b[0],y:b[1]}});k?k.trigger(O):v.trigger(O),e.hoverData.cxtDragged=!0,e.hoverData.cxtOver&&_===e.hoverData.cxtOver||(e.hoverData.cxtOver&&e.hoverData.cxtOver.trigger(new o(i,{type:"cxtdragout",cyPosition:{x:b[0],y:b[1]}})),e.hoverData.cxtOver=_,_&&_.trigger(new o(i,{type:"cxtdragover",cyPosition:{x:b[0],y:b[1]}})))}}else if(e.hoverData.dragging){if(l=!0,v.panningEnabled()&&v.userPanningEnabled()){var A;if(e.hoverData.justStartedPan){var R=e.hoverData.mdownPos;A={x:(b[0]-R[0])*g,y:(b[1]-R[1])*g},e.hoverData.justStartedPan=!1}else A={x:T[0]*g,y:T[1]*g};v.panBy(A),e.hoverData.dragged=!0}b=e.projectIntoViewport(i.clientX,i.clientY)}else if(1!=E[4]||null!=k&&!k.isEdge()){if(k&&k.isEdge()&&k.active()&&k.unactivate(),k&&k.grabbed()||_==S||(S&&t(S,["mouseout","tapdragout"],i,{cyPosition:{x:b[0],y:b[1]}}),_&&t(_,["mouseover","tapdragover"],i,{cyPosition:{x:b[0],y:b[1]}}),e.hoverData.last=_),k&&e.nodeIsDraggable(k))if(P){var q=!e.dragData.didDrag;q&&e.redrawHint("eles",!0),e.dragData.didDrag=!0;var V=[];e.hoverData.draggingEles||y(v.collection(D),{inDragLayer:!0});for(var F=0;F0&&e.redrawHint("eles",!0),e.dragData.possibleDragElements=c=[]),t(u,["mouseup","tapend","vmouseup"],n,{cyPosition:{x:s[0],y:s[1]}}),e.dragData.didDrag||e.hoverData.dragged||e.hoverData.selecting||t(d,["click","tap","vclick"],n,{cyPosition:{x:s[0],y:s[1]}}),u!=d||e.dragData.didDrag||e.hoverData.selecting||null!=u&&u._private.selectable&&(e.hoverData.dragging||("additive"===a.selectionType()||h?u.selected()?u.unselect():u.select():h||(a.$(":selected").unmerge(u).unselect(),u.select())),e.redrawHint("eles",!0)),e.hoverData.selecting){var v=a.collection(e.getAllInBox(l[0],l[1],l[2],l[3]));e.redrawHint("select",!0),v.length>0&&e.redrawHint("eles",!0),a.trigger("boxend");var g=function(e){return e.selectable()&&!e.selected()};"additive"===a.selectionType()?v.trigger("box").stdFilter(g).select().trigger("boxselect"):(h||a.$(":selected").unmerge(v).unselect(),v.trigger("box").stdFilter(g).select().trigger("boxselect")),e.redraw()}if(e.hoverData.dragging&&(e.hoverData.dragging=!1,e.redrawHint("select",!0),e.redrawHint("eles",!0),e.redraw()),!l[4]){e.redrawHint("drag",!0),e.redrawHint("eles",!0);var y=d&&d.grabbed();b(c),y&&d.trigger("free")}}l[4]=0,e.hoverData.down=null,e.hoverData.cxtStarted=!1,e.hoverData.draggingEles=!1,e.hoverData.selecting=!1,e.dragData.didDrag=!1,e.hoverData.dragged=!1,e.hoverData.dragDelta=[],e.hoverData.mdownPos=null,e.hoverData.mdownGPos=null}},!1);var k=function(t){if(!e.scrollingPage){var r=e.cy,n=e.projectIntoViewport(t.clientX,t.clientY),i=[n[0]*r.zoom()+r.pan().x,n[1]*r.zoom()+r.pan().y];if(e.hoverData.draggingEles||e.hoverData.dragging||e.hoverData.cxtStarted||S())return void t.preventDefault();if(r.panningEnabled()&&r.userPanningEnabled()&&r.zoomingEnabled()&&r.userZoomingEnabled()){t.preventDefault(),e.data.wheelZooming=!0,clearTimeout(e.data.wheelTimeout),e.data.wheelTimeout=setTimeout(function(){e.data.wheelZooming=!1,e.redrawHint("eles",!0),e.redraw()},150);var a=t.deltaY/-250||t.wheelDeltaY/1e3||t.wheelDelta/1e3;a*=e.wheelSensitivity;var o=1===t.deltaMode;o&&(a*=33),r.zoom({level:r.zoom()*Math.pow(10,a),renderedPosition:{x:i[0],y:i[1]}})}}};e.registerBinding(e.container,"wheel",k,!0),e.registerBinding(window,"scroll",function(t){e.scrollingPage=!0,clearTimeout(e.scrollingPageTimeout),e.scrollingPageTimeout=setTimeout(function(){e.scrollingPage=!1},250)},!0),e.registerBinding(e.container,"mouseout",function(t){var r=e.projectIntoViewport(t.clientX,t.clientY);e.cy.trigger(new o(t,{type:"mouseout",cyPosition:{x:r[0],y:r[1]}}))},!1),e.registerBinding(e.container,"mouseover",function(t){var r=e.projectIntoViewport(t.clientX,t.clientY);e.cy.trigger(new o(t,{type:"mouseover",cyPosition:{x:r[0],y:r[1]}}))},!1);var T,D,C,M,N,B,z,I,L,O,A,R,q,V,F=function(e,t,r,n){return Math.sqrt((r-e)*(r-e)+(n-t)*(n-t))},j=function(e,t,r,n){return(r-e)*(r-e)+(n-t)*(n-t)};e.registerBinding(e.container,"touchstart",V=function(r){e.touchData.capture=!0,e.data.bgActivePosistion=void 0;var n=e.cy,i=e.touchData.now,a=e.touchData.earlier;if(r.touches[0]){var s=e.projectIntoViewport(r.touches[0].clientX,r.touches[0].clientY);i[0]=s[0],i[1]=s[1]}if(r.touches[1]){var s=e.projectIntoViewport(r.touches[1].clientX,r.touches[1].clientY);i[2]=s[0],i[3]=s[1]}if(r.touches[2]){var s=e.projectIntoViewport(r.touches[2].clientX,r.touches[2].clientY);i[4]=s[0],i[5]=s[1]}if(r.touches[1]){b(e.dragData.touchDragEles);var l=e.findContainerClientCoords();L=l[0],O=l[1],A=l[2],R=l[3],T=r.touches[0].clientX-L,D=r.touches[0].clientY-O,C=r.touches[1].clientX-L,M=r.touches[1].clientY-O,q=T>=0&&A>=T&&C>=0&&A>=C&&D>=0&&R>=D&&M>=0&&R>=M;var u=n.pan(),c=n.zoom();N=F(T,D,C,M),B=j(T,D,C,M),z=[(T+C)/2,(D+M)/2],I=[(z[0]-u.x)/c,(z[1]-u.y)/c];var d=200,h=d*d;if(h>B&&!r.touches[2]){var f=e.findNearestElement(i[0],i[1],!0,!0),v=e.findNearestElement(i[2],i[3],!0,!0);return f&&f.isNode()?(f.activate().trigger(new o(r,{type:"cxttapstart",cyPosition:{x:i[0],y:i[1]}})),e.touchData.start=f):v&&v.isNode()?(v.activate().trigger(new o(r,{type:"cxttapstart",cyPosition:{x:i[0],y:i[1]}})),e.touchData.start=v):(n.trigger(new o(r,{type:"cxttapstart",cyPosition:{x:i[0],y:i[1]}})),e.touchData.start=null),e.touchData.start&&(e.touchData.start._private.grabbed=!1),e.touchData.cxt=!0,e.touchData.cxtDragged=!1,e.data.bgActivePosistion=void 0,void e.redraw()}}if(r.touches[2]);else if(r.touches[1]);else if(r.touches[0]){var g=e.findNearestElements(i[0],i[1],!0,!0),x=g[0];if(null!=x&&(x.activate(),e.touchData.start=x,e.touchData.starts=g,e.nodeIsGrabbable(x))){var w=e.dragData.touchDragEles=[];if(e.redrawHint("eles",!0),e.redrawHint("drag",!0),x.selected()){var E=n.$(function(){return this.selected()&&e.nodeIsGrabbable(this)});y(E,{addToList:w})}else m(x,{addToList:w});p(x),x.trigger(new o(r,{type:"grab",cyPosition:{x:i[0],y:i[1]}}))}t(x,["touchstart","tapstart","vmousedown"],r,{cyPosition:{x:i[0],y:i[1]}}),null==x&&(e.data.bgActivePosistion={x:s[0],y:s[1]},e.redrawHint("select",!0),e.redraw()),e.touchData.startPosition=[];for(var _=0;_=e.touchTapThreshold2}if(l&&e.touchData.cxt){r.preventDefault();var S=r.touches[0].clientX-L,k=r.touches[0].clientY-O,z=r.touches[1].clientX-L,A=r.touches[1].clientY-O,R=j(S,k,z,A),V=R/B,X=150,Y=X*X,W=1.5,$=W*W;if(V>=$||R>=Y){e.touchData.cxt=!1,e.touchData.start&&(e.touchData.start.unactivate(),e.touchData.start=null),e.data.bgActivePosistion=void 0,e.redrawHint("select",!0);var H=new o(r,{type:"cxttapend",cyPosition:{x:c[0],y:c[1]}});e.touchData.start?e.touchData.start.trigger(H):u.trigger(H)}}if(l&&e.touchData.cxt){var H=new o(r,{type:"cxtdrag",cyPosition:{x:c[0],y:c[1]}});e.data.bgActivePosistion=void 0,e.redrawHint("select",!0),e.touchData.start?e.touchData.start.trigger(H):u.trigger(H),e.touchData.start&&(e.touchData.start._private.grabbed=!1),e.touchData.cxtDragged=!0;var U=e.findNearestElement(c[0],c[1],!0,!0);e.touchData.cxtOver&&U===e.touchData.cxtOver||(e.touchData.cxtOver&&e.touchData.cxtOver.trigger(new o(r,{type:"cxtdragout",cyPosition:{x:c[0],y:c[1]}})),e.touchData.cxtOver=U,U&&U.trigger(new o(r,{type:"cxtdragover",cyPosition:{x:c[0],y:c[1]}})))}else if(l&&r.touches[2]&&u.boxSelectionEnabled())r.preventDefault(),e.data.bgActivePosistion=void 0,this.lastThreeTouch=+new Date,e.touchData.selecting||u.trigger("boxstart"),e.touchData.selecting=!0,e.redrawHint("select",!0),i&&0!==i.length&&void 0!==i[0]?(i[2]=(c[0]+c[2]+c[4])/3,i[3]=(c[1]+c[3]+c[5])/3):(i[0]=(c[0]+c[2]+c[4])/3,i[1]=(c[1]+c[3]+c[5])/3,i[2]=(c[0]+c[2]+c[4])/3+1,i[3]=(c[1]+c[3]+c[5])/3+1),i[4]=1,e.touchData.selecting=!0,e.redraw();else if(l&&r.touches[1]&&u.zoomingEnabled()&&u.panningEnabled()&&u.userZoomingEnabled()&&u.userPanningEnabled()){r.preventDefault(),e.data.bgActivePosistion=void 0,e.redrawHint("select",!0);var Z=e.dragData.touchDragEles;if(Z){e.redrawHint("drag",!0);for(var G=0;G=e*e+t*t}}},i.generateRoundRectangle=function(){return this.nodeShapes.roundrectangle={renderer:this,name:"roundrectangle",points:n.generateUnitNgonPointsFitToSquare(4,0),draw:function(e,t,r,n,i){this.renderer.nodeShapeImpl(this.name,e,t,r,n,i)},intersectLine:function(e,t,r,i,a,o,s){return n.roundRectangleIntersectLine(a,o,e,t,r,i,s)},checkPoint:function(e,t,r,i,a,o,s){var l=n.getRoundRectangleRadius(i,a);if(n.pointInsidePolygon(e,t,this.points,o,s,i,a-2*l,[0,-1],r))return!0;if(n.pointInsidePolygon(e,t,this.points,o,s,i-2*l,a,[0,-1],r))return!0;var u=function(e,t,r,n,i,a,o){return e-=r,t-=n,e/=i/2+o,t/=a/2+o,1>=e*e+t*t};return u(e,t,o-i/2+l,s-a/2+l,2*l,2*l,r)?!0:u(e,t,o+i/2-l,s-a/2+l,2*l,2*l,r)?!0:u(e,t,o+i/2-l,s+a/2-l,2*l,2*l,r)?!0:!!u(e,t,o-i/2+l,s+a/2-l,2*l,2*l,r)}}},i.registerNodeShapes=function(){var e=this.nodeShapes={},t=this;this.generateEllipse(),this.generatePolygon("triangle",n.generateUnitNgonPointsFitToSquare(3,0)),this.generatePolygon("rectangle",n.generateUnitNgonPointsFitToSquare(4,0)),e.square=e.rectangle,this.generateRoundRectangle(),this.generatePolygon("diamond",[0,1,1,0,0,-1,-1,0]),this.generatePolygon("pentagon",n.generateUnitNgonPointsFitToSquare(5,0)),this.generatePolygon("hexagon",n.generateUnitNgonPointsFitToSquare(6,0)),this.generatePolygon("heptagon",n.generateUnitNgonPointsFitToSquare(7,0)),this.generatePolygon("octagon",n.generateUnitNgonPointsFitToSquare(8,0));var r=new Array(20),i=n.generateUnitNgonPoints(5,0),a=n.generateUnitNgonPoints(5,Math.PI/5),o=.5*(3-Math.sqrt(5));o*=1.57;for(var s=0;ss;s++)r[4*s]=i[2*s],r[4*s+1]=i[2*s+1],r[4*s+2]=a[2*s],r[4*s+3]=a[2*s+1];r=n.fitPolygonToSquare(r),this.generatePolygon("star",r),this.generatePolygon("vee",[-1,-1,0,-.333,1,-1,0,1]),this.generatePolygon("rhomboid",[-1,-1,.333,-1,1,1,-.333,1]),e.makePolygon=function(e){var r,n=e.join("$"),i="polygon-"+n;return(r=this[i])?r:t.generatePolygon(i,e)}},t.exports=i},{"../../../math":85}],63:[function(e,t,r){"use strict";var n=e("../../../util"),i={};i.timeToRender=function(){return this.redrawTotalTime/this.redrawCount},i.redraw=function(e){e=e||n.staticEmptyObject();var t=this;void 0===t.averageRedrawTime&&(t.averageRedrawTime=0),void 0===t.lastRedrawTime&&(t.lastRedrawTime=0),void 0===t.lastDrawTime&&(t.lastDrawTime=0),t.requestedFrame=!0,t.renderOptions=e},i.beforeRender=function(e,t){t=t||0;var r=this.beforeRenderCallbacks;r.push({fn:e,priority:t}),r.sort(function(e,t){return t.priority-e.priority})};var a=function(e,t,r){for(var n=e.beforeRenderCallbacks,i=0;io)},o.drawElementText=function(e,t,r){var n=this;if(void 0===r){if(!n.eleTextBiggerThanMin(t))return}else if(!r)return;if(t.isNode()){var i=t.pstyle("label");if(!i||!i.value)return;var a=t.pstyle("text-halign").strValue;t.pstyle("text-valign").strValue;switch(a){case"left":e.textAlign="right";break;case"right":e.textAlign="left";break;default:e.textAlign="center"}e.textBaseline="bottom"}else{var i=t.pstyle("label"),o=t.pstyle("source-label"),s=t.pstyle("target-label");if(!(i&&i.value||o&&o.value||s&&s.value))return;e.textAlign="center",e.textBaseline="bottom"}n.drawText(e,t),t.isEdge()&&(n.drawText(e,t,"source"),n.drawText(e,t,"target"))},o.drawNodeText=o.drawEdgeText=o.drawElementText,o.getFontCache=function(e){var t;this.fontCaches=this.fontCaches||[];for(var r=0;r0||N>0&&M>0){var B=l;switch(b){case"left":B-=h;break;case"center":B-=h/2;break;case"right":}var z=u;switch(x){case"top":z-=p;break;case"center":z-=p/2;break;case"bottom":}if(C>0){var I=e.fillStyle,L=t.pstyle("text-background-color").value;e.fillStyle="rgba("+L[0]+","+L[1]+","+L[2]+","+C*s+")";var O=t.pstyle("text-background-shape").strValue;"roundrectangle"==O?n(e,B,z,h,p,2):e.fillRect(B,z,h,p),e.fillStyle=I}if(N>0&&M>0){var A=e.strokeStyle,R=e.lineWidth,q=t.pstyle("text-border-color").value,V=t.pstyle("text-border-style").value;if(e.strokeStyle="rgba("+q[0]+","+q[1]+","+q[2]+","+M*s+")",e.lineWidth=N,e.setLineDash)switch(V){case"dotted":e.setLineDash([1,1]);break;case"dashed":e.setLineDash([4,2]);break;case"double":e.lineWidth=N/4,e.setLineDash([]);break;case"solid":e.setLineDash([])}if(e.strokeRect(B,z,h,p),"double"===V){var F=N/2;e.strokeRect(B+F,z+F,h-2*F,p-2*F)}e.setLineDash&&e.setLineDash([]), -e.lineWidth=R,e.strokeStyle=A}}var j=2*t.pstyle("text-outline-width").pfValue;if(j>0&&(e.lineWidth=j),"wrap"===t.pstyle("text-wrap").value){var X=o.labelWrapCachedLines,Y=p/X.length;switch(x){case"top":u-=(X.length-1)*Y;break;case"bottom":break;default:case"center":u-=(X.length-1)*Y/2}for(var W=0;W0&&e.strokeText(X[W],l,u),e.fillText(X[W],l,u),u+=Y}else j>0&&e.strokeText(c,l,u),e.fillText(c,l,u);0!==w&&(e.rotate(-w),e.translate(-_,-P)),this.shadowStyle(e,"transparent",0)}}},t.exports=o},{"../../../math":85,"../../../util":100}],69:[function(e,t,r){"use strict";var n=e("../../../is"),i={};i.drawNode=function(e,t,r,i){var a,o,s=this,l=t._private.rscratch,u=t._private,c=c||u.position;if(n.number(c.x)&&n.number(c.y)){var d,h=this.usePaths(),p=!1,f=t.effectiveOpacity();if(0!==f){a=t.width()+t.pstyle("padding-left").pfValue+t.pstyle("padding-right").pfValue,o=t.height()+t.pstyle("padding-top").pfValue+t.pstyle("padding-bottom").pfValue,e.lineWidth=t.pstyle("border-width").pfValue;var v;r&&(v=r,e.translate(-v.x1,-v.y1));var g,y=t.pstyle("background-image"),m=y.value[2]||y.value[1];if(void 0!==m){g=this.getCachedImage(m,function(){t.trigger("background"),s.redrawHint("eles",!0),s.redrawHint("drag",!0),s.drawingImage=!0,s.redraw()});var b=u.backgrounding;u.backgrounding=!g.complete,b!==u.backgrounding&&t.updateStyle(!1)}var x=t.pstyle("background-color").value,w=t.pstyle("border-color").value,E=t.pstyle("border-style").value;this.fillStyle(e,x[0],x[1],x[2],t.pstyle("background-opacity").value*f),this.strokeStyle(e,w[0],w[1],w[2],t.pstyle("border-opacity").value*f);var _=t.pstyle("shadow-blur").pfValue,P=t.pstyle("shadow-opacity").value,S=t.pstyle("shadow-color").value,k=t.pstyle("shadow-offset-x").pfValue,T=t.pstyle("shadow-offset-y").pfValue;if(this.shadowStyle(e,S,P,_,k,T),e.lineJoin="miter",e.setLineDash)switch(E){case"dotted":e.setLineDash([1,1]);break;case"dashed":e.setLineDash([4,2]);break;case"solid":case"double":e.setLineDash([])}var D=t.pstyle("shape").strValue,C=t.pstyle("shape-polygon-points").pfValue;if(h){var M=D+"$"+a+"$"+o+("polygon"===D?"$"+C.join("$"):"");e.translate(c.x,c.y),l.pathCacheKey===M?(d=l.pathCache,p=!0):(d=new Path2D,l.pathCacheKey=M,l.pathCache=d)}if(!p){var N=c;h&&(N={x:0,y:0}),s.nodeShapes[this.getNodeShape(t)].draw(d||e,N.x,N.y,a,o)}h?e.fill(d):e.fill(),this.shadowStyle(e,"transparent",0),void 0!==m&&g.complete&&this.drawInscribedImage(e,g,t);var B=t.pstyle("background-blacken").value,z=t.pstyle("border-width").pfValue;if(this.hasPie(t)&&(this.drawPie(e,t,f),0===B&&0===z||h||s.nodeShapes[this.getNodeShape(t)].draw(e,c.x,c.y,a,o)),B>0?(this.fillStyle(e,0,0,0,B),h?e.fill(d):e.fill()):0>B&&(this.fillStyle(e,255,255,255,-B),h?e.fill(d):e.fill()),z>0&&(h?e.stroke(d):e.stroke(),"double"===E)){e.lineWidth=t.pstyle("border-width").pfValue/3;var I=e.globalCompositeOperation;e.globalCompositeOperation="destination-out",h?e.stroke(d):e.stroke(),e.globalCompositeOperation=I}h&&e.translate(-c.x,-c.y),e.setLineDash&&e.setLineDash([]),s.drawElementText(e,t,i);var L=t.pstyle("overlay-padding").pfValue,O=t.pstyle("overlay-opacity").value,A=t.pstyle("overlay-color").value;O>0&&(this.fillStyle(e,A[0],A[1],A[2],O),s.nodeShapes.roundrectangle.draw(e,t._private.position.x,t._private.position.y,a+2*L,o+2*L),e.fill()),r&&e.translate(v.x1,v.y1)}}},i.hasPie=function(e){return e=e[0],e._private.hasPie},i.drawPie=function(e,t,r,n){t=t[0];var i=t._private,a=t.cy().style(),o=t.pstyle("pie-size"),s=t.width(),l=t.height(),n=n||i.position,u=n.x,c=n.y,d=Math.min(s,l)/2,h=0,p=this.usePaths();p&&(u=0,c=0),"%"===o.units?d=d*o.value/100:void 0!==o.pfValue&&(d=o.pfValue/2);for(var f=1;f<=a.pieBackgroundN;f++){var v=t.pstyle("pie-"+f+"-background-size").value,g=t.pstyle("pie-"+f+"-background-color").value,y=t.pstyle("pie-"+f+"-background-opacity").value*r,m=v/100;m+h>1&&(m=1-h);var b=1.5*Math.PI+2*Math.PI*h,x=2*Math.PI*m,w=b+x;0===v||h>=1||h+m>1||(e.beginPath(),e.moveTo(u,c),e.arc(u,c,d,b,w),e.closePath(),this.fillStyle(e,g[0],g[1],g[2],y),e.fill(),h+=m)}},t.exports=i},{"../../../is":83}],70:[function(e,t,r){"use strict";var n={},i=e("../../../util"),a=100;n.getPixelRatio=function(){var e=this.data.contexts[0];if(null!=this.forcedPixelRatio)return this.forcedPixelRatio;var t=e.backingStorePixelRatio||e.webkitBackingStorePixelRatio||e.mozBackingStorePixelRatio||e.msBackingStorePixelRatio||e.oBackingStorePixelRatio||e.backingStorePixelRatio||1;return(window.devicePixelRatio||1)/t},n.paintCache=function(e){for(var t,r=this.paintCaches=this.paintCaches||[],n=!0,i=0;i0?(e.shadowBlur=n*o,e.shadowColor="rgba("+t[0]+","+t[1]+","+t[2]+","+r+")",e.shadowOffsetX=i*o,e.shadowOffsetY=a*o):(e.shadowBlur=0,e.shadowColor="transparent",e.shadowOffsetX=0,e.shadowOffsetY=0)},n.matchCanvasSize=function(e){var t=this,r=t.data,n=e.clientWidth,i=e.clientHeight,a=t.getPixelRatio(),o=t.motionBlurPxRatio;e!==t.data.bufferCanvases[t.MOTIONBLUR_BUFFER_NODE]&&e!==t.data.bufferCanvases[t.MOTIONBLUR_BUFFER_DRAG]||(a=o);var s,l=n*a,u=i*a;if(l!==t.canvasWidth||u!==t.canvasHeight){t.fontCaches=null;var c=r.canvasContainer;c.style.width=n+"px",c.style.height=i+"px";for(var d=0;d=a&&(s=r.bufferCanvases[t.TEXTURE_BUFFER],t.textureMult=2,s.width=l*t.textureMult,s.height=u*t.textureMult),t.canvasWidth=l,t.canvasHeight=u}},n.renderTo=function(e,t,r,n){this.render({forcedContext:e,forcedZoom:t,forcedPan:r,drawAllLayers:!0,forcedPxRatio:n})},n.render=function(e){function t(e,t,r,n,i){var a=e.globalCompositeOperation;e.globalCompositeOperation="destination-out",c.fillStyle(e,255,255,255,c.motionBlurTransparency),e.fillRect(t,r,n,i),e.globalCompositeOperation=a}function r(e,r){var i,a,s,d;c.clearingMotionBlur||e!==p.bufferContexts[c.MOTIONBLUR_BUFFER_NODE]&&e!==p.bufferContexts[c.MOTIONBLUR_BUFFER_DRAG]?(i=k,a=P,s=c.canvasWidth,d=c.canvasHeight):(i={x:S.x*y,y:S.y*y},a=_*y,s=c.canvasWidth*y,d=c.canvasHeight*y),e.setTransform(1,0,0,1,0,0),"motionBlur"===r?t(e,0,0,s,d):n||void 0!==r&&!r||e.clearRect(0,0,s,d),o||(e.translate(i.x,i.y),e.scale(a,a)),u&&e.translate(u.x,u.y),l&&e.scale(l,l)}e=e||i.staticEmptyObject();var n=e.forcedContext,o=e.drawAllLayers,s=e.drawOnlyNodeLayer,l=e.forcedZoom,u=e.forcedPan,c=this,d=void 0===e.forcedPxRatio?this.getPixelRatio():e.forcedPxRatio,h=c.cy,p=c.data,f=p.canvasNeedsRedraw,v=c.textureOnViewport&&!n&&(c.pinching||c.hoverData.dragging||c.swipePanning||c.data.wheelZooming),g=void 0!==e.motionBlur?e.motionBlur:c.motionBlur,y=c.motionBlurPxRatio,m=h.hasCompoundNodes(),b=c.hoverData.draggingEles,x=!(!c.hoverData.selecting&&!c.touchData.selecting);g=g&&!n&&c.motionBlurEnabled&&!x;var w=g;n||(c.prevPxRatio!==d&&(c.invalidateContainerClientCoordsCache(),c.matchCanvasSize(c.container),c.redrawHint("eles",!0),c.redrawHint("drag",!0)),c.prevPxRatio=d),!n&&c.motionBlurTimeout&&clearTimeout(c.motionBlurTimeout),g&&(null==c.mbFrames&&(c.mbFrames=0),c.drawingImage||c.mbFrames++,c.mbFrames<3&&(w=!1),c.mbFrames>c.minMbLowQualFrames&&(c.motionBlurPxRatio=c.mbPxRBlurry)),c.clearingMotionBlur&&(c.motionBlurPxRatio=1),c.textureDrawLastFrame&&!v&&(f[c.NODE]=!0,f[c.SELECT_BOX]=!0);var E=h.style()._private.coreStyle,_=h.zoom(),P=void 0!==l?l:_,S=h.pan(),k={x:S.x,y:S.y},T={zoom:_,pan:{x:S.x,y:S.y}},D=c.prevViewport,C=void 0===D||T.zoom!==D.zoom||T.pan.x!==D.pan.x||T.pan.y!==D.pan.y;C||b&&!m||(c.motionBlurPxRatio=1),u&&(k=u),P*=d,k.x*=d,k.y*=d;var M=c.getCachedZSortedEles();if(v||(c.textureDrawLastFrame=!1),v){c.textureDrawLastFrame=!0;var N;if(!c.textureCache){c.textureCache={},N=c.textureCache.bb=h.mutableElements().boundingBox(),c.textureCache.texture=c.data.bufferCanvases[c.TEXTURE_BUFFER];var B=c.data.bufferContexts[c.TEXTURE_BUFFER];B.setTransform(1,0,0,1,0,0),B.clearRect(0,0,c.canvasWidth*c.textureMult,c.canvasHeight*c.textureMult),c.render({forcedContext:B,drawOnlyNodeLayer:!0,forcedPxRatio:d*c.textureMult});var T=c.textureCache.viewport={zoom:h.zoom(),pan:h.pan(),width:c.canvasWidth,height:c.canvasHeight};T.mpan={x:(0-T.pan.x)/T.zoom,y:(0-T.pan.y)/T.zoom}}f[c.DRAG]=!1,f[c.NODE]=!1;var z=p.contexts[c.NODE],I=c.textureCache.texture,T=c.textureCache.viewport;N=c.textureCache.bb,z.setTransform(1,0,0,1,0,0),g?t(z,0,0,T.width,T.height):z.clearRect(0,0,T.width,T.height);var L=E["outside-texture-bg-color"].value,O=E["outside-texture-bg-opacity"].value;c.fillStyle(z,L[0],L[1],L[2],O),z.fillRect(0,0,T.width,T.height);var _=h.zoom();r(z,!1),z.clearRect(T.mpan.x,T.mpan.y,T.width/T.zoom/d,T.height/T.zoom/d),z.drawImage(I,T.mpan.x,T.mpan.y,T.width/T.zoom/d,T.height/T.zoom/d)}else c.textureOnViewport&&!n&&(c.textureCache=null);var A=h.extent(),R=c.pinching||c.hoverData.dragging||c.swipePanning||c.data.wheelZooming||c.hoverData.draggingEles,q=c.hideEdgesOnViewport&&R,V=[];if(V[c.NODE]=!f[c.NODE]&&g&&!c.clearedForMotionBlur[c.NODE]||c.clearingMotionBlur,V[c.NODE]&&(c.clearedForMotionBlur[c.NODE]=!0),V[c.DRAG]=!f[c.DRAG]&&g&&!c.clearedForMotionBlur[c.DRAG]||c.clearingMotionBlur,V[c.DRAG]&&(c.clearedForMotionBlur[c.DRAG]=!0),f[c.NODE]||o||s||V[c.NODE]){var F=g&&!V[c.NODE]&&1!==y,z=n||(F?c.data.bufferContexts[c.MOTIONBLUR_BUFFER_NODE]:p.contexts[c.NODE]),j=g&&!F?"motionBlur":void 0;r(z,j),q?c.drawCachedNodes(z,M.nondrag,d,A):c.drawLayeredElements(z,M.nondrag,d,A),o||g||(f[c.NODE]=!1)}if(!s&&(f[c.DRAG]||o||V[c.DRAG])){var F=g&&!V[c.DRAG]&&1!==y,z=n||(F?c.data.bufferContexts[c.MOTIONBLUR_BUFFER_DRAG]:p.contexts[c.DRAG]);r(z,g&&!F?"motionBlur":void 0),q?c.drawCachedNodes(z,M.drag,d,A):c.drawCachedElements(z,M.drag,d,A),o||g||(f[c.DRAG]=!1)}if(c.showFps||!s&&f[c.SELECT_BOX]&&!o){var z=n||p.contexts[c.SELECT_BOX];if(r(z),1==c.selection[4]&&(c.hoverData.selecting||c.touchData.selecting)){var _=c.cy.zoom(),X=E["selection-box-border-width"].value/_;z.lineWidth=X,z.fillStyle="rgba("+E["selection-box-color"].value[0]+","+E["selection-box-color"].value[1]+","+E["selection-box-color"].value[2]+","+E["selection-box-opacity"].value+")",z.fillRect(c.selection[0],c.selection[1],c.selection[2]-c.selection[0],c.selection[3]-c.selection[1]),X>0&&(z.strokeStyle="rgba("+E["selection-box-border-color"].value[0]+","+E["selection-box-border-color"].value[1]+","+E["selection-box-border-color"].value[2]+","+E["selection-box-opacity"].value+")",z.strokeRect(c.selection[0],c.selection[1],c.selection[2]-c.selection[0],c.selection[3]-c.selection[1]))}if(p.bgActivePosistion&&!c.hoverData.selecting){var _=c.cy.zoom(),Y=p.bgActivePosistion;z.fillStyle="rgba("+E["active-bg-color"].value[0]+","+E["active-bg-color"].value[1]+","+E["active-bg-color"].value[2]+","+E["active-bg-opacity"].value+")",z.beginPath(),z.arc(Y.x,Y.y,E["active-bg-size"].pfValue/_,0,2*Math.PI),z.fill()}var W=c.lastRedrawTime;if(c.showFps&&W){W=Math.round(W);var $=Math.round(1e3/W);z.setTransform(1,0,0,1,0,0),z.fillStyle="rgba(255, 0, 0, 0.75)",z.strokeStyle="rgba(255, 0, 0, 0.75)",z.lineWidth=1,z.fillText("1 frame = "+W+" ms = "+$+" fps",0,20);var H=60;z.strokeRect(0,30,250,20),z.fillRect(0,30,250*Math.min($/H,1),20)}o||(f[c.SELECT_BOX]=!1)}if(g&&1!==y){var U=p.contexts[c.NODE],Z=c.data.bufferCanvases[c.MOTIONBLUR_BUFFER_NODE],G=p.contexts[c.DRAG],Q=c.data.bufferCanvases[c.MOTIONBLUR_BUFFER_DRAG],K=function(e,r,n){e.setTransform(1,0,0,1,0,0),n||!w?e.clearRect(0,0,c.canvasWidth,c.canvasHeight):t(e,0,0,c.canvasWidth,c.canvasHeight);var i=y;e.drawImage(r,0,0,c.canvasWidth*i,c.canvasHeight*i,0,0,c.canvasWidth,c.canvasHeight)};(f[c.NODE]||V[c.NODE])&&(K(U,Z,V[c.NODE]),f[c.NODE]=!1),(f[c.DRAG]||V[c.DRAG])&&(K(G,Q,V[c.DRAG]),f[c.DRAG]=!1)}c.prevViewport=T,c.clearingMotionBlur&&(c.clearingMotionBlur=!1,c.motionBlurCleared=!0,c.motionBlur=!0),g&&(c.motionBlurTimeout=setTimeout(function(){c.motionBlurTimeout=null,c.clearedForMotionBlur[c.NODE]=!1,c.clearedForMotionBlur[c.DRAG]=!1,c.motionBlur=!1,c.clearingMotionBlur=!v,c.mbFrames=0,f[c.NODE]=!0,f[c.DRAG]=!0,c.redraw()},a)),c.drawingImage=!1,n||c.initrender||(c.initrender=!0,h.trigger("initrender")),n||h.trigger("render")},t.exports=n},{"../../../util":100}],71:[function(e,t,r){"use strict";var n=e("../../../math"),i={};i.drawPolygonPath=function(e,t,r,n,i,a){var o=n/2,s=i/2;e.beginPath&&e.beginPath(),e.moveTo(t+o*a[0],r+s*a[1]);for(var l=1;li)i=u;else if(y>=d||i>c)return null;var m=Math.pow(2,i),w=t.h*m,E=t.w*m,_=g.imgCaches=g.imgCaches||{},P=_[i];if(P)return P;var S;if(S=s>=w?s:l>=w?l:Math.ceil(w/l)*l,w>v||E>f||!b&&e.isEdge()||!x&&e.isParent())return null;var k=o.getTextureQueue(S),D=k[k.length-2],C=function(){return o.recycleTexture(S,E)||o.addTexture(S,E)};D||(D=k[k.length-1]),D||(D=C()),D.width-D.usedWidth=O;O++){var A=_[O];if(A){M=A;break}}var R=M&&M.level===i+1?M:null,q=function(){D.context.drawImage(R.texture.canvas,R.x,0,R.width,R.height,D.usedWidth,0,E,w)};if(B(R))q();else if(B(M)){if(!I)return o.queueElement(e,t,M.level-1),M;for(var O=M.level;O>i;O--)R=o.getElement(e,t,r,O,T.downscale);q()}else{var V;if(!z&&!I&&!L)for(var O=i-1;O>=u;O--){var A=_[O];if(A){V=A;break}}if(B(V))return o.queueElement(e,t,i),V;D.context.translate(D.usedWidth,0),D.context.scale(m,m),p.drawElement(D.context,e,t,N),D.context.scale(1/m,1/m),D.context.translate(-D.usedWidth,0)}return P=_[i]={ele:e,x:D.usedWidth,texture:D,level:i,scale:m,width:E,height:w,scaledLabelShown:N},D.usedWidth+=Math.ceil(E+h),D.eleCaches.push(P),o.checkTextureFullness(D),P},C.invalidateElement=function(e){var t=this,r=e._private.rscratch.imgCaches;if(r)for(var n=u;c>=n;n++){var a=r[n];if(a){var o=a.texture;o.invalidatedWidth+=a.width,r[n]=null,i.removeFromArray(o.eleCaches,a),t.checkTextureUtility(o)}}},C.checkTextureUtility=function(e){e.invalidatedWidth>=g*e.width&&this.retireTexture(e)},C.checkTextureFullness=function(e){var t=this,r=t.getTextureQueue(e.height);e.usedWidth/e.width>y&&e.fullnessChecks>=m?i.removeFromArray(r,e):e.fullnessChecks++},C.retireTexture=function(e){var t=this,r=e.height,n=t.getTextureQueue(r);i.removeFromArray(n,e),e.retired=!0;for(var a=e.eleCaches,o=0;o=t)return s.retired=!1,s.usedWidth=0,s.invalidatedWidth=0,s.fullnessChecks=0,i.clearArray(s.eleCaches),s.context.clearRect(0,0,s.width,s.height),i.removeFromArray(a,s),n.push(s),s}},C.queueElement=function(e,t,r){var i=this,a=i.getElementQueue(),o=i.getElementIdToQueue(),s=e.id(),l=o[s];if(l)l.level=Math.max(l.level,r),l.reqs++,a.updateItem(l);else{var u={ele:e,bb:t,position:n.copyPosition(e.position()),level:r,reqs:1};e.isEdge()&&(u.positions={source:n.copyPosition(e.source().position()),target:n.copyPosition(e.target().position())}),a.push(u),o[s]=u}},C.dequeue=function(e,t){for(var r=this,i=r.getElementQueue(),a=r.getElementIdToQueue(),o=[],s=0;k>s&&i.size()>0;s++){var l=i.pop();a[l.ele.id()]=null,o.push(l);var u,c=l.ele;u=(!c.isEdge()||n.arePositionsSame(c.source().position(),l.positions.source)&&n.arePositionsSame(c.target().position(),l.positions.target))&&n.arePositionsSame(c.position(),l.position)?l.bb:c.boundingBox(),r.getElement(l.ele,u,e,l.level,T.dequeue)}return o},C.onDequeue=function(e){this.onDequeues.push(e)},C.offDequeue=function(e){i.removeFromArray(this.onDequeues,e)},C.setupDequeueing=o.setupDequeueing({deqRedrawThreshold:S,deqCost:w,deqAvgCost:E,deqNoDrawCost:_,deqFastCost:P,deq:function(e,t,r){return e.dequeue(t,r)},onDeqd:function(e,t){for(var r=0;r0&&o>0){p.clearRect(0,0,a,o),e.bg&&(p.fillStyle=e.bg,p.rect(0,0,a,o),p.fill()),p.globalCompositeOperation="source-over";var f=this.getCachedZSortedEles();if(e.full)p.translate(-i.x1*u,-i.y1*u),p.scale(u,u),this.drawElements(p,f);else{var v=t.pan(),g={x:v.x*u,y:v.y*u};u*=t.zoom(),p.translate(g.x,g.y),p.scale(u,u),this.drawElements(p,f)}}return h},i.png=function(e){return this.bufferCanvasImage(e).toDataURL("image/png")},i.jpg=function(e){return this.bufferCanvasImage(e).toDataURL("image/jpeg")},t.exports=i},{"../../../is":83}],74:[function(e,t,r){"use strict";function n(e){var t=this;t.data={canvases:new Array(u.CANVAS_LAYERS),contexts:new Array(u.CANVAS_LAYERS),canvasNeedsRedraw:new Array(u.CANVAS_LAYERS),bufferCanvases:new Array(u.BUFFER_COUNT),bufferContexts:new Array(u.CANVAS_LAYERS)},t.data.canvasContainer=document.createElement("div");var r=t.data.canvasContainer.style;t.data.canvasContainer.setAttribute("style","-webkit-tap-highlight-color: rgba(0,0,0,0);"),r.position="relative",r.zIndex="0",r.overflow="hidden";var n=e.cy.container();n.appendChild(t.data.canvasContainer),n.setAttribute("style",(n.getAttribute("style")||"")+"-webkit-tap-highlight-color: rgba(0,0,0,0);");for(var i=0;i0&&t.data.lyrTxrCache.invalidateElements(r)})}var i=e("../../../util"),a=e("../../../is"),o=e("./ele-texture-cache"),s=e("./layered-texture-cache"),l=n,u=n.prototype;u.CANVAS_LAYERS=3,u.SELECT_BOX=0,u.DRAG=1,u.NODE=2,u.BUFFER_COUNT=3,u.TEXTURE_BUFFER=0,u.MOTIONBLUR_BUFFER_NODE=1,u.MOTIONBLUR_BUFFER_DRAG=2,u.redrawHint=function(e,t){var r=this;switch(e){case"eles":r.data.canvasNeedsRedraw[u.NODE]=t;break;case"drag":r.data.canvasNeedsRedraw[u.DRAG]=t;break;case"select":r.data.canvasNeedsRedraw[u.SELECT_BOX]=t}};var c="undefined"!=typeof Path2D;u.path2dEnabled=function(e){return void 0===e?this.pathsEnabled:void(this.pathsEnabled=!!e)},u.usePaths=function(){return c&&this.pathsEnabled},[e("./arrow-shapes"),e("./drawing-elements"),e("./drawing-edges"),e("./drawing-images"),e("./drawing-label-text"),e("./drawing-nodes"),e("./drawing-redraw"),e("./drawing-shapes"),e("./export-image"),e("./node-shapes")].forEach(function(e){i.extend(u,e)}),t.exports=l},{"../../../is":83,"../../../util":100,"./arrow-shapes":64,"./drawing-edges":65,"./drawing-elements":66,"./drawing-images":67,"./drawing-label-text":68,"./drawing-nodes":69,"./drawing-redraw":70,"./drawing-shapes":71,"./ele-texture-cache":72,"./export-image":73,"./layered-texture-cache":75,"./node-shapes":76}],75:[function(e,t,r){"use strict";function n(e,t){null!=e.imageSmoothingEnabled?e.imageSmoothingEnabled=t:(e.webkitImageSmoothingEnabled=t,e.mozImageSmoothingEnabled=t,e.msImageSmoothingEnabled=t)}var i=e("../../../util"),a=e("../../../math"),o=e("../../../heap"),s=e("../../../is"),l=e("./texture-cache-defs"),u=1,c=-4,d=2,h=3.99,p=50,f=50,v=!0,g=.15,y=.1,m=.9,b=.9,x=1,w=250,E=16e6,_=!0,P=!0,S=!0,k=function(e,t){var r=this,n=r.renderer=e;r.layersByLevel={},r.firstGet=!0,r.lastInvalidationTime=i.performanceNow()-2*w,r.skipping=!1,n.beforeRender(function(e,t){t-r.lastInvalidationTime<=w?r.skipping=!0:r.skipping=!1});var a=function(e,t){return t.reqs-e.reqs};r.layersQueue=new o(a),r.eleTxrCache=t,r.setupEleCacheInvalidation(),r.setupDequeueing()},T=k.prototype,D=0,C=Math.pow(2,53)-1;T.makeLayer=function(e,t){var r=Math.pow(2,t),n=Math.ceil(e.w*r),i=Math.ceil(e.h*r),a=document.createElement("canvas");a.width=n,a.height=i;var o={id:D=++D%C,bb:e,level:t,width:n,height:i,canvas:a,context:a.getContext("2d"),eles:[],elesQueue:[],reqs:0},s=o.context,l=-o.bb.x1,u=-o.bb.y1;return s.scale(r,r),s.translate(l,u),o},T.getLayers=function(e,t,r){var n=this,o=n.renderer,s=o.cy,l=s.zoom(),p=n.firstGet;if(n.firstGet=!1,null==r)if(r=Math.ceil(a.log2(l*t)),c>r)r=c;else if(l>=h||r>d)return null;n.validateLayersElesOrdering(r,e);var f,v,g=n.layersByLevel,y=Math.pow(2,r),m=g[r]=g[r]||[],b=n.levelIsComplete(r,e),x=function(){var t=function(t){return n.validateLayersElesOrdering(t,e),n.levelIsComplete(t,e)?(v=g[t],!0):void 0},a=function(e){if(!v)for(var n=r+e;n>=c&&d>=n&&!t(n);n+=e);};a(1),a(-1);for(var o=m.length-1;o>=0;o--){var s=m[o];s.invalid&&i.removeFromArray(m,s)}};if(b)return m;x();var w=function(){if(!f){f=a.makeBoundingBox();for(var t=0;tE)return null;var a=n.makeLayer(f,r);if(null!=t){var o=m.indexOf(t)+1;m.splice(o,0,a)}else(void 0===e.insert||e.insert)&&m.unshift(a);return a};if(n.skipping&&!p)return null;for(var S=null,k=e.length/u,T=_&&!p,D=0;D=k||u>1&&!a.boundingBoxInBoundingBox(S.bb,C.boundingBox()))&&(S=P({insert:!0,after:S}),!S))return null;v||T?n.queueLayer(S,C):n.drawEleInLayer(S,C,r,t),S.eles.push(C),N[r]=S}}return v?v:T?null:m},T.getEleLevelForLayerLevel=function(e,t){return e},T.drawEleInLayer=function(e,t,r,i){var a=this,o=this.renderer,s=e.context,l=t.boundingBox(),u=a.eleTxrCache,c=P?u.reasons.highQuality:void 0;r=a.getEleLevelForLayerLevel(r,i);var d=S?u.getElement(t,l,null,r,c):null;d?(v&&n(s,!1),s.drawImage(d.texture.canvas,d.x,0,d.width,d.height,l.x1,l.y1,l.w,l.h),v&&n(s,!0)):o.drawElement(s,t)},T.levelIsComplete=function(e,t){var r=this,n=r.layersByLevel[e];if(!n||0===n.length)return!1;for(var i=0,a=0;a0)return!1;if(o.invalid)return!1;i+=o.eles.length}return i===t.length},T.validateLayersElesOrdering=function(e,t){var r=this.layersByLevel[e];if(r)for(var n=0;na)this.invalidateLayer(i);else for(var s=a,o=0;o=h;h++){var p=u[h];p&&(a&&r.getEleLevelForLayerLevel(p.level)!==a.level||t(p,o,a))}},T.haveLayers=function(){for(var e=this,t=!1,r=c;d>=r;r++){var n=e.layersByLevel[r];if(n&&n.length>0){t=!0;break}}return t},T.invalidateElements=function(e){var t=this;t.lastInvalidationTime=i.performanceNow(),0!==e.length&&t.haveLayers()&&t.updateElementsInLayers(e,function(e,r,n){t.invalidateLayer(e)})},T.invalidateLayer=function(e){if(this.lastInvalidationTime=i.performanceNow(),!e.invalid){var t=e.level,r=e.eles,n=this.layersByLevel[t];i.removeFromArray(n,e),e.elesQueue=[],e.invalid=!0,e.replacement&&(e.replacement.invalid=!0);for(var a=0;ai&&0!==r.size();){var a=r.peek();if(a.replacement)r.pop();else if(a.replaces&&a!==a.replaces.replacement)r.pop();else if(a.invalid)r.pop();else{var o=a.elesQueue.shift();o&&(t.drawEleInLayer(a,o,a.level,e),i++),0===n.length&&n.push(!0),0===a.elesQueue.length&&(r.pop(),a.reqs=0,a.replaces&&t.applyLayerReplacement(a),t.requestRedraw())}}return n},T.applyLayerReplacement=function(e){var t=this,r=t.layersByLevel[e.level],n=e.replaces,i=r.indexOf(n);if(!(0>i||n.invalid)){r[i]=e;for(var a=0;ac){var y=i-(o?u:0);if(g>=e.deqFastCost*y)break}else if(o){if(v>=e.deqCost*c||v>=e.deqAvgCost*u)break}else if(g>=e.deqNoDrawCost*i)break;var m=e.deq(t,p,h);if(!(m.length>0))break;for(var b=0;b0&&(e.onDeqd(t,d),!o&&e.shouldRedraw(t,d,p,h)&&a())},s=e.priority||n.noop;r.beforeRender(o,s(t))}}}}},{"../../../util":100}],78:[function(e,t,r){"use strict";t.exports=[{name:"null",impl:e("./null")},{name:"base",impl:e("./base")},{name:"canvas",impl:e("./canvas")}]},{"./base":60,"./canvas":74,"./null":79}],79:[function(e,t,r){"use strict";function n(e){this.options=e,this.notifications=0}var i=function(){};n.prototype={recalculateRenderedStyle:i,notify:function(){this.notifications++},init:i},t.exports=n},{}],80:[function(e,t,r){/*! Weaver licensed under MIT (https://tldrlegal.com/license/mit-license), copyright Max Franz */ -"use strict";var n=e("./is"),i=e("./util"),a=e("./thread"),o=e("./promise"),s=e("./define"),l=function(t){if(!(this instanceof l))return new l(t);this._private={pass:[]};var r=4;if(n.number(t),"undefined"!=typeof navigator&&null!=navigator.hardwareConcurrency)t=navigator.hardwareConcurrency;else try{t=e("os").cpus().length}catch(i){t=r}for(var o=0;t>o;o++)this[o]=new a;this.length=t},u=l.prototype;i.extend(u,{instanceString:function(){return"fabric"},require:function(e,t){for(var r=0;re?-1:e>t?1:0},t.require(e,"_$_$_cmp"),t.spread(function(e){var t=e.sort(_$_$_cmp);resolve(t)}).then(function(t){for(var i=function(n,i,a){i=Math.min(i,r),a=Math.min(a,r);for(var o=n,s=i,l=[],u=o;a>u;u++){var c=t[n],d=t[i];s>n&&(i>=a||e(c,d)<=0)?(l.push(c),n++):(l.push(d),i++)}for(var u=0;ua;a*=2)for(var o=0;r>o;o+=2*a)i(o,o+a,o+2*a);return t})}});var c=function(e){return e=e||{},function(t,r){var n=this._private.pass.shift();return this.random().pass(n)[e.threadFn](t,r)}};i.extend(u,{randomMap:c({threadFn:"map"}),reduce:c({threadFn:"reduce"}),reduceRight:c({threadFn:"reduceRight"})});var d=u;d.promise=d.run,d.terminate=d.halt=d.stop,d.include=d.require,i.extend(u,{on:s.on(),one:s.on({unbindSelfOnTrigger:!0}),off:s.off(),trigger:s.trigger()}),s.eventAliasesOn(u),t.exports=l},{"./define":44,"./is":83,"./promise":86,"./thread":98,"./util":100,os:void 0}],81:[function(e,t,r){/*! -Ported by Xueqiao Xu ; - -PSF LICENSE AGREEMENT FOR PYTHON 2.7.2 - -1. This LICENSE AGREEMENT is between the Python Software Foundation (“PSF”), and the Individual or Organization (“Licensee”) accessing and otherwise using Python 2.7.2 software in source or binary form and its associated documentation. -2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python 2.7.2 alone or in any derivative version, provided, however, that PSF’s License Agreement and PSF’s notice of copyright, i.e., “Copyright © 2001-2012 Python Software Foundation; All Rights Reserved” are retained in Python 2.7.2 alone or in any derivative version prepared by Licensee. -3. In the event Licensee prepares a derivative work that is based on or incorporates Python 2.7.2 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python 2.7.2. -4. PSF is making Python 2.7.2 available to Licensee on an “AS IS” basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.7.2 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. -5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 2.7.2 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.7.2, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. -6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. -7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between PSF and Licensee. This License Agreement does not grant permission to use PSF trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. -8. By copying, installing or otherwise using Python 2.7.2, Licensee agrees to be bound by the terms and conditions of this License Agreement. -*/ -"use strict";(function(){var e,n,i,a,o,s,l,u,c,d,h,p,f,v,g;i=Math.floor,d=Math.min,n=function(e,t){return t>e?-1:e>t?1:0},c=function(e,t,r,a,o){var s;if(null==r&&(r=0),null==o&&(o=n),0>r)throw new Error("lo must be non-negative");for(null==a&&(a=e.length);a>r;)s=i((r+a)/2),o(t,e[s])<0?a=s:r=s+1;return[].splice.apply(e,[r,r-r].concat(t)),t},s=function(e,t,r){return null==r&&(r=n),e.push(t),v(e,0,e.length-1,r)},o=function(e,t){var r,i;return null==t&&(t=n),r=e.pop(),e.length?(i=e[0],e[0]=r,g(e,0,t)):i=r,i},u=function(e,t,r){var i;return null==r&&(r=n),i=e[0],e[0]=t,g(e,0,r),i},l=function(e,t,r){var i;return null==r&&(r=n),e.length&&r(e[0],t)<0&&(i=[e[0],t],t=i[0],e[0]=i[1],g(e,0,r)),t},a=function(e,t){var r,a,o,s,l,u;for(null==t&&(t=n),s=function(){u=[];for(var t=0,r=i(e.length/2);r>=0?r>t:t>r;r>=0?t++:t--)u.push(t);return u}.apply(this).reverse(),l=[],a=0,o=s.length;o>a;a++)r=s[a],l.push(g(e,r,t));return l},f=function(e,t,r){var i;return null==r&&(r=n),i=e.indexOf(t),-1!==i?(v(e,0,i,r),g(e,i,r)):void 0},h=function(e,t,r){var i,o,s,u,c;if(null==r&&(r=n),o=e.slice(0,t),!o.length)return o;for(a(o,r),c=e.slice(t),s=0,u=c.length;u>s;s++)i=c[s],l(o,i,r);return o.sort(r).reverse()},p=function(e,t,r){var i,s,l,u,h,p,f,v,g,y;if(null==r&&(r=n),10*t<=e.length){if(u=e.slice(0,t).sort(r),!u.length)return u;for(l=u[u.length-1],v=e.slice(t),h=0,f=v.length;f>h;h++)i=v[h],r(i,l)<0&&(c(u,i,0,null,r),u.pop(),l=u[u.length-1]);return u}for(a(e,r),y=[],s=p=0,g=d(t,e.length);g>=0?g>p:p>g;s=g>=0?++p:--p)y.push(o(e,r));return y},v=function(e,t,r,i){var a,o,s;for(null==i&&(i=n),a=e[r];r>t&&(s=r-1>>1,o=e[s],i(a,o)<0);)e[r]=o,r=s;return e[r]=a},g=function(e,t,r){var i,a,o,s,l;for(null==r&&(r=n),a=e.length,l=t,o=e[t],i=2*t+1;a>i;)s=i+1,a>s&&!(r(e[i],e[s])<0)&&(i=s),e[t]=e[i],t=i,i=2*t+1;return e[t]=o,v(e,l,t,r)},e=function(){function e(e){this.cmp=null!=e?e:n,this.nodes=[]}return e.push=s,e.pop=o,e.replace=u,e.pushpop=l,e.heapify=a,e.updateItem=f,e.nlargest=h,e.nsmallest=p,e.prototype.push=function(e){return s(this.nodes,e,this.cmp)},e.prototype.pop=function(){return o(this.nodes,this.cmp)},e.prototype.peek=function(){return this.nodes[0]},e.prototype.contains=function(e){return-1!==this.nodes.indexOf(e)},e.prototype.replace=function(e){return u(this.nodes,e,this.cmp)},e.prototype.pushpop=function(e){return l(this.nodes,e,this.cmp)},e.prototype.heapify=function(){return a(this.nodes,this.cmp)},e.prototype.updateItem=function(e){return f(this.nodes,e,this.cmp)},e.prototype.clear=function(){return this.nodes=[]},e.prototype.empty=function(){return 0===this.nodes.length},e.prototype.size=function(){return this.nodes.length},e.prototype.clone=function(){var t;return t=new e,t.nodes=this.nodes.slice(0),t},e.prototype.toArray=function(){return this.nodes.slice(0)},e.prototype.insert=e.prototype.push,e.prototype.top=e.prototype.peek,e.prototype.front=e.prototype.peek,e.prototype.has=e.prototype.contains,e.prototype.copy=e.prototype.clone,e}(),function(e,n){return"function"==typeof define&&define.amd?define([],n):"object"==typeof r?t.exports=n():e.Heap=n()}(this,function(){return e})}).call(this)},{}],82:[function(e,t,r){"use strict";e("./-preamble");var n=e("./window"),i=e("./is"),a=e("./core"),o=e("./extension"),s=e("./jquery-plugin"),l=e("./stylesheet"),u=e("./thread"),c=e("./fabric"),d=function(e){return void 0===e&&(e={}),i.plainObject(e)?new a(e):i.string(e)?o.apply(o,arguments):void 0};d.version=e("./version.json"),n&&n.jQuery&&s(n.jQuery,d),d.registerJquery=function(e){s(e,d)},d.stylesheet=d.Stylesheet=l,d.thread=d.Thread=u,d.fabric=d.Fabric=c,t.exports=d},{"./-preamble":1,"./core":37,"./extension":46,"./fabric":80,"./is":83,"./jquery-plugin":84,"./stylesheet":97,"./thread":98,"./version.json":106,"./window":107}],83:[function(e,t,r){"use strict";var n=e("./window"),i=n?n.navigator:null,a=n?n.document:null,o="string",s=typeof{},l="function",u=typeof HTMLElement,c=function(e){return e&&e.instanceString&&d.fn(e.instanceString)?e.instanceString():null},d={defined:function(e){return null!=e},string:function(e){return null!=e&&typeof e==o},fn:function(e){return null!=e&&typeof e===l},array:function(e){return Array.isArray?Array.isArray(e):null!=e&&e instanceof Array},plainObject:function(e){return null!=e&&typeof e===s&&!d.array(e)&&e.constructor===Object},object:function(e){return null!=e&&typeof e===s},number:function(e){return null!=e&&"number"==typeof e&&!isNaN(e)},integer:function(e){return d.number(e)&&Math.floor(e)===e},bool:function(e){return null!=e&&typeof e==typeof!0},htmlElement:function(e){return"undefined"===u?void 0:null!=e&&e instanceof HTMLElement},elementOrCollection:function(e){return d.element(e)||d.collection(e)},element:function(e){return"collection"===c(e)&&e._private.single},collection:function(e){return"collection"===c(e)&&!e._private.single},core:function(e){return"core"===c(e)},style:function(e){return"style"===c(e)},stylesheet:function(e){return"stylesheet"===c(e)},event:function(e){return"event"===c(e)},thread:function(e){return"thread"===c(e)},fabric:function(e){return"fabric"===c(e)},emptyString:function(e){return void 0===e||null===e?!0:!(""!==e&&!e.match(/^\s+$/))},nonemptyString:function(e){return!(!e||!d.string(e)||""===e||e.match(/^\s+$/))},domElement:function(e){return"undefined"==typeof HTMLElement?!1:e instanceof HTMLElement},boundingBox:function(e){return d.plainObject(e)&&d.number(e.x1)&&d.number(e.x2)&&d.number(e.y1)&&d.number(e.y2)},promise:function(e){return d.object(e)&&d.fn(e.then)},touch:function(){return n&&("ontouchstart"in n||n.DocumentTouch&&a instanceof DocumentTouch)},gecko:function(){return n&&("undefined"!=typeof InstallTrigger||"MozAppearance"in a.documentElement.style)},webkit:function(){return n&&("undefined"!=typeof webkitURL||"WebkitAppearance"in a.documentElement.style)},chromium:function(){return n&&"undefined"!=typeof chrome},khtml:function(){return i&&i.vendor.match(/kde/i)},khtmlEtc:function(){return d.khtml()||d.webkit()||d.chromium()},ms:function(){return i&&i.userAgent.match(/msie|trident|edge/i)},windows:function(){return i&&i.appVersion.match(/Win/i)},mac:function(){return i&&i.appVersion.match(/Mac/i)},linux:function(){return i&&i.appVersion.match(/Linux/i)},unix:function(){return i&&i.appVersion.match(/X11/i)}};t.exports=d},{"./window":107}],84:[function(e,t,r){"use strict";var n=e("./is"),i=function(e){var t=e[0]._cyreg=e[0]._cyreg||{};return t},a=function(e,t){e&&(e.fn.cytoscape||(e.fn.cytoscape=function(r){var a=e(this);if("get"===r)return i(a).cy;if(n.fn(r)){var o=r,s=i(a).cy;if(s&&s.isReady())s.trigger("ready",[],o);else{var l=i(a),u=l.readies=l.readies||[];u.push(o)}}else if(n.plainObject(r))return a.each(function(){var n=e.extend({},r,{container:e(this)[0]});t(n)})},e.cytoscape=t,null==e.fn.cy&&null==e.cy&&(e.fn.cy=e.fn.cytoscape,e.cy=e.cytoscape)))};t.exports=a},{"./is":83}],85:[function(e,t,r){"use strict";var n={};n.arePositionsSame=function(e,t){return e.x===t.x&&e.y===t.y},n.copyPosition=function(e){return{x:e.x,y:e.y}},n.array2point=function(e){return{x:e[0],y:e[1]}},n.deg2rad=function(e){return Math.PI*e/180},n.log2=Math.log2||function(e){return Math.log(e)/Math.log(2)},n.signum=function(e){return e>0?1:0>e?-1:0},n.dist=function(e,t){return Math.sqrt(n.sqdist(e,t))},n.sqdist=function(e,t){var r=t.x-e.x,n=t.y-e.y;return r*r+n*n},n.qbezierAt=function(e,t,r,n){return(1-n)*(1-n)*e+2*(1-n)*n*t+n*n*r},n.qbezierPtAt=function(e,t,r,i){return{x:n.qbezierAt(e.x,t.x,r.x,i),y:n.qbezierAt(e.y,t.y,r.y,i)}},n.lineAt=function(e,t,r,i){var a={x:t.x-e.x,y:t.y-e.y},o=n.dist(e,t),s={x:a.x/o,y:a.y/o};r=null==r?0:r;var i=null!=i?i:r*o;return{x:e.x+s.x*i,y:e.y+s.y*i}},n.lineAtDist=function(e,t,r){return n.lineAt(e,t,void 0,r)},n.triangleAngle=function(e,t,r){var i=n.dist(t,r),a=n.dist(e,r),o=n.dist(e,t);return Math.acos((i*i+a*a-o*o)/(2*i*a))},n.bound=function(e,t,r){return Math.max(e,Math.min(r,t))},n.makeBoundingBox=function(e){if(null==e)return{x1:1/0,y1:1/0,x2:-(1/0),y2:-(1/0),w:0,h:0};if(null!=e.x1&&null!=e.y1){if(null!=e.x2&&null!=e.y2&&e.x2>=e.x1&&e.y2>=e.y1)return{x1:e.x1,y1:e.y1,x2:e.x2,y2:e.y2,w:e.x2-e.x1,h:e.y2-e.y1};if(null!=e.w&&null!=e.h&&e.w>=0&&e.h>=0)return{x1:e.x1,y1:e.y1,x2:e.x1+e.w,y2:e.y1+e.h,w:e.w,h:e.h}}},n.updateBoundingBox=function(e,t){e.x1=Math.min(e.x1,t.x1),e.x2=Math.max(e.x2,t.x2),e.w=e.x2-e.x1,e.y1=Math.min(e.y1,t.y1),e.y2=Math.max(e.y2,t.y2),e.h=e.y2-e.y1},n.expandBoundingBox=function(e,t){return e.x1-=t,e.x2+=t,e.y1-=t,e.y2+=t,e.w=e.x2-e.x1,e.h=e.y2-e.y1,e},n.boundingBoxesIntersect=function(e,t){return e.x1>t.x2?!1:t.x1>e.x2?!1:e.x2t.y2?!1:!(t.y1>e.y2)},n.inBoundingBox=function(e,t,r){return e.x1<=t&&t<=e.x2&&e.y1<=r&&r<=e.y2},n.pointInBoundingBox=function(e,t){return this.inBoundingBox(e,t.x,t.y)},n.boundingBoxInBoundingBox=function(e,t){return n.inBoundingBox(e,t.x1,t.y1)&&n.inBoundingBox(e,t.x2,t.y2)},n.roundRectangleIntersectLine=function(e,t,r,n,i,a,o){var s,l=this.getRoundRectangleRadius(i,a),u=i/2,c=a/2,d=r-u+l-o,h=n-c-o,p=r+u-l+o,f=h;if(s=this.finiteLinesIntersect(e,t,r,n,d,h,p,f,!1),s.length>0)return s;var v=r+u+o,g=n-c+l-o,y=v,m=n+c-l+o;if(s=this.finiteLinesIntersect(e,t,r,n,v,g,y,m,!1),s.length>0)return s;var b=r-u+l-o,x=n+c+o,w=r+u-l+o,E=x;if(s=this.finiteLinesIntersect(e,t,r,n,b,x,w,E,!1),s.length>0)return s;var _=r-u-o,P=n-c+l-o,S=_,k=n+c-l+o;if(s=this.finiteLinesIntersect(e,t,r,n,_,P,S,k,!1),s.length>0)return s;var T,D=r-u+l,C=n-c+l;if(T=this.intersectLineCircle(e,t,r,n,D,C,l+o),T.length>0&&T[0]<=D&&T[1]<=C)return[T[0],T[1]];var M=r+u-l,N=n-c+l;if(T=this.intersectLineCircle(e,t,r,n,M,N,l+o),T.length>0&&T[0]>=M&&T[1]<=N)return[T[0],T[1]];var B=r+u-l,z=n+c-l;if(T=this.intersectLineCircle(e,t,r,n,B,z,l+o),T.length>0&&T[0]>=B&&T[1]>=z)return[T[0],T[1]];var I=r-u+l,L=n+c-l;return T=this.intersectLineCircle(e,t,r,n,I,L,l+o),T.length>0&&T[0]<=I&&T[1]>=L?[T[0],T[1]]:[]},n.inLineVicinity=function(e,t,r,n,i,a,o){var s=o,l=Math.min(r,i),u=Math.max(r,i),c=Math.min(n,a),d=Math.max(n,a);return e>=l-s&&u+s>=e&&t>=c-s&&d+s>=t},n.inBezierVicinity=function(e,t,r,n,i,a,o,s,l){var u={x1:Math.min(r,o,i)-l,x2:Math.max(r,o,i)+l,y1:Math.min(n,s,a)-l,y2:Math.max(n,s,a)+l};return!(eu.x2||tu.y2)},n.solveCubic=function(e,t,r,n,i){t/=e,r/=e,n/=e;var a,o,s,l,u,c,d,h;return o=(3*r-t*t)/9,s=-(27*n)+t*(9*r-2*(t*t)),s/=54,a=o*o*o+s*s,i[1]=0,d=t/3,a>0?(u=s+Math.sqrt(a),u=0>u?-Math.pow(-u,1/3):Math.pow(u,1/3),c=s-Math.sqrt(a),c=0>c?-Math.pow(-c,1/3):Math.pow(c,1/3),i[0]=-d+u+c,d+=(u+c)/2,i[4]=i[2]=-d,d=Math.sqrt(3)*(-c+u)/2,i[3]=d,void(i[5]=-d)):(i[5]=i[3]=0,0===a?(h=0>s?-Math.pow(-s,1/3):Math.pow(s,1/3),i[0]=-d+2*h,void(i[4]=i[2]=-(h+d))):(o=-o,l=o*o*o,l=Math.acos(s/Math.sqrt(l)),h=2*Math.sqrt(o),i[0]=-d+h*Math.cos(l/3),i[2]=-d+h*Math.cos((l+2*Math.PI)/3),void(i[4]=-d+h*Math.cos((l+4*Math.PI)/3))))},n.sqdistToQuadraticBezier=function(e,t,r,n,i,a,o,s){var l=1*r*r-4*r*i+2*r*o+4*i*i-4*i*o+o*o+n*n-4*n*a+2*n*s+4*a*a-4*a*s+s*s,u=9*r*i-3*r*r-3*r*o-6*i*i+3*i*o+9*n*a-3*n*n-3*n*s-6*a*a+3*a*s,c=3*r*r-6*r*i+r*o-r*e+2*i*i+2*i*e-o*e+3*n*n-6*n*a+n*s-n*t+2*a*a+2*a*t-s*t,d=1*r*i-r*r+r*e-i*e+n*a-n*n+n*t-a*t,h=[];this.solveCubic(l,u,c,d,h);for(var p=1e-7,f=[],v=0;6>v;v+=2)Math.abs(h[v+1])=0&&h[v]<=1&&f.push(h[v]);f.push(1),f.push(0);for(var g,y,m,b,x=-1,w=0;w=0?x>b&&(x=b,g=f[w]):(x=b,g=f[w]);return x},n.sqdistToFiniteLine=function(e,t,r,n,i,a){var o=[e-r,t-n],s=[i-r,a-n],l=s[0]*s[0]+s[1]*s[1],u=o[0]*o[0]+o[1]*o[1],c=o[0]*s[0]+o[1]*s[1],d=c*c/l;return 0>c?u:d>l?(e-i)*(e-i)+(t-a)*(t-a):u-d},n.pointInsidePolygonPoints=function(e,t,r){for(var n,i,a,o,s,l=0,u=0,c=0;c=e&&e>=a||e>=n&&a>=e))continue;s=(e-n)/(a-n)*(o-i)+i,s>t&&l++,t>s&&u++}return l%2!==0},n.pointInsidePolygon=function(e,t,r,i,a,o,s,l,u){var c,d=new Array(r.length);null!=l[0]?(c=Math.atan(l[1]/l[0]),l[0]<0?c+=Math.PI/2:c=-c-Math.PI/2):c=l;for(var h=Math.cos(-c),p=Math.sin(-c),f=0;f0){var g=this.expandPolygon(d,-u);v=this.joinLines(g)}else v=d;return n.pointInsidePolygonPoints(e,t,v)},n.joinLines=function(e){for(var t,r,n,i,a,o,s,l,u=new Array(e.length/2),c=0;cu)return[];var c=u/l;return[(r-e)*c+e,(n-t)*c+t]},n.intersectLineCircle=function(e,t,r,n,i,a,o){var s=[r-e,n-t],l=[i,a],u=[e-i,t-a],c=s[0]*s[0]+s[1]*s[1],d=2*(u[0]*s[0]+u[1]*s[1]),l=u[0]*u[0]+u[1]*u[1]-o*o,h=d*d-4*c*l;if(0>h)return[];var p=(-d+Math.sqrt(h))/(2*c),f=(-d-Math.sqrt(h))/(2*c),v=Math.min(p,f),g=Math.max(p,f),y=[];if(v>=0&&1>=v&&y.push(v),g>=0&&1>=g&&y.push(g),0===y.length)return[];var m=y[0]*s[0]+e,b=y[0]*s[1]+t;if(y.length>1){if(y[0]==y[1])return[m,b];var x=y[1]*s[0]+e,w=y[1]*s[1]+t;return[m,b,x,w]}return[m,b]},n.findCircleNearPoint=function(e,t,r,n,i){var a=n-e,o=i-t,s=Math.sqrt(a*a+o*o),l=a/s,u=o/s;return[e+l*r,t+u*r]},n.findMaxSqDistanceToOrigin=function(e){for(var t,r=1e-6,n=0;nr&&(r=t);return r},n.midOfThree=function(e,t,r){return e>=t&&r>=e||e>=r&&t>=e?e:t>=e&&r>=t||t>=r&&e>=t?t:r},n.finiteLinesIntersect=function(e,t,r,n,i,a,o,s,l){var u=e-i,c=r-e,d=o-i,h=t-a,p=n-t,f=s-a,v=d*h-f*u,g=c*h-p*u,y=f*c-d*p;if(0!==y){var m=v/y,b=g/y,x=.001,w=0-x,E=1+x;return m>=w&&E>=m&&b>=w&&E>=b?[e+m*c,t+m*p]:l?[e+m*c,t+m*p]:[]}return 0===v||0===g?this.midOfThree(e,r,o)===o?[o,s]:this.midOfThree(e,r,i)===i?[i,a]:this.midOfThree(i,o,r)===r?[r,n]:[]:[]},n.polygonIntersectLine=function(e,t,r,i,a,o,s,l){for(var u,c=[],d=new Array(r.length),h=0;h0){var f=n.expandPolygon(d,-l);p=n.joinLines(f)}else p=d;for(var v,g,y,m,h=0;ha&&(a=1e-5),[t[0]+a*n[0],t[1]+a*n[1]]},n.generateUnitNgonPointsFitToSquare=function(e,t){var r=n.generateUnitNgonPoints(e,t);return r=n.fitPolygonToSquare(r)},n.fitPolygonToSquare=function(e){for(var t,r,n=e.length/2,i=1/0,a=1/0,o=-(1/0),s=-(1/0),l=0;n>l;l++)t=e[2*l],r=e[2*l+1],i=Math.min(i,t),o=Math.max(o,t),a=Math.min(a,r),s=Math.max(s,r);for(var u=2/(o-i),c=2/(s-a),l=0;n>l;l++)t=e[2*l]=e[2*l]*u,r=e[2*l+1]=e[2*l+1]*c,i=Math.min(i,t),o=Math.max(o,t),a=Math.min(a,r),s=Math.max(s,r);if(-1>a)for(var l=0;n>l;l++)r=e[2*l+1]=e[2*l+1]+(-1-a);return e},n.generateUnitNgonPoints=function(e,t){var r=1/e*2*Math.PI,n=e%2===0?Math.PI/2+r/2:Math.PI/2;n+=t;for(var i,a,o,s=new Array(2*e),l=0;e>l;l++)i=l*r+n,a=s[2*l]=Math.cos(i),o=s[2*l+1]=Math.sin(-i);return s},n.getRoundRectangleRadius=function(e,t){return Math.min(e/4,t/4,8)},t.exports=n},{}],86:[function(e,t,r){/*! -Embeddable Minimum Strictly-Compliant Promises/A+ 1.1.1 Thenable -Copyright (c) 2013-2014 Ralf S. Engelschall (http://engelschall.com) -Licensed under The MIT License (http://opensource.org/licenses/MIT) -*/ -"use strict";var n=0,i=1,a=2,o=function(e){return this instanceof o?(this.id="Thenable/1.0.7",this.state=n,this.fulfillValue=void 0,this.rejectReason=void 0,this.onFulfilled=[],this.onRejected=[],this.proxy={then:this.then.bind(this)},void("function"==typeof e&&e.call(this,this.fulfill.bind(this),this.reject.bind(this)))):new o(e)};o.prototype={fulfill:function(e){return s(this,i,"fulfillValue",e)},reject:function(e){return s(this,a,"rejectReason",e)},then:function(e,t){var r=this,n=new o;return r.onFulfilled.push(c(e,n,"fulfill")),r.onRejected.push(c(t,n,"reject")),l(r),n.proxy}};var s=function(e,t,r,i){return e.state===n&&(e.state=t,e[r]=i,l(e)),e},l=function(e){e.state===i?u(e,"onFulfilled",e.fulfillValue):e.state===a&&u(e,"onRejected",e.rejectReason)},u=function(e,t,r){if(0!==e[t].length){var n=e[t];e[t]=[];var i=function(){for(var e=0;e\\?\\@\\[\\]\\^\\`\\{\\|\\}\\~]",comparatorOp:"=|\\!=|>|>=|<|<=|\\$=|\\^=|\\*=",boolOp:"\\?|\\!|\\^",string:'"(?:\\\\"|[^"])+"|'+"'(?:\\\\'|[^'])+'",number:i.regex.number,meta:"degree|indegree|outdegree",separator:"\\s*,\\s*",descendant:"\\s+",child:"\\s+>\\s+",subject:"\\$"};l.variable="(?:[\\w-]|(?:\\\\"+l.metaChar+"))+",l.value=l.string+"|"+l.number,l.className=l.variable,l.id=l.variable;for(var u=function(e){return e.replace(new RegExp("\\\\("+l.metaChar+")","g"),function(e,t,r,n){return t})},c=l.comparatorOp.split("|"),d=0;d=0||"="!==h&&(l.comparatorOp+="|\\!"+h)}var p=[{name:"group",query:!0,regex:"(node|edge|\\*)",populate:function(e){this.group="*"===e?e:e+"s"}},{name:"state",query:!0,regex:"(:selected|:unselected|:locked|:unlocked|:visible|:hidden|:transparent|:grabbed|:free|:removed|:inside|:grabbable|:ungrabbable|:animated|:unanimated|:selectable|:unselectable|:orphan|:nonorphan|:parent|:child|:loop|:simple|:active|:inactive|:touch|:backgrounding|:nonbackgrounding)",populate:function(e){this.colonSelectors.push(e)}},{name:"id",query:!0,regex:"\\#("+l.id+")",populate:function(e){this.ids.push(u(e))}},{name:"className",query:!0,regex:"\\.("+l.className+")",populate:function(e){this.classes.push(u(e))}},{name:"dataExists",query:!0,regex:"\\[\\s*("+l.variable+")\\s*\\]",populate:function(e){this.data.push({field:u(e)})}},{name:"dataCompare",query:!0,regex:"\\[\\s*("+l.variable+")\\s*("+l.comparatorOp+")\\s*("+l.value+")\\s*\\]",populate:function(e,t,r){var n=null!=new RegExp("^"+l.string+"$").exec(r);r=n?r.substring(1,r.length-1):parseFloat(r),this.data.push({field:u(e),operator:t,value:r})}},{name:"dataBool",query:!0,regex:"\\[\\s*("+l.boolOp+")\\s*("+l.variable+")\\s*\\]",populate:function(e,t){this.data.push({field:u(t),operator:e})}},{name:"metaCompare",query:!0,regex:"\\[\\[\\s*("+l.meta+")\\s*("+l.comparatorOp+")\\s*("+l.number+")\\s*\\]\\]",populate:function(e,t,r){this.meta.push({field:u(e),operator:t,value:parseFloat(r)})}},{name:"nextQuery",separator:!0,regex:l.separator,populate:function(){t[++d]=r(),s=null}},{name:"child",separator:!0,regex:l.child,populate:function(){var e=r();e.parent=this,e.subject=s,t[d]=e}},{name:"descendant",separator:!0,regex:l.descendant,populate:function(){var e=r();e.ancestor=this,e.subject=s,t[d]=e}},{name:"subject",modifier:!0,regex:l.subject,populate:function(){return null!=s&&this.subject!=this?(i.error("Redefinition of subject in selector `"+e+"`"),!1):(s=this,void(this.subject=this))}}];t._private.selectorText=e;var f=e,d=0,v=function(e){for(var t,r,i,a=0;a=0&&(d=d.toLowerCase(),h=h.toLowerCase(),s=s.replace("@",""),p=!0);var f=!1;s.indexOf("!")>=0&&(s=s.replace("!",""),f=!0),p&&(l=h.toLowerCase(),c=d.toLowerCase());var v=!1;switch(s){case"*=":a=d.indexOf(h)>=0;break;case"$=":a=d.indexOf(h,d.length-h.length)>=0;break;case"^=":a=0===d.indexOf(h);break;case"=":a=c===l;break;case">":v=!0,a=c>l;break;case">=":v=!0,a=c>=l;break;case"<":v=!0,a=l>c;break;case"<=":v=!0,a=l>=c;break;default:a=!1}!f||null==c&&v||(a=!a)}else if(null!=s)switch(s){case"?":a=t.fieldTruthy(u);break;case"!":a=!t.fieldTruthy(u);break;case"^":a=t.fieldUndefined(u)}else a=!t.fieldUndefined(u);if(!a){r=!1;break}}return r},v=f({name:"data",fieldValue:function(e){return r.data[e]},fieldUndefined:function(e){return void 0===r.data[e]},fieldTruthy:function(e){return!!r.data[e]}});if(!v)return!1;var g=f({name:"meta",fieldValue:function(e){return t[e]()},fieldUndefined:function(e){return null==t[e]()},fieldTruthy:function(e){return!!t[e]()}});if(!g)return!1;if(null!=e.collection){var y=e.collection.hasElementWithId(t.id());if(!y)return!1}if(null!=e.filter&&0===t.collection().filter(e.filter).size())return!1;var m=function(e,t){if(null!=e){var r=!1;if(!i.hasCompoundNodes())return!1;t=t();for(var n=0;n "+n),null!=e.ancestor&&(n=r(e.ancestor)+" "+n),null!=e.child&&(n+=" > "+r(e.child)),null!=e.descendant&&(n+=" "+r(e.descendant)),n},i=0;i1&&i0;if(h||p){var f;h&&p?f=u.properties:h?f=u.properties:p&&(f=u.mappedProperties);for(var v=0;v0){n=!0;break}}t.hasPie=n;var o=e.pstyle("text-transform").strValue,s=e.pstyle("label").strValue,l=e.pstyle("source-label").strValue,u=e.pstyle("target-label").strValue,c=e.pstyle("font-style").strValue,a=e.pstyle("font-size").pfValue+"px",d=e.pstyle("font-family").strValue,h=e.pstyle("font-weight").strValue,p=e.pstyle("text-valign").strValue,f=e.pstyle("text-valign").strValue,v=e.pstyle("text-outline-width").pfValue,g=e.pstyle("text-wrap").strValue,y=e.pstyle("text-max-width").pfValue,m=c+"$"+a+"$"+d+"$"+h+"$"+o+"$"+p+"$"+f+"$"+v+"$"+g+"$"+y;t.labelStyleKey=m,t.sourceLabelKey=m+"$"+l,t.targetLabelKey=m+"$"+u,t.labelKey=m+"$"+s,t.fontKey=c+"$"+h+"$"+a+"$"+d,t.styleKey=Date.now()}},a.applyParsedProperty=function(e,t){var r,a,o=this,s=t,l=e._private.style,u=o.types,c=o.properties[s.name].type,d=s.bypass,h=l[s.name],p=h&&h.bypass,f=e._private;if("curve-style"===t.name&&"haystack"===t.value&&e.isEdge()&&(e.isLoop()||e.source().isParent()||e.target().isParent())&&(s=t=this.parse(t.name,"bezier",d)),s["delete"])return l[s.name]=void 0,!0;if(s.deleteBypassed)return h?h.bypass?(h.bypassed=void 0,!0):!1:!0;if(s.deleteBypass)return h?h.bypass?(l[s.name]=h.bypassed,!0):!1:!0;var v=function(){n.error("Do not assign mappings to elements without corresponding data (e.g. ele `"+e.id()+"` for property `"+s.name+"` with data field `"+s.field+"`); try a `["+s.field+"]` selector to limit scope to elements with `"+s.field+"` defined")};switch(s.mapped){case u.mapData:case u.mapLayoutData:case u.mapScratch:var r,g=s.mapped===u.mapLayoutData,y=s.mapped===u.mapScratch,m=s.field.split(".");r=y||g?f.scratch:f.data;for(var b=0;bw?w=0:w>1&&(w=1),c.color){var E=s.valueMin[0],_=s.valueMax[0],P=s.valueMin[1],S=s.valueMax[1],k=s.valueMin[2],T=s.valueMax[2],D=null==s.valueMin[3]?1:s.valueMin[3],C=null==s.valueMax[3]?1:s.valueMax[3],M=[Math.round(E+(_-E)*w),Math.round(P+(S-P)*w),Math.round(k+(T-k)*w),Math.round(D+(C-D)*w)];a={bypass:s.bypass,name:s.name,value:M,strValue:"rgb("+M[0]+", "+M[1]+", "+M[2]+")"}}else{if(!c.number)return!1;var N=s.valueMin+(s.valueMax-s.valueMin)*w;a=this.parse(s.name,N,s.bypass,!0)}a||(a=this.parse(s.name,h.strValue,s.bypass,!0)),a||v(),a.mapping=s,s=a;break;case u.data:case u.layoutData:case u.scratch:var r,g=s.mapped===u.layoutData,y=s.mapped===u.scratch,m=s.field.split(".");if(r=y||g?f.scratch:f.data)for(var b=0;b0&&s>0){for(var u={},c=!1,d=0;d0&&e.delay(l),e.animate({css:u},{duration:s,easing:e.pstyle("transition-timing-function").value,queue:!1,complete:function(){r||n.removeBypasses(e,o),a.transitioning=!1}})}else a.transitioning&&(e.stop(),this.removeBypasses(e,o),a.transitioning=!1)},t.exports=a},{"../is":83,"../util":100}],89:[function(e,t,r){"use strict";var n=e("../is"),i=e("../util"),a={};a.applyBypass=function(e,t,r,a){var o=this,s=[],l=!0;if("*"===t||"**"===t){if(void 0!==r)for(var u=0;uh.max)return null;var B={name:e,value:t,strValue:""+t+(D?D:""),units:D,bypass:r};return h.unitless||"px"!==D&&"em"!==D?B.pfValue=t:B.pfValue="px"!==D&&D?this.getEmSizeInPixels()*t:t,"ms"!==D&&"s"!==D||(B.pfValue="ms"===D?t:1e3*t),"deg"!==D&&"rad"!==D||(B.pfValue="rad"===D?t:a.deg2rad(t)),B}if(h.propList){var z=[],I=""+t;if("none"===I);else{for(var L=I.split(","),O=0;O node").css({shape:"rectangle","padding-top":10,"padding-right":10,"padding-left":10,"padding-bottom":10,"background-color":"#eee","border-color":"#ccc","border-width":1}).selector("edge").css({width:3,"curve-style":"haystack"}).selector(":selected").css({"background-color":"#0169D9","line-color":"#0169D9","source-arrow-color":"#0169D9","target-arrow-color":"#0169D9","mid-source-arrow-color":"#0169D9","mid-target-arrow-color":"#0169D9"}).selector("node:parent:selected").css({"background-color":"#CCE1F9","border-color":"#aec8e5"}).selector(":active").css({"overlay-color":"black","overlay-padding":10,"overlay-opacity":.25}).selector("core").css({"selection-box-color":"#ddd","selection-box-opacity":.65,"selection-box-border-color":"#aaa","selection-box-border-width":1,"active-bg-color":"black","active-bg-opacity":.15,"active-bg-size":30,"outside-texture-bg-color":"#000","outside-texture-bg-opacity":.125}),this.defaultLength=this.length},t.exports=i},{"../util":100}],96:[function(e,t,r){"use strict";var n=e("../util"),i=e("../selector"),a={};a.applyFromString=function(e){function t(){c=c.length>a.length?c.substr(a.length):""}function r(){o=o.length>s.length?o.substr(s.length):""}var a,o,s,l=this,u=this,c=""+e;for(c=c.replace(/[\/][*](\s|.)+?[*][\/]/g,"");;){var d=c.match(/^\s*$/);if(d)break;var h=c.match(/^\s*((?:.|\s)+?)\s*\{((?:.|\s)+?)\}/);if(!h){n.error("Halting stylesheet parsing: String stylesheet contains more to parse but no selector and block found in: "+c);break}a=h[0];var p=h[1];if("core"!==p){var f=new i(p);if(f._private.invalid){n.error("Skipping parsing of block: Invalid selector found in string stylesheet: "+p),t();continue}}var v=h[2],g=!1;o=v;for(var y=[];;){var d=o.match(/^\s*$/);if(d)break;var m=o.match(/^\s*(.+?)\s*:\s*(.+?)\s*;/);if(!m){n.error("Skipping parsing of block: Invalid formatting of style property and value definitions found in:"+v),g=!0;break}s=m[0];var b=m[1],x=m[2],w=l.properties[b];if(w){var E=u.parse(b,x);E?(y.push({name:b,val:x}),r()):(n.error("Skipping property: Invalid property definition in: "+s),r())}else n.error("Skipping property: Invalid property name in: "+s),r()}if(g){t();break}u.selector(p);for(var _=0;_1?", "+JSON.stringify(r):"")+" );"," "," resolve = origResolve;"," resolve( res.length > 0 ? res : ret );","}"].join("\n"))}};util.extend(thdfn,{reduce:defineFnal({name:"reduce"}),reduceRight:defineFnal({name:"reduceRight"}),map:defineFnal({name:"map"})});var fn=thdfn;fn.promise=fn.run,fn.terminate=fn.halt=fn.stop,fn.include=fn.require,util.extend(thdfn,{on:define.on(),one:define.on({unbindSelfOnTrigger:!0}),off:define.off(),trigger:define.trigger()}),define.eventAliasesOn(thdfn),module.exports=Thread},{"./define":44,"./event":45,"./is":83,"./promise":86,"./util":100,"./window":107,child_process:void 0,path:void 0}],99:[function(e,t,r){"use strict";var n=e("../is");t.exports={hex2tuple:function(e){if((4===e.length||7===e.length)&&"#"===e[0]){var t,r,n,i=4===e.length,a=16;return i?(t=parseInt(e[1]+e[1],a),r=parseInt(e[2]+e[2],a),n=parseInt(e[3]+e[3],a)):(t=parseInt(e[1]+e[2],a),r=parseInt(e[3]+e[4],a),n=parseInt(e[5]+e[6],a)),[t,r,n]}},hsl2tuple:function(e){function t(e,t,r){return 0>r&&(r+=1),r>1&&(r-=1),1/6>r?e+6*(t-e)*r:.5>r?t:2/3>r?e+(t-e)*(2/3-r)*6:e}var r,n,i,a,o,s,l,u,c=new RegExp("^"+this.regex.hsla+"$").exec(e);if(c){if(n=parseInt(c[1]),0>n?n=(360- -1*n%360)%360:n>360&&(n%=360),n/=360,i=parseFloat(c[2]),0>i||i>100)return;if(i/=100,a=parseFloat(c[3]),0>a||a>100)return;if(a/=100,o=c[4],void 0!==o&&(o=parseFloat(o),0>o||o>1))return;if(0===i)s=l=u=Math.round(255*a);else{var d=.5>a?a*(1+i):a+i-a*i,h=2*a-d;s=Math.round(255*t(h,d,n+1/3)),l=Math.round(255*t(h,d,n)),u=Math.round(255*t(h,d,n-1/3))}r=[s,l,u,o]}return r},rgb2tuple:function(e){var t,r=new RegExp("^"+this.regex.rgba+"$").exec(e);if(r){t=[];for(var n=[],i=1;3>=i;i++){var a=r[i];if("%"===a[a.length-1]&&(n[i]=!0),a=parseFloat(a),n[i]&&(a=a/100*255),0>a||a>255)return;t.push(Math.floor(a))}var o=n[1]||n[2]||n[3],s=n[1]&&n[2]&&n[3];if(o&&!s)return;var l=r[4];if(void 0!==l){if(l=parseFloat(l),0>l||l>1)return;t.push(l)}}return t},colorname2tuple:function(e){return this.colors[e.toLowerCase()]},color2tuple:function(e){return(n.array(e)?e:null)||this.colorname2tuple(e)||this.hex2tuple(e)||this.rgb2tuple(e)||this.hsl2tuple(e)},colors:{transparent:[0,0,0,0],aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],grey:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}}},{"../is":83}],100:[function(e,t,r){"use strict";var n=e("../is"),i=e("../math"),a={trueify:function(){return!0},falsify:function(){return!1},zeroify:function(){return 0},noop:function(){},error:function(e){console.error?(console.error.apply(console,arguments),console.trace&&console.trace()):(console.log.apply(console,arguments),console.trace&&console.trace())},clone:function(e){return this.extend({},e)},copy:function(e){return null==e?e:n.array(e)?e.slice():n.plainObject(e)?this.clone(e):e},uuid:function(e,t){for(t=e="";e++<36;t+=51*e&52?(15^e?8^Math.random()*(20^e?16:4):4).toString(16):"-");return t}};a.makeBoundingBox=i.makeBoundingBox.bind(i),a._staticEmptyObject={},a.staticEmptyObject=function(){return a._staticEmptyObject},a.extend=null!=Object.assign?Object.assign:function(e){for(var t=arguments,r=1;r=0&&(e[n]!==t||(e.splice(n,1),r));n--);},a.clearArray=function(e){e.splice(0,e.length)},a.getPrefixedProperty=function(e,t,r){return r&&(t=this.prependCamel(r,t)),e[t]},a.setPrefixedProperty=function(e,t,r,n){r&&(t=this.prependCamel(r,t)),e[t]=n},[e("./colors"),e("./maps"),{memoize:e("./memoize")},e("./regex"),e("./strings"),e("./timing")].forEach(function(e){a.extend(a,e)}),t.exports=a},{"../is":83,"../math":85,"./colors":99,"./maps":101,"./memoize":102,"./regex":103,"./strings":104,"./timing":105}],101:[function(e,t,r){"use strict";var n=e("../is");t.exports={mapEmpty:function(e){var t=!0;return null!=e?0===Object.keys(e).length:t},pushMap:function(e){var t=this.getMap(e);null==t?this.setMap(this.extend({},e,{value:[e.value]})):t.push(e.value)},setMap:function(e){for(var t,r=e.map,i=e.keys,a=i.length,o=0;a>o;o++){var t=i[o];n.plainObject(t)&&this.error("Tried to set map with object key"),oa;a++){var o=r[a];if(n.plainObject(o)&&this.error("Tried to get map with object key"),t=t[o],null==t)return t}return t},deleteMap:function(e){for(var t=e.map,r=e.keys,i=r.length,a=e.keepChildren,o=0;i>o;o++){var s=r[o];n.plainObject(s)&&this.error("Tried to delete map with object key");var l=o===e.keys.length-1;if(l)if(a)for(var u=Object.keys(t),c=0;c=r){a&&clearTimeout(a);var i=c;a=u=c=void 0,i&&(h=d.now(),o=e.apply(l,n),u||a||(n=l=null))}else u=setTimeout(g,r)},y=function(){u&&clearTimeout(u),a=u=c=void 0,(f||p!==t)&&(h=d.now(),o=e.apply(l,n),u||a||(n=l=null))};return function(){if(n=arguments,s=d.now(),l=this,c=f&&(u||!v),p===!1)var r=v&&!u;else{a||v||(h=s);var i=p-(s-h),m=0>=i;m?(a&&(a=clearTimeout(a)),h=s,o=e.apply(l,n)):a||(a=setTimeout(y,i))}return m&&u?u=clearTimeout(u):u||t===p||(u=setTimeout(g,t)),r&&(m=!0,o=e.apply(l,n)),!m||u||a||(n=l=null),o}}},t.exports=o},{"../is":83,"../window":107}],106:[function(e,t,r){t.exports="2.7.8"},{}],107:[function(e,t,r){t.exports="undefined"==typeof window?null:window},{}]},{},[82])(82)}); \ No newline at end of file +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.cytoscape=t()}(this,function(){"use strict";function E(e){return(E="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){for(var n=0;n>>0},oe=function(e){return(33*(1>>0},se=function(e,t){var n={value:0,done:!1},r=0,i=e.length;return ie({next:function(){return r>1])<0;)e[n]=a,n=o;return e[n]=i},h=function(e,t,n){var r,i,a,o,s;for(null==n&&(n=d),i=e.length,a=e[s=t],r=2*t+1;rD&&(p[S]=D,y[S]=C,m[S]=x),!r){var T=C*u+k;!r&&p[T]>D&&(p[T]=D,y[T]=k,m[T]=x)}}}for(var P=0;P=e.x1&&e.y2>=e.y1)return{x1:e.x1,y1:e.y1,x2:e.x2,y2:e.y2,w:e.x2-e.x1,h:e.y2-e.y1};if(null!=e.w&&null!=e.h&&0<=e.w&&0<=e.h)return{x1:e.x1,y1:e.y1,x2:e.x1+e.w,y2:e.y1+e.h,w:e.w,h:e.h}}},ot=function(e){var t=1t.x2)&&(!(t.x1>e.x2)&&(!(e.x2t.y2)&&!(t.y1>e.y2)))))))},ct=function(e,t,n){return e.x1<=t&&t<=e.x2&&e.y1<=n&&n<=e.y2},ht=function(e,t){return ct(e,t.x1,t.y1)&&ct(e,t.x2,t.y2)},dt=function(e,t,n,r,i,a,o){var s,l=Tt(i,a),u=i/2,c=a/2,h=r-c-o;if(0<(s=wt(e,t,n,r,n-u+l-o,h,n+u-l+o,h,!1)).length)return s;var d=n+u+o;if(0<(s=wt(e,t,n,r,d,r-c+l-o,d,r+c-l+o,!1)).length)return s;var p=r+c+o;if(0<(s=wt(e,t,n,r,n-u+l-o,p,n+u-l+o,p,!1)).length)return s;var f,g=n-u-o;if(0<(s=wt(e,t,n,r,g,r-c+l-o,g,r+c-l+o,!1)).length)return s;var v=n-u+l,y=r-c+l;if(0<(f=bt(e,t,n,r,v,y,l+o)).length&&f[0]<=v&&f[1]<=y)return[f[0],f[1]];var m=n+u-l,b=r-c+l;if(0<(f=bt(e,t,n,r,m,b,l+o)).length&&f[0]>=m&&f[1]<=b)return[f[0],f[1]];var x=n+u-l,w=r+c-l;if(0<(f=bt(e,t,n,r,x,w,l+o)).length&&f[0]>=x&&f[1]>=w)return[f[0],f[1]];var E=n-u+l,k=r+c-l;return 0<(f=bt(e,t,n,r,E,k,l+o)).length&&f[0]<=E&&f[1]>=k?[f[0],f[1]]:[]},pt=function(e,t,n,r,i,a,o,s){var l,u,c,h,d,p,f,g,v,y,m,b,x,w=[];u=9*n*i-3*n*n-3*n*o-6*i*i+3*i*o+9*r*a-3*r*r-3*r*s-6*a*a+3*a*s,c=3*n*n-6*n*i+n*o-n*e+2*i*i+2*i*e-o*e+3*r*r-6*r*a+r*s-r*t+2*a*a+2*a*t-s*t,h=1*n*i-n*n+n*e-i*e+r*a-r*r+r*t-a*t,g=-27*(h/=l=1*n*n-4*n*i+2*n*o+4*i*i-4*i*o+o*o+r*r-4*r*a+2*r*s+4*a*a-4*a*s+s*s)+(u/=l)*(9*(c/=l)-u*u*2),p=(f=(3*c-u*u)/9)*f*f+(g/=54)*g,b=u/3,((d=w)[1]=0)a[u]+f&&(a[h]=a[u]+f,o.nodes.indexOf(h)<0?o.push(h):o.updateItem(h),i[h]=0,r[h]=[]),a[h]==a[u]+f&&(i[h]=i[h]+i[u],r[h].push(u))}else for(var g=0;gi&&(i=t[l][u],a=u);o[a].push(e[l])}for(var c=0;c=i.threshold||"dendrogram"===i.mode&&1===e.length)return!1;var p,f=t[o],g=t[r[o]];p="dendrogram"===i.mode?{left:f,right:g,key:f.key}:{value:f.value.concat(g.value),key:f.key},e[f.index]=p,e.splice(g.index,1),t[f.key]=p;for(var v=0;vn[g.key][y.key]&&(a=n[g.key][y.key])):"max"===i.linkage?(a=n[f.key][y.key],n[f.key][y.key]o&&(o=t[i*e+(a=l)])}0=u.minIterations-1||E==u.maxIterations-1)){for(var F=0,V=0;V\\?\\@\\[\\]\\^\\`\\{\\|\\}\\~]",comparatorOp:"=|\\!=|>|>=|<|<=|\\$=|\\^=|\\*=",boolOp:"\\?|\\!|\\^",string:'"(?:\\\\"|[^"])*"|'+"'(?:\\\\'|[^'])*'",number:W,meta:"degree|indegree|outdegree",separator:"\\s*,\\s*",descendant:"\\s+",child:"\\s+>\\s+",subject:"\\$",group:"node|edge|\\*",directedEdge:"\\s+->\\s+",undirectedEdge:"\\s+<->\\s+"};jn.variable="(?:[\\w-]|(?:\\\\"+jn.metaChar+"))+",jn.value=jn.string+"|"+jn.number,jn.className=jn.variable,jn.id=jn.variable,function(){var e,t,n;for(e=jn.comparatorOp.split("|"),n=0;n")+v(e.child,t);case ur:case sr:return v(e.ancestor,t)+" "+v(e.descendant,t);case cr:var c=v(e.left,t),h=v(e.subject,t),d=v(e.right,t);return c+(0":h=!0,r=n=":h=!0,r=n<=e;break;case"<":h=!0,r=ee.x2?r:e.x2,e.y1=ne.y2?i:e.y2)},Gr=function(e,t){return Kr(e,t.x1,t.y1,t.x2,t.y2)},Zr=function(e,t,n){return De(e,t,n)},Ur=function(e,t,n){if(!t.cy().headless()){var r,i,a=t._private,o=a.rstyle,s=o.arrowWidth/2;if("none"!==t.pstyle(n+"-arrow-shape").value){i="source"===n?(r=o.srcX,o.srcY):"target"===n?(r=o.tgtX,o.tgtY):(r=o.midX,o.midY);var l=a.arrowBounds=a.arrowBounds||{},u=l[n]=l[n]||{};u.x1=r-s,u.y1=i-s,u.x2=r+s,u.y2=i+s,u.w=u.x2-u.x1,u.h=u.y2-u.y1,ot(u,1),Kr(e,u.x1,u.y1,u.x2,u.y2)}}},$r=function(e,t,n){if(!t.cy().headless()){var r;r=n?n+"-":"";var i=t._private,a=i.rstyle;if(t.pstyle(r+"label").strValue){var o,s,l,u,c=t.pstyle("text-halign"),h=t.pstyle("text-valign"),d=Zr(a,"labelWidth",n),p=Zr(a,"labelHeight",n),f=Zr(a,"labelX",n),g=Zr(a,"labelY",n),v=t.pstyle(r+"text-margin-x").pfValue,y=t.pstyle(r+"text-margin-y").pfValue,m=t.isEdge(),b=t.pstyle(r+"text-rotation"),x=t.pstyle("text-outline-width").pfValue,w=t.pstyle("text-border-width").pfValue/2,E=t.pstyle("text-background-padding").pfValue,k=p+2*E,C=d+2*E,S=C/2,D=k/2;if(m)o=f-S,s=f+S,l=g-D,u=g+D;else{switch(c.value){case"left":o=f-C,s=f;break;case"center":o=f-S,s=f+S;break;case"right":s=(o=f)+C}switch(h.value){case"top":l=g-k,u=g;break;case"center":l=g-D,u=g+D;break;case"bottom":u=(l=g)+k}}o+=v-Math.max(x,w),s+=v+Math.max(x,w),l+=y-Math.max(x,w),u+=y+Math.max(x,w);var T=n||"main",P=i.labelBounds,M=P[T]=P[T]||{};M.x1=o,M.y1=l,M.x2=s,M.y2=u,M.w=s-o,M.h=u-l,ot(M,1);var _=m&&"autorotate"===b.strValue,B=null!=b.pfValue&&0!==b.pfValue;if(_||B){var N=_?Zr(i.rstyle,"labelAngle",n):b.pfValue,I=Math.cos(N),A=Math.sin(N),L=(o+s)/2,z=(l+u)/2;if(!m){switch(c.value){case"left":L=s;break;case"right":L=o}switch(h.value){case"top":z=u;break;case"bottom":z=l}}var O=function(e,t){return{x:(e-=L)*I-(t-=z)*A+L,y:e*A+t*I+z}},R=O(o,l),F=O(o,u),V=O(s,l),q=O(s,u);o=Math.min(R.x,F.x,V.x,q.x),s=Math.max(R.x,F.x,V.x,q.x),l=Math.min(R.y,F.y,V.y,q.y),u=Math.max(R.y,F.y,V.y,q.y)}Kr(e,o,l,s,u),Kr(i.labelBounds.all,o,l,s,u)}return e}},Qr=function(e){var t=0,n=function(e){return(e?1:0)<u&&++at.length?i.substr(t.length):""}function o(){n=n.length>r.length?n.substr(r.length):""}for(i=i.replace(/[/][*](\s|.)+?[*][/]/g,"");;){if(i.match(/^\s*$/))break;var s=i.match(/^\s*((?:.|\s)+?)\s*\{((?:.|\s)+?)\}/);if(!s){be("Halting stylesheet parsing: String stylesheet contains more to parse but no selector and block found in: "+i);break}t=s[0];var l=s[1];if("core"!==l)if(new Cr(l).invalid){be("Skipping parsing of block: Invalid selector found in string stylesheet: "+l),a();continue}var u=s[2],c=!1;n=u;for(var h=[];;){if(n.match(/^\s*$/))break;var d=n.match(/^\s*(.+?)\s*:\s*(.+?)\s*;/);if(!d){be("Skipping parsing of block: Invalid formatting of style property and value definitions found in:"+u),c=!0;break}r=d[0];var p=d[1],f=d[2];if(this.properties[p])this.parse(p,f)?h.push({name:p,val:f}):be("Skipping property: Invalid property definition in: "+r),o();else be("Skipping property: Invalid property name in: "+r),o()}if(c){a();break}this.selector(l);for(var g=0;gc.max||c.strictMax&&n===c.max))return null;var N={name:t,value:n,strValue:""+n+(P||""),units:P,bypass:r};return c.unitless||"px"!==P&&"em"!==P?N.pfValue=n:N.pfValue="px"!==P&&P?this.getEmSizeInPixels()*n:n,"ms"!==P&&"s"!==P||(N.pfValue="ms"===P?n:1e3*n),"deg"!==P&&"rad"!==P||(N.pfValue="rad"===P?n:(S=n,Math.PI*S/180)),"%"===P&&(N.pfValue=n/100),N}if(c.propList){var I=[],A=""+n;if("none"===A);else{for(var L=A.split(/\s*,\s*|\s+/),z=0;zthis._private.maxZoom?this._private.maxZoom:o)=n.minZoom&&(n.maxZoom=t),this},minZoom:function(e){return void 0===e?this._private.minZoom:this.zoomRange({min:e})},maxZoom:function(e){return void 0===e?this._private.maxZoom:this.zoomRange({max:e})},getZoomedViewport:function(e){var t,n,r=this._private,i=r.pan,a=r.zoom,o=!1;if(r.zoomingEnabled||(o=!0),$t(e)?n=e:B(e)&&(n=e.level,null!=e.position?t=Ze(e.position,a,i):null!=e.renderedPosition&&(t=e.renderedPosition),null==t||r.panningEnabled||(o=!0)),n=(n=n>r.maxZoom?r.maxZoom:n)t.maxZoom||!t.zoomingEnabled?a=!0:(t.zoom=s,i.push("zoom"))}if(r&&(!a||!e.cancelOnFailedZoom)&&t.panningEnabled){var l=e.pan;$t(l.x)&&(t.pan.x=l.x,o=!1),$t(l.y)&&(t.pan.y=l.y,o=!1),o||i.push("pan")}return 0i.maxX)&&(i.maxX=t.maxX+i.padRight,a=!0),(null==i.minX||t.minX-i.padLefti.maxY)&&(i.maxY=t.maxY+i.padBottom,a=!0),(null==i.minY||t.minY-i.padTop(g=ee,v=te,y=K[G],m=K[G+1],b=K[G+2],x=K[G+3],void 0,C=(w=[g-y,v-m])[0]*w[0]+w[1]*w[1],D=(S=w[0]*(E=[b-y,x-m])[0]+w[1]*E[1])*S/(k=E[0]*E[0]+E[1]*E[1]),t=S<0?C:k(t=pt(ee,te,K[G],K[G+1],K[G+2],K[G+3],K[G+4],K[G+5])))return se(e,t),!0;W=W||R.source,H=H||R.target;var Z=ne.getArrowWidth(V,q),U=[{name:"source",x:F.arrowStartX,y:F.arrowStartY,angle:F.srcArrowAngle},{name:"target",x:F.arrowEndX,y:F.arrowEndY,angle:F.tgtArrowAngle},{name:"mid-source",x:F.midX,y:F.midY,angle:F.midsrcArrowAngle},{name:"mid-target",x:F.midX,y:F.midY,angle:F.midtgtArrowAngle}];for(G=0;Gr.id()){var B=n;n=r,r=B}i=n.position(),a=r.position(),o=n.outerWidth(),s=n.outerHeight(),l=r.outerWidth(),u=r.outerHeight(),c=this.nodeShapes[this.getNodeShape(n)],h=this.nodeShapes[this.getNodeShape(r)],p=!1;var N={north:0,west:0,south:0,east:0,northwest:0,southwest:0,northeast:0,southeast:0},I=i.x,A=i.y,L=o,z=s,O=a.x,R=a.y,F=l,V=u,q=M.length;for(b=0;b=q.desktopTapThreshold2}var b=B(e);c&&(q.hoverData.tapholdCancelled=!0);t=!0,Y(u,["mousemove","vmousemove","tapdrag"],e,{x:a[0],y:a[1]});var x,w=function(){q.data.bgActivePosistion=void 0,q.hoverData.selecting||n.emit({originalEvent:e,type:"boxstart",position:{x:a[0],y:a[1]}}),l[4]=1,q.hoverData.selecting=!0,q.redrawHint("select",!0),q.redraw()};if(3===q.hoverData.which){if(c){var E={originalEvent:e,type:"cxtdrag",position:{x:a[0],y:a[1]}};d?d.emit(E):n.emit(E),q.hoverData.cxtDragged=!0,q.hoverData.cxtOver&&u===q.hoverData.cxtOver||(q.hoverData.cxtOver&&q.hoverData.cxtOver.emit({originalEvent:e,type:"cxtdragout",position:{x:a[0],y:a[1]}}),(q.hoverData.cxtOver=u)&&u.emit({originalEvent:e,type:"cxtdragover",position:{x:a[0],y:a[1]}}))}}else if(q.hoverData.dragging){if(t=!0,n.panningEnabled()&&n.userPanningEnabled()){var k;if(q.hoverData.justStartedPan){var C=q.hoverData.mdownPos;k={x:(a[0]-C[0])*r,y:(a[1]-C[1])*r},q.hoverData.justStartedPan=!1}else k={x:p[0]*r,y:p[1]*r};n.panBy(k),q.hoverData.dragged=!0}a=q.projectIntoViewport(e.clientX,e.clientY)}else if(1!=l[4]||null!=d&&!d.isEdge()){if(d&&d.isEdge()&&d.active()&&d.unactivate(),d&&d.grabbed()||u==h||(h&&Y(h,["mouseout","tapdragout"],e,{x:a[0],y:a[1]}),u&&Y(u,["mouseover","tapdragover"],e,{x:a[0],y:a[1]}),q.hoverData.last=u),d)if(c){if(n.boxSelectionEnabled()&&b)d&&d.grabbed()&&(W(f),d.emit("freeon"),f.emit("free"),q.dragData.didDrag&&(d.emit("dragfreeon"),f.emit("dragfree"))),w();else if(d&&d.grabbed()&&q.nodeIsDraggable(d)){var S=!q.dragData.didDrag;S&&q.redrawHint("eles",!0),q.dragData.didDrag=!0;var D=n.collection();q.hoverData.draggingEles||j(f,{inDragLayer:!0});var T={x:0,y:0};if($t(p[0])&&$t(p[1])&&(T.x+=p[0],T.y+=p[1],S)){var P=q.hoverData.dragDelta;P&&$t(P[0])&&$t(P[1])&&(T.x+=P[0],T.y+=P[1])}for(var M=0;M=q.touchTapThreshold2}if(t&&q.touchData.cxt){e.preventDefault();var g=e.touches[0].clientX-ee,v=e.touches[0].clientY-te,y=e.touches[1].clientX-ee,m=e.touches[1].clientY-te,b=ie(g,v,y,m);if(2.25<=b/Q||22500<=b){q.touchData.cxt=!1,q.data.bgActivePosistion=void 0,q.redrawHint("select",!0);var x={originalEvent:e,type:"cxttapend",position:{x:i[0],y:i[1]}};q.touchData.start?(q.touchData.start.unactivate().emit(x),q.touchData.start=null):r.emit(x)}}if(t&&q.touchData.cxt){x={originalEvent:e,type:"cxtdrag",position:{x:i[0],y:i[1]}};q.data.bgActivePosistion=void 0,q.redrawHint("select",!0),q.touchData.start?q.touchData.start.emit(x):r.emit(x),q.touchData.start&&(q.touchData.start._private.grabbed=!1),q.touchData.cxtDragged=!0;var w=q.findNearestElement(i[0],i[1],!0,!0);q.touchData.cxtOver&&w===q.touchData.cxtOver||(q.touchData.cxtOver&&q.touchData.cxtOver.emit({originalEvent:e,type:"cxtdragout",position:{x:i[0],y:i[1]}}),(q.touchData.cxtOver=w)&&w.emit({originalEvent:e,type:"cxtdragover",position:{x:i[0],y:i[1]}}))}else if(t&&e.touches[2]&&r.boxSelectionEnabled())e.preventDefault(),q.data.bgActivePosistion=void 0,this.lastThreeTouch=+new Date,q.touchData.selecting||r.emit({originalEvent:e,type:"boxstart",position:{x:i[0],y:i[1]}}),q.touchData.selecting=!0,q.redrawHint("select",!0),n&&0!==n.length&&void 0!==n[0]?(n[2]=(i[0]+i[2]+i[4])/3,n[3]=(i[1]+i[3]+i[5])/3):(n[0]=(i[0]+i[2]+i[4])/3,n[1]=(i[1]+i[3]+i[5])/3,n[2]=(i[0]+i[2]+i[4])/3+1,n[3]=(i[1]+i[3]+i[5])/3+1),n[4]=1,q.touchData.selecting=!0,q.redraw();else if(t&&e.touches[1]&&r.zoomingEnabled()&&r.panningEnabled()&&r.userZoomingEnabled()&&r.userPanningEnabled()){if(e.preventDefault(),q.data.bgActivePosistion=void 0,q.redrawHint("select",!0),L=q.dragData.touchDragEles){q.redrawHint("drag",!0);for(var E=0;E=y.deqFastCost*h)break}else if(e){if(u>=y.deqCost*i||u>=y.deqAvgCost*r)break}else if(c>=y.deqNoDrawCost*Lo)break;var d=y.deq(f,s,o);if(!(0=.2*e.width&&this.retireTexture(e)},qo.checkTextureFullness=function(e){var t=this.getTextureQueue(e.height);.8=t)return a.retired=!1,a.usedWidth=0,a.invalidatedWidth=0,a.fullnessChecks=0,Qt(a.eleCaches),a.context.setTransform(1,0,0,1,0,0),a.context.clearRect(0,0,a.width,a.height),Se(r,a),n.push(a),a}},qo.queueElement=function(e,t){var n=this.getElementQueue(),r=this.getElementKeyToQueue(),i=this.getKey(e),a=r[i];if(a)a.level=Math.max(a.level,t),a.eles.merge(e),a.reqs++,n.updateItem(a);else{var o={eles:e.spawn().merge(e),level:t,reqs:1,key:i};n.push(o),r[i]=o}},qo.dequeue=function(e){for(var t=this.getElementQueue(),n=this.getElementKeyToQueue(),r=[],i=this.lookup,a=0;a<1&&0=p||!ht(d.bb,v.boundingBox()))&&!(d=r({insert:!0,after:d})))return null;l||f?o.queueLayer(d,v):o.drawEleInLayer(d,v,a,e),d.eles.push(v),m[a]=d}}return l||(f?null:h)},Xo.getEleLevelForLayerLevel=function(e,t){return e},Xo.drawEleInLayer=function(e,t,n,r){var i=this.renderer,a=e.context,o=t.boundingBox();0!==o.w&&0!==o.h&&t.visible()&&(n=this.getEleLevelForLayerLevel(n,r),i.setImgSmoothing(a,!1),i.drawCachedElement(a,t,null,null,n,!0),i.setImgSmoothing(a,!0))},Xo.levelIsComplete=function(e,t){var n=this.layersByLevel[e];if(!n||0===n.length)return!1;for(var r=0,i=0;ic.minMbLowQualFrames&&(c.motionBlurPxRatio=c.mbPxRBlurry)),c.clearingMotionBlur&&(c.motionBlurPxRatio=1),c.textureDrawLastFrame&&!a&&(i[c.NODE]=!0,i[c.SELECT_BOX]=!0);var m=r.style(),b=r.zoom(),x=void 0!==l?l:b,w=r.pan(),E={x:w.x,y:w.y},k={zoom:b,pan:{x:w.x,y:w.y}},C=c.prevViewport;void 0===C||k.zoom!==C.zoom||k.pan.x!==C.pan.x||k.pan.y!==C.pan.y||g&&!f||(c.motionBlurPxRatio=1),u&&(E=u),x*=n,E.x*=n,E.y*=n;var S=c.getCachedZSortedEles();function D(e,t,n,r,i){var a=e.globalCompositeOperation;e.globalCompositeOperation="destination-out",c.colorFillStyle(e,255,255,255,c.motionBlurTransparency),e.fillRect(t,n,r,i),e.globalCompositeOperation=a}function T(e,t){var n,r,i,a;a=c.clearingMotionBlur||e!==h.bufferContexts[c.MOTIONBLUR_BUFFER_NODE]&&e!==h.bufferContexts[c.MOTIONBLUR_BUFFER_DRAG]?(n=E,r=x,i=c.canvasWidth,c.canvasHeight):(n={x:w.x*p,y:w.y*p},r=b*p,i=c.canvasWidth*p,c.canvasHeight*p),e.setTransform(1,0,0,1,0,0),"motionBlur"===t?D(e,0,0,i,a):o||void 0!==t&&!t||e.clearRect(0,0,i,a),s||(e.translate(n.x,n.y),e.scale(r,r)),u&&e.translate(u.x,u.y),l&&e.scale(l,l)}if(a||(c.textureDrawLastFrame=!1),a){if(c.textureDrawLastFrame=!0,!c.textureCache){c.textureCache={},c.textureCache.bb=r.mutableElements().boundingBox(),c.textureCache.texture=c.data.bufferCanvases[c.TEXTURE_BUFFER];var P=c.data.bufferContexts[c.TEXTURE_BUFFER];P.setTransform(1,0,0,1,0,0),P.clearRect(0,0,c.canvasWidth*c.textureMult,c.canvasHeight*c.textureMult),c.render({forcedContext:P,drawOnlyNodeLayer:!0,forcedPxRatio:n*c.textureMult}),(k=c.textureCache.viewport={zoom:r.zoom(),pan:r.pan(),width:c.canvasWidth,height:c.canvasHeight}).mpan={x:(0-k.pan.x)/k.zoom,y:(0-k.pan.y)/k.zoom}}i[c.DRAG]=!1,i[c.NODE]=!1;var M=h.contexts[c.NODE],_=c.textureCache.texture;k=c.textureCache.viewport;M.setTransform(1,0,0,1,0,0),d?D(M,0,0,k.width,k.height):M.clearRect(0,0,k.width,k.height);var B=m.core("outside-texture-bg-color").value,N=m.core("outside-texture-bg-opacity").value;c.colorFillStyle(M,B[0],B[1],B[2],N),M.fillRect(0,0,k.width,k.height);b=r.zoom();T(M,!1),M.clearRect(k.mpan.x,k.mpan.y,k.width/k.zoom/n,k.height/k.zoom/n),M.drawImage(_,k.mpan.x,k.mpan.y,k.width/k.zoom/n,k.height/k.zoom/n)}else c.textureOnViewport&&!o&&(c.textureCache=null);var I=r.extent(),A=c.pinching||c.hoverData.dragging||c.swipePanning||c.data.wheelZooming||c.hoverData.draggingEles,L=c.hideEdgesOnViewport&&A,z=[];if(z[c.NODE]=!i[c.NODE]&&d&&!c.clearedForMotionBlur[c.NODE]||c.clearingMotionBlur,z[c.NODE]&&(c.clearedForMotionBlur[c.NODE]=!0),z[c.DRAG]=!i[c.DRAG]&&d&&!c.clearedForMotionBlur[c.DRAG]||c.clearingMotionBlur,z[c.DRAG]&&(c.clearedForMotionBlur[c.DRAG]=!0),i[c.NODE]||s||t||z[c.NODE]){var O=d&&!z[c.NODE]&&1!==p;T(M=o||(O?c.data.bufferContexts[c.MOTIONBLUR_BUFFER_NODE]:h.contexts[c.NODE]),d&&!O?"motionBlur":void 0),L?c.drawCachedNodes(M,S.nondrag,n,I):c.drawLayeredElements(M,S.nondrag,n,I),c.debug&&c.drawDebugPoints(M,S.nondrag),s||d||(i[c.NODE]=!1)}if(!t&&(i[c.DRAG]||s||z[c.DRAG])){O=d&&!z[c.DRAG]&&1!==p;T(M=o||(O?c.data.bufferContexts[c.MOTIONBLUR_BUFFER_DRAG]:h.contexts[c.DRAG]),d&&!O?"motionBlur":void 0),L?c.drawCachedNodes(M,S.drag,n,I):c.drawCachedElements(M,S.drag,n,I),c.debug&&c.drawDebugPoints(M,S.drag),s||d||(i[c.DRAG]=!1)}if(c.showFps||!t&&i[c.SELECT_BOX]&&!s){if(T(M=o||h.contexts[c.SELECT_BOX]),1==c.selection[4]&&(c.hoverData.selecting||c.touchData.selecting)){b=c.cy.zoom();var R=m.core("selection-box-border-width").value/b;M.lineWidth=R,M.fillStyle="rgba("+m.core("selection-box-color").value[0]+","+m.core("selection-box-color").value[1]+","+m.core("selection-box-color").value[2]+","+m.core("selection-box-opacity").value+")",M.fillRect(c.selection[0],c.selection[1],c.selection[2]-c.selection[0],c.selection[3]-c.selection[1]),0/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g, '/'); - }; - - Position = { - getName: function(position) { - return Position.strings[position - 1]; - }, - nameToIndex: function(name) { - var i, _i, _ref1; - - for (i = _i = 1, _ref1 = Position.strings.length; 1 <= _ref1 ? _i <= _ref1 : _i >= _ref1; i = 1 <= _ref1 ? ++_i : --_i) { - if (Position.strings[i - 1] === name) { - return i; - } - } - return 0; - } - }; - - Position.BEFORE = 1; - - Position.AFTER = 2; - - Position.INSIDE = 3; - - Position.NONE = 4; - - Position.strings = ['before', 'after', 'inside', 'none']; - - this.Tree.Position = Position; - - Node = (function() { - function Node(o, is_root, node_class) { - if (is_root == null) { - is_root = false; - } - if (node_class == null) { - node_class = Node; - } - this.setData(o); - this.children = []; - this.parent = null; - if (is_root) { - this.id_mapping = {}; - this.tree = this; - this.node_class = node_class; - } - } - - Node.prototype.setData = function(o) { - var key, value, _results; - - if (typeof o !== 'object') { - return this.name = o; - } else { - _results = []; - for (key in o) { - value = o[key]; - if (key === 'label') { - _results.push(this.name = value); - } else { - _results.push(this[key] = value); - } - } - return _results; - } - }; - - Node.prototype.initFromData = function(data) { - var addChildren, addNode, - _this = this; - - addNode = function(node_data) { - _this.setData(node_data); - if (node_data.children) { - return addChildren(node_data.children); - } - }; - addChildren = function(children_data) { - var child, node, _i, _len; - - for (_i = 0, _len = children_data.length; _i < _len; _i++) { - child = children_data[_i]; - node = new _this.tree.node_class(''); - node.initFromData(child); - _this.addChild(node); - } - return null; - }; - addNode(data); - return null; - }; - - /* - Create tree from data. - - Structure of data is: - [ - { - label: 'node1', - children: [ - { label: 'child1' }, - { label: 'child2' } - ] - }, - { - label: 'node2' - } - ] - */ - - - Node.prototype.loadFromData = function(data) { - var node, o, _i, _len; - - this.removeChildren(); - for (_i = 0, _len = data.length; _i < _len; _i++) { - o = data[_i]; - node = new this.tree.node_class(o); - this.addChild(node); - if (typeof o === 'object' && o.children) { - node.loadFromData(o.children); - } - } - return null; - }; - - /* - Add child. - - tree.addChild( - new Node('child1') - ); - */ - - - Node.prototype.addChild = function(node) { - this.children.push(node); - return node._setParent(this); - }; - - /* - Add child at position. Index starts at 0. - - tree.addChildAtPosition( - new Node('abc'), - 1 - ); - */ - - - Node.prototype.addChildAtPosition = function(node, index) { - this.children.splice(index, 0, node); - return node._setParent(this); - }; - - Node.prototype._setParent = function(parent) { - this.parent = parent; - this.tree = parent.tree; - return this.tree.addNodeToIndex(this); - }; - - /* - Remove child. This also removes the children of the node. - - tree.removeChild(tree.children[0]); - */ - - - Node.prototype.removeChild = function(node) { - node.removeChildren(); - return this._removeChild(node); - }; - - Node.prototype._removeChild = function(node) { - this.children.splice(this.getChildIndex(node), 1); - return this.tree.removeNodeFromIndex(node); - }; - - /* - Get child index. - - var index = getChildIndex(node); - */ - - - Node.prototype.getChildIndex = function(node) { - return $.inArray(node, this.children); - }; - - /* - Does the tree have children? - - if (tree.hasChildren()) { - // - } - */ - - - Node.prototype.hasChildren = function() { - return this.children.length !== 0; - }; - - Node.prototype.isFolder = function() { - return this.hasChildren() || this.load_on_demand; - }; - - /* - Iterate over all the nodes in the tree. - - Calls callback with (node, level). - - The callback must return true to continue the iteration on current node. - - tree.iterate( - function(node, level) { - console.log(node.name); - - // stop iteration after level 2 - return (level <= 2); - } - ); - */ - - - Node.prototype.iterate = function(callback) { - var _iterate, - _this = this; - - _iterate = function(node, level) { - var child, result, _i, _len, _ref1; - - if (node.children) { - _ref1 = node.children; - for (_i = 0, _len = _ref1.length; _i < _len; _i++) { - child = _ref1[_i]; - result = callback(child, level); - if (_this.hasChildren() && result) { - _iterate(child, level + 1); - } - } - return null; - } - }; - _iterate(this, 0); - return null; - }; - - /* - Move node relative to another node. - - Argument position: Position.BEFORE, Position.AFTER or Position.Inside - - // move node1 after node2 - tree.moveNode(node1, node2, Position.AFTER); - */ - - - Node.prototype.moveNode = function(moved_node, target_node, position) { - if (moved_node.isParentOf(target_node)) { - return; - } - moved_node.parent._removeChild(moved_node); - if (position === Position.AFTER) { - return target_node.parent.addChildAtPosition(moved_node, target_node.parent.getChildIndex(target_node) + 1); - } else if (position === Position.BEFORE) { - return target_node.parent.addChildAtPosition(moved_node, target_node.parent.getChildIndex(target_node)); - } else if (position === Position.INSIDE) { - return target_node.addChildAtPosition(moved_node, 0); - } - }; - - /* - Get the tree as data. - */ - - - Node.prototype.getData = function() { - var getDataFromNodes, - _this = this; - - getDataFromNodes = function(nodes) { - var data, k, node, tmp_node, v, _i, _len; - - data = []; - for (_i = 0, _len = nodes.length; _i < _len; _i++) { - node = nodes[_i]; - tmp_node = {}; - for (k in node) { - v = node[k]; - if ((k !== 'parent' && k !== 'children' && k !== 'element' && k !== 'tree') && Object.prototype.hasOwnProperty.call(node, k)) { - tmp_node[k] = v; - } - } - if (node.hasChildren()) { - tmp_node.children = getDataFromNodes(node.children); - } - data.push(tmp_node); - } - return data; - }; - return getDataFromNodes(this.children); - }; - - Node.prototype.getNodeByName = function(name) { - var result; - - result = null; - this.iterate(function(node) { - if (node.name === name) { - result = node; - return false; - } else { - return true; - } - }); - return result; - }; - - Node.prototype.addAfter = function(node_info) { - var child_index, node; - - if (!this.parent) { - return null; - } else { - node = new this.tree.node_class(node_info); - child_index = this.parent.getChildIndex(this); - this.parent.addChildAtPosition(node, child_index + 1); - return node; - } - }; - - Node.prototype.addBefore = function(node_info) { - var child_index, node; - - if (!this.parent) { - return null; - } else { - node = new this.tree.node_class(node_info); - child_index = this.parent.getChildIndex(this); - this.parent.addChildAtPosition(node, child_index); - return node; - } - }; - - Node.prototype.addParent = function(node_info) { - var child, new_parent, original_parent, _i, _len, _ref1; - - if (!this.parent) { - return null; - } else { - new_parent = new this.tree.node_class(node_info); - new_parent._setParent(this.tree); - original_parent = this.parent; - _ref1 = original_parent.children; - for (_i = 0, _len = _ref1.length; _i < _len; _i++) { - child = _ref1[_i]; - new_parent.addChild(child); - } - original_parent.children = []; - original_parent.addChild(new_parent); - return new_parent; - } - }; - - Node.prototype.remove = function() { - if (this.parent) { - this.parent.removeChild(this); - return this.parent = null; - } - }; - - Node.prototype.append = function(node_info) { - var node; - - node = new this.tree.node_class(node_info); - this.addChild(node); - return node; - }; - - Node.prototype.prepend = function(node_info) { - var node; - - node = new this.tree.node_class(node_info); - this.addChildAtPosition(node, 0); - return node; - }; - - Node.prototype.isParentOf = function(node) { - var parent; - - parent = node.parent; - while (parent) { - if (parent === this) { - return true; - } - parent = parent.parent; - } - return false; - }; - - Node.prototype.getLevel = function() { - var level, node; - - level = 0; - node = this; - while (node.parent) { - level += 1; - node = node.parent; - } - return level; - }; - - Node.prototype.getNodeById = function(node_id) { - return this.id_mapping[node_id]; - }; - - Node.prototype.addNodeToIndex = function(node) { - if (node.id) { - return this.id_mapping[node.id] = node; - } - }; - - Node.prototype.removeNodeFromIndex = function(node) { - if (node.id) { - return delete this.id_mapping[node.id]; - } - }; - - Node.prototype.removeChildren = function() { - var _this = this; - - this.iterate(function(child) { - _this.tree.removeNodeFromIndex(child); - return true; - }); - return this.children = []; - }; - - return Node; - - })(); - - this.Tree.Node = Node; - - JqTreeWidget = (function(_super) { - __extends(JqTreeWidget, _super); - - function JqTreeWidget() { - _ref1 = JqTreeWidget.__super__.constructor.apply(this, arguments); - return _ref1; - } - - JqTreeWidget.prototype.defaults = { - autoOpen: false, - saveState: false, - dragAndDrop: false, - selectable: true, - useContextMenu: true, - onCanSelectNode: null, - onSetStateFromStorage: null, - onGetStateFromStorage: null, - onCreateLi: null, - onIsMoveHandle: null, - onCanMove: null, - onCanMoveTo: null, - onLoadFailed: null, - autoEscape: true, - dataUrl: null, - closedIcon: '►', - openedIcon: '▼', - slide: true, - nodeClass: Node - }; - - JqTreeWidget.prototype.toggle = function(node, slide) { - if (slide == null) { - slide = true; - } - if (node.is_open) { - return this.closeNode(node, slide); - } else { - return this.openNode(node, slide); - } - }; - - JqTreeWidget.prototype.getTree = function() { - return this.tree; - }; - - JqTreeWidget.prototype.selectNode = function(node) { - return this._selectNode(node, true); - }; - - JqTreeWidget.prototype._selectNode = function(node, must_toggle) { - var canSelect, openParents, saveState, - _this = this; - - if (must_toggle == null) { - must_toggle = false; - } - canSelect = function() { - if (!_this.options.onCanSelectNode) { - return _this.options.selectable; - } - return _this.options.selectable && _this.options.onCanSelectNode(node); - }; - openParents = function() { - var parent; - - parent = node.parent; - if (!parent.is_open && parent.parent) { - return _this.openNode(parent, false); - } - }; - saveState = function() { - if (_this.options.saveState) { - return _this.save_state_handler.saveState(); - } - }; - if (!node) { - this._deselectCurrentNode(); - saveState; - return; - } - if (!canSelect()) { - return; - } - if (this.select_node_handler.isNodeSelected(node)) { - if (must_toggle) { - this._deselectCurrentNode(); - this._triggerEvent('tree.select', { - node: null - }); - } - } else { - this._deselectCurrentNode(); - this.addToSelection(node); - this._triggerEvent('tree.select', { - node: node - }); - openParents(); - } - return saveState(); - }; - - JqTreeWidget.prototype.getSelectedNode = function() { - return this.select_node_handler.getSelectedNode(); - }; - - JqTreeWidget.prototype.toJson = function() { - return JSON.stringify(this.tree.getData()); - }; - - JqTreeWidget.prototype.loadData = function(data, parent_node) { - return this._loadData(data, parent_node); - }; - - JqTreeWidget.prototype.loadDataFromUrl = function(url, parent_node, on_finished) { - if ($.type(url) !== 'string') { - on_finished = parent_node; - parent_node = url; - url = null; - } - return this._loadDataFromUrl(url, parent_node, on_finished); - }; - - JqTreeWidget.prototype._loadDataFromUrl = function(url_info, parent_node, on_finished) { - var $el, addLoadingClass, parseUrlInfo, removeLoadingClass, - _this = this; - - $el = null; - addLoadingClass = function() { - var folder_element; - - if (!parent_node) { - $el = _this.element; - } else { - folder_element = new FolderElement(parent_node, _this); - $el = folder_element.getLi(); - } - return $el.addClass('jqtree-loading'); - }; - removeLoadingClass = function() { - if ($el) { - return $el.removeClass('jqtree-loading'); - } - }; - parseUrlInfo = function() { - if ($.type(url_info) === 'string') { - url_info = { - url: url_info - }; - } - if (!url_info.method) { - return url_info.method = 'get'; - } - }; - addLoadingClass(); - if (!url_info) { - url_info = this._getDataUrlInfo(parent_node); - } - parseUrlInfo(); - return $.ajax({ - url: url_info.url, - data: url_info.data, - type: url_info.method.toUpperCase(), - cache: false, - dataType: 'json', - success: function(response) { - var data; - - if ($.isArray(response) || typeof response === 'object') { - data = response; - } else { - data = $.parseJSON(response); - } - removeLoadingClass(); - _this._loadData(data, parent_node); - if (on_finished && $.isFunction(on_finished)) { - return on_finished(); - } - }, - error: function(response) { - removeLoadingClass(); - if (_this.options.onLoadFailed) { - return _this.options.onLoadFailed(response); - } - } - }); - }; - - JqTreeWidget.prototype._loadData = function(data, parent_node) { - var n, selected_nodes_under_parent, _i, _len; - - this._triggerEvent('tree.load_data', { - tree_data: data - }); - if (!parent_node) { - this._initTree(data, false, this.options.nodeClass); - } else { - selected_nodes_under_parent = this.select_node_handler.getSelectedNodes(parent_node); - for (_i = 0, _len = selected_nodes_under_parent.length; _i < _len; _i++) { - n = selected_nodes_under_parent[_i]; - this.select_node_handler.removeFromSelection(n); - } - parent_node.loadFromData(data); - parent_node.load_on_demand = false; - this._refreshElements(parent_node.parent); - } - if (this.is_dragging) { - return this.dnd_handler.refreshHitAreas(); - } - }; - - JqTreeWidget.prototype.getNodeById = function(node_id) { - return this.tree.getNodeById(node_id); - }; - - JqTreeWidget.prototype.getNodeByName = function(name) { - return this.tree.getNodeByName(name); - }; - - JqTreeWidget.prototype.openNode = function(node, slide) { - if (slide == null) { - slide = true; - } - return this._openNode(node, slide); - }; - - JqTreeWidget.prototype._openNode = function(node, slide, on_finished) { - var doOpenNode, parent, - _this = this; - - if (slide == null) { - slide = true; - } - doOpenNode = function(_node, _slide, _on_finished) { - var folder_element; - - folder_element = new FolderElement(_node, _this); - return folder_element.open(_on_finished, _slide); - }; - if (node.isFolder()) { - if (node.load_on_demand) { - return this._loadFolderOnDemand(node, slide, on_finished); - } else { - parent = node.parent; - while (parent && !parent.is_open) { - if (parent.parent) { - doOpenNode(parent, false, null); - } - parent = parent.parent; - } - doOpenNode(node, slide, on_finished); - return this._saveState(); - } - } - }; - - JqTreeWidget.prototype._loadFolderOnDemand = function(node, slide, on_finished) { - var _this = this; - - if (slide == null) { - slide = true; - } - return this._loadDataFromUrl(null, node, function() { - return _this._openNode(node, slide, on_finished); - }); - }; - - JqTreeWidget.prototype.closeNode = function(node, slide) { - if (slide == null) { - slide = true; - } - if (node.isFolder()) { - new FolderElement(node, this).close(slide); - return this._saveState(); - } - }; - - JqTreeWidget.prototype.isDragging = function() { - return this.is_dragging; - }; - - JqTreeWidget.prototype.refreshHitAreas = function() { - return this.dnd_handler.refreshHitAreas(); - }; - - JqTreeWidget.prototype.addNodeAfter = function(new_node_info, existing_node) { - var new_node; - - new_node = existing_node.addAfter(new_node_info); - this._refreshElements(existing_node.parent); - return new_node; - }; - - JqTreeWidget.prototype.addNodeBefore = function(new_node_info, existing_node) { - var new_node; - - new_node = existing_node.addBefore(new_node_info); - this._refreshElements(existing_node.parent); - return new_node; - }; - - JqTreeWidget.prototype.addParentNode = function(new_node_info, existing_node) { - var new_node; - - new_node = existing_node.addParent(new_node_info); - this._refreshElements(new_node.parent); - return new_node; - }; - - JqTreeWidget.prototype.removeNode = function(node) { - var parent; - - parent = node.parent; - if (parent) { - this.select_node_handler.removeFromSelection(node, true); - node.remove(); - return this._refreshElements(parent.parent); - } - }; - - JqTreeWidget.prototype.appendNode = function(new_node_info, parent_node) { - var is_already_root_node, node; - - if (!parent_node) { - parent_node = this.tree; - } - is_already_root_node = parent_node.isFolder(); - node = parent_node.append(new_node_info); - if (is_already_root_node) { - this._refreshElements(parent_node); - } else { - this._refreshElements(parent_node.parent); - } - return node; - }; - - JqTreeWidget.prototype.prependNode = function(new_node_info, parent_node) { - var node; - - if (!parent_node) { - parent_node = this.tree; - } - node = parent_node.prepend(new_node_info); - this._refreshElements(parent_node); - return node; - }; - - JqTreeWidget.prototype.updateNode = function(node, data) { - node.setData(data); - this._refreshElements(node.parent); - return this._selectCurrentNode(); - }; - - JqTreeWidget.prototype.moveNode = function(node, target_node, position) { - var position_index; - - position_index = Position.nameToIndex(position); - this.tree.moveNode(node, target_node, position_index); - return this._refreshElements(); - }; - - JqTreeWidget.prototype.getStateFromStorage = function() { - return this.save_state_handler.getStateFromStorage(); - }; - - JqTreeWidget.prototype.addToSelection = function(node) { - this.select_node_handler.addToSelection(node); - return this._getNodeElementForNode(node).select(); - }; - - JqTreeWidget.prototype.getSelectedNodes = function() { - return this.select_node_handler.getSelectedNodes(); - }; - - JqTreeWidget.prototype.isNodeSelected = function(node) { - return this.select_node_handler.isNodeSelected(node); - }; - - JqTreeWidget.prototype.removeFromSelection = function(node) { - this.select_node_handler.removeFromSelection(node); - return this._getNodeElementForNode(node).deselect(); - }; - - JqTreeWidget.prototype.scrollToNode = function(node) { - var $element, top; - - $element = $(node.element); - top = $element.offset().top - this.$el.offset().top; - return this.scroll_handler.scrollTo(top); - }; - - JqTreeWidget.prototype._init = function() { - JqTreeWidget.__super__._init.call(this); - this.element = this.$el; - this.mouse_delay = 300; - this.save_state_handler = new SaveStateHandler(this); - this.select_node_handler = new SelectNodeHandler(this); - this.dnd_handler = new DragAndDropHandler(this); - this.scroll_handler = new ScrollHandler(this); - this._initData(); - this.element.click($.proxy(this._click, this)); - if (this.options.useContextMenu) { - return this.element.bind('contextmenu', $.proxy(this._contextmenu, this)); - } - }; - - JqTreeWidget.prototype._deinit = function() { - this.element.empty(); - this.element.unbind(); - this.tree = null; - return JqTreeWidget.__super__._deinit.call(this); - }; - - JqTreeWidget.prototype._initData = function() { - if (this.options.data) { - return this._loadData(this.options.data); - } else { - return this._loadDataFromUrl(this._getDataUrlInfo()); - } - }; - - JqTreeWidget.prototype._getDataUrlInfo = function(node) { - var data, data_url, url_info; - - data_url = this.options.dataUrl || this.element.data('url'); - if ($.isFunction(data_url)) { - return data_url(node); - } else if ($.type(data_url) === 'string') { - url_info = { - url: data_url - }; - if (node && node.id) { - data = { - node: node.id - }; - url_info['data'] = data; - } - return url_info; - } else { - return data_url; - } - }; - - JqTreeWidget.prototype._initTree = function(data) { - this.tree = new this.options.nodeClass(null, true, this.options.nodeClass); - this.select_node_handler.clear(); - this.tree.loadFromData(data); - this._openNodes(); - this._refreshElements(); - return this._triggerEvent('tree.init'); - }; - - JqTreeWidget.prototype._openNodes = function() { - var max_level; - - if (this.options.saveState) { - if (this.save_state_handler.restoreState()) { - return; - } - } - if (this.options.autoOpen === false) { - return; - } else if (this.options.autoOpen === true) { - max_level = -1; - } else { - max_level = parseInt(this.options.autoOpen); - } - return this.tree.iterate(function(node, level) { - if (node.hasChildren()) { - node.is_open = true; - } - return level !== max_level; - }); - }; - - JqTreeWidget.prototype._refreshElements = function(from_node) { - var $element, createFolderLi, createLi, createNodeLi, createUl, doCreateDomElements, escapeIfNecessary, is_root_node, node_element, - _this = this; - - if (from_node == null) { - from_node = null; - } - escapeIfNecessary = function(value) { - if (_this.options.autoEscape) { - return html_escape(value); - } else { - return value; - } - }; - createUl = function(is_root_node) { - var class_string; - - if (is_root_node) { - class_string = 'jqtree-tree'; - } else { - class_string = ''; - } - return $("
    "); - }; - createLi = function(node) { - var $li; - - if (node.isFolder()) { - $li = createFolderLi(node); - } else { - $li = createNodeLi(node); - } - if (_this.options.onCreateLi) { - _this.options.onCreateLi(node, $li); - } - return $li; - }; - createNodeLi = function(node) { - var class_string, escaped_name, li_classes; - - li_classes = ['jqtree_common']; - if (_this.select_node_handler.isNodeSelected(node)) { - li_classes.push('jqtree-selected'); - } - class_string = li_classes.join(' '); - escaped_name = escapeIfNecessary(node.name); - return $("
  • " + escaped_name + "
  • "); - }; - createFolderLi = function(node) { - var button_char, button_classes, escaped_name, folder_classes, getButtonClasses, getFolderClasses; - - getButtonClasses = function() { - var classes; - - classes = ['jqtree-toggler']; - if (!node.is_open) { - classes.push('jqtree-closed'); - } - return classes.join(' '); - }; - getFolderClasses = function() { - var classes; - - classes = ['jqtree-folder']; - if (!node.is_open) { - classes.push('jqtree-closed'); - } - if (_this.select_node_handler.isNodeSelected(node)) { - classes.push('jqtree-selected'); - } - return classes.join(' '); - }; - button_classes = getButtonClasses(); - folder_classes = getFolderClasses(); - escaped_name = escapeIfNecessary(node.name); - if (node.is_open) { - button_char = _this.options.openedIcon; - } else { - button_char = _this.options.closedIcon; - } - return $("
  • " + button_char + "" + escaped_name + "
  • "); - }; - doCreateDomElements = function($element, children, is_root_node, is_open) { - var $li, $ul, child, _i, _len; - - $ul = createUl(is_root_node); - $element.append($ul); - for (_i = 0, _len = children.length; _i < _len; _i++) { - child = children[_i]; - $li = createLi(child); - $ul.append($li); - child.element = $li[0]; - $li.data('node', child); - if (child.hasChildren()) { - doCreateDomElements($li, child.children, false, child.is_open); - } - } - return null; - }; - if (from_node && from_node.parent) { - is_root_node = false; - node_element = this._getNodeElementForNode(from_node); - node_element.getUl().remove(); - $element = node_element.$element; - } else { - from_node = this.tree; - $element = this.element; - $element.empty(); - is_root_node = true; - } - doCreateDomElements($element, from_node.children, is_root_node, is_root_node); - return this._triggerEvent('tree.refresh'); - }; - - JqTreeWidget.prototype._click = function(e) { - var $button, $el, $target, event, node; - - if (e.ctrlKey) { - return; - } - $target = $(e.target); - $button = $target.closest('.jqtree-toggler'); - if ($button.length) { - node = this._getNode($button); - if (node) { - this.toggle(node, this.options.slide); - e.preventDefault(); - return e.stopPropagation(); - } - } else { - $el = $target.closest('.jqtree-element'); - if ($el.length) { - node = this._getNode($el); - if (node) { - event = this._triggerEvent('tree.click', { - node: node - }); - if (!event.isDefaultPrevented()) { - return this._selectNode(node, true); - } - } - } - } - }; - - JqTreeWidget.prototype._getNode = function($element) { - var $li; - - $li = $element.closest('li'); - if ($li.length === 0) { - return null; - } else { - return $li.data('node'); - } - }; - - JqTreeWidget.prototype._getNodeElementForNode = function(node) { - if (node.isFolder()) { - return new FolderElement(node, this); - } else { - return new NodeElement(node, this); - } - }; - - JqTreeWidget.prototype._getNodeElement = function($element) { - var node; - - node = this._getNode($element); - if (node) { - return this._getNodeElementForNode(node); - } else { - return null; - } - }; - - JqTreeWidget.prototype._contextmenu = function(e) { - var $div, node; - - $div = $(e.target).closest('ul.jqtree-tree .jqtree-element'); - if ($div.length) { - node = this._getNode($div); - if (node) { - e.preventDefault(); - e.stopPropagation(); - this._triggerEvent('tree.contextmenu', { - node: node, - click_event: e - }); - return false; - } - } - }; - - JqTreeWidget.prototype._saveState = function() { - if (this.options.saveState) { - return this.save_state_handler.saveState(); - } - }; - - JqTreeWidget.prototype._mouseCapture = function(event) { - if (this.options.dragAndDrop) { - return this.dnd_handler.mouseCapture(event); - } else { - return false; - } - }; - - JqTreeWidget.prototype._mouseStart = function(event) { - if (this.options.dragAndDrop) { - return this.dnd_handler.mouseStart(event); - } else { - return false; - } - }; - - JqTreeWidget.prototype._mouseDrag = function(event) { - var result; - - if (this.options.dragAndDrop) { - result = this.dnd_handler.mouseDrag(event); - this.scroll_handler.checkScrolling(); - return result; - } else { - return false; - } - }; - - JqTreeWidget.prototype._mouseStop = function(e) { - if (this.options.dragAndDrop) { - return this.dnd_handler.mouseStop(e); - } else { - return false; - } - }; - - JqTreeWidget.prototype._triggerEvent = function(event_name, values) { - var event; - - event = $.Event(event_name); - $.extend(event, values); - this.element.trigger(event); - return event; - }; - - JqTreeWidget.prototype.testGenerateHitAreas = function(moving_node) { - this.dnd_handler.current_item = this._getNodeElementForNode(moving_node); - this.dnd_handler.generateHitAreas(); - return this.dnd_handler.hit_areas; - }; - - JqTreeWidget.prototype._selectCurrentNode = function() { - var node, node_element; - - node = this.getSelectedNode(); - if (node) { - node_element = this._getNodeElementForNode(node); - if (node_element) { - return node_element.select(); - } - } - }; - - JqTreeWidget.prototype._deselectCurrentNode = function() { - var node; - - node = this.getSelectedNode(); - if (node) { - return this.removeFromSelection(node); - } - }; - - return JqTreeWidget; - - })(MouseWidget); - - SimpleWidget.register(JqTreeWidget, 'tree'); - - GhostDropHint = (function() { - function GhostDropHint(node, $element, position) { - this.$element = $element; - this.node = node; - this.$ghost = $('
  • '); - if (position === Position.AFTER) { - this.moveAfter(); - } else if (position === Position.BEFORE) { - this.moveBefore(); - } else if (position === Position.INSIDE) { - if (node.isFolder() && node.is_open) { - this.moveInsideOpenFolder(); - } else { - this.moveInside(); - } - } - } - - GhostDropHint.prototype.remove = function() { - return this.$ghost.remove(); - }; - - GhostDropHint.prototype.moveAfter = function() { - return this.$element.after(this.$ghost); - }; - - GhostDropHint.prototype.moveBefore = function() { - return this.$element.before(this.$ghost); - }; - - GhostDropHint.prototype.moveInsideOpenFolder = function() { - return $(this.node.children[0].element).before(this.$ghost); - }; - - GhostDropHint.prototype.moveInside = function() { - this.$element.after(this.$ghost); - return this.$ghost.addClass('jqtree-inside'); - }; - - return GhostDropHint; - - })(); - - BorderDropHint = (function() { - function BorderDropHint($element) { - var $div, width; - - $div = $element.children('.jqtree-element'); - width = $element.width() - 4; - this.$hint = $(''); - $div.append(this.$hint); - this.$hint.css({ - width: width, - height: $div.height() - 4 - }); - } - - BorderDropHint.prototype.remove = function() { - return this.$hint.remove(); - }; - - return BorderDropHint; - - })(); - - NodeElement = (function() { - function NodeElement(node, tree_widget) { - this.init(node, tree_widget); - } - - NodeElement.prototype.init = function(node, tree_widget) { - this.node = node; - this.tree_widget = tree_widget; - return this.$element = $(node.element); - }; - - NodeElement.prototype.getUl = function() { - return this.$element.children('ul:first'); - }; - - NodeElement.prototype.getSpan = function() { - return this.$element.children('.jqtree-element').find('span.jqtree-title'); - }; - - NodeElement.prototype.getLi = function() { - return this.$element; - }; - - NodeElement.prototype.addDropHint = function(position) { - if (position === Position.INSIDE) { - return new BorderDropHint(this.$element); - } else { - return new GhostDropHint(this.node, this.$element, position); - } - }; - - NodeElement.prototype.select = function() { - return this.getLi().addClass('jqtree-selected'); - }; - - NodeElement.prototype.deselect = function() { - return this.getLi().removeClass('jqtree-selected'); - }; - - return NodeElement; - - })(); - - FolderElement = (function(_super) { - __extends(FolderElement, _super); - - function FolderElement() { - _ref2 = FolderElement.__super__.constructor.apply(this, arguments); - return _ref2; - } - - FolderElement.prototype.open = function(on_finished, slide) { - var $button, doOpen, - _this = this; - - if (slide == null) { - slide = true; - } - if (!this.node.is_open) { - this.node.is_open = true; - $button = this.getButton(); - $button.removeClass('jqtree-closed'); - $button.html(this.tree_widget.options.openedIcon); - doOpen = function() { - _this.getLi().removeClass('jqtree-closed'); - if (on_finished) { - on_finished(); - } - return _this.tree_widget._triggerEvent('tree.open', { - node: _this.node - }); - }; - if (slide) { - return this.getUl().slideDown('fast', doOpen); - } else { - this.getUl().show(); - return doOpen(); - } - } - }; - - FolderElement.prototype.close = function(slide) { - var $button, doClose, - _this = this; - - if (slide == null) { - slide = true; - } - if (this.node.is_open) { - this.node.is_open = false; - $button = this.getButton(); - $button.addClass('jqtree-closed'); - $button.html(this.tree_widget.options.closedIcon); - doClose = function() { - _this.getLi().addClass('jqtree-closed'); - return _this.tree_widget._triggerEvent('tree.close', { - node: _this.node - }); - }; - if (slide) { - return this.getUl().slideUp('fast', doClose); - } else { - this.getUl().hide(); - return doClose(); - } - } - }; - - FolderElement.prototype.getButton = function() { - return this.$element.children('.jqtree-element').find('a.jqtree-toggler'); - }; - - FolderElement.prototype.addDropHint = function(position) { - if (!this.node.is_open && position === Position.INSIDE) { - return new BorderDropHint(this.$element); - } else { - return new GhostDropHint(this.node, this.$element, position); - } - }; - - return FolderElement; - - })(NodeElement); - - DragElement = (function() { - function DragElement(node, offset_x, offset_y, $tree) { - this.offset_x = offset_x; - this.offset_y = offset_y; - this.$element = $("" + node.name + ""); - this.$element.css("position", "absolute"); - $tree.append(this.$element); - } - - DragElement.prototype.move = function(page_x, page_y) { - return this.$element.offset({ - left: page_x - this.offset_x, - top: page_y - this.offset_y - }); - }; - - DragElement.prototype.remove = function() { - return this.$element.remove(); - }; - - return DragElement; - - })(); - - SaveStateHandler = (function() { - function SaveStateHandler(tree_widget) { - this.tree_widget = tree_widget; - } - - SaveStateHandler.prototype.saveState = function() { - if (this.tree_widget.options.onSetStateFromStorage) { - return this.tree_widget.options.onSetStateFromStorage(this.getState()); - } else if (typeof localStorage !== "undefined" && localStorage !== null) { - return localStorage.setItem(this.getCookieName(), this.getState()); - } else if ($.cookie) { - $.cookie.raw = true; - return $.cookie(this.getCookieName(), this.getState(), { - path: '/' - }); - } - }; - - SaveStateHandler.prototype.restoreState = function() { - var state; - - state = this.getStateFromStorage(); - if (state) { - this.setState(state); - return true; - } else { - return false; - } - }; - - SaveStateHandler.prototype.getStateFromStorage = function() { - if (this.tree_widget.options.onGetStateFromStorage) { - return this.tree_widget.options.onGetStateFromStorage(); - } else if (typeof localStorage !== "undefined" && localStorage !== null) { - return localStorage.getItem(this.getCookieName()); - } else if ($.cookie) { - $.cookie.raw = true; - return $.cookie(this.getCookieName()); - } else { - return null; - } - }; - - SaveStateHandler.prototype.getState = function() { - var open_nodes, selected_node, selected_node_id, - _this = this; - - open_nodes = []; - this.tree_widget.tree.iterate(function(node) { - if (node.is_open && node.id && node.hasChildren()) { - open_nodes.push(node.id); - } - return true; - }); - selected_node = this.tree_widget.getSelectedNode(); - if (selected_node) { - selected_node_id = selected_node.id; - } else { - selected_node_id = ''; - } - return JSON.stringify({ - open_nodes: open_nodes, - selected_node: selected_node_id - }); - }; - - SaveStateHandler.prototype.setState = function(state) { - var data, open_nodes, selected_node, selected_node_id, - _this = this; - - data = $.parseJSON(state); - if (data) { - open_nodes = data.open_nodes; - selected_node_id = data.selected_node; - this.tree_widget.tree.iterate(function(node) { - if (node.id && node.hasChildren() && (indexOf(open_nodes, node.id) >= 0)) { - node.is_open = true; - } - return true; - }); - if (selected_node_id) { - selected_node = this.tree_widget.getNodeById(selected_node_id); - if (selected_node) { - return this.tree_widget.select_node_handler.addToSelection(selected_node); - } - } - } - }; - - SaveStateHandler.prototype.getCookieName = function() { - if (typeof this.tree_widget.options.saveState === 'string') { - return this.tree_widget.options.saveState; - } else { - return 'tree'; - } - }; - - return SaveStateHandler; - - })(); - - SelectNodeHandler = (function() { - function SelectNodeHandler(tree_widget) { - this.tree_widget = tree_widget; - this.clear(); - } - - SelectNodeHandler.prototype.getSelectedNode = function() { - var selected_nodes; - - selected_nodes = this.getSelectedNodes(); - if (selected_nodes.length) { - return selected_nodes[0]; - } else { - return false; - } - }; - - SelectNodeHandler.prototype.getSelectedNodes = function() { - var id, node, selected_nodes; - - if (this.selected_single_node) { - return [this.selected_single_node]; - } else { - selected_nodes = []; - for (id in this.selected_nodes) { - node = this.tree_widget.getNodeById(id); - if (node) { - selected_nodes.push(node); - } - } - return selected_nodes; - } - }; - - SelectNodeHandler.prototype.isNodeSelected = function(node) { - if (node.id) { - return this.selected_nodes[node.id]; - } else if (this.selected_single_node) { - return this.selected_single_node.element === node.element; - } else { - return false; - } - }; - - SelectNodeHandler.prototype.clear = function() { - this.selected_nodes = {}; - return this.selected_single_node = null; - }; - - SelectNodeHandler.prototype.removeFromSelection = function(node, include_children) { - var _this = this; - - if (include_children == null) { - include_children = false; - } - if (!node.id) { - if (node.element === this.selected_single_node) { - return this.selected_single_node = null; - } - } else { - delete this.selected_nodes[node.id]; - if (include_children) { - return node.iterate(function(n) { - delete _this.selected_nodes[node.id]; - return true; - }); - } - } - }; - - SelectNodeHandler.prototype.addToSelection = function(node) { - if (node.id) { - return this.selected_nodes[node.id] = true; - } else { - return this.selected_single_node = node; - } - }; - - return SelectNodeHandler; - - })(); - - DragAndDropHandler = (function() { - function DragAndDropHandler(tree_widget) { - this.tree_widget = tree_widget; - this.hovered_area = null; - this.$ghost = null; - this.hit_areas = []; - this.is_dragging = false; - } - - DragAndDropHandler.prototype.mouseCapture = function(event) { - var $element, node_element; - - $element = $(event.target); - if (this.tree_widget.options.onIsMoveHandle && !this.tree_widget.options.onIsMoveHandle($element)) { - return null; - } - node_element = this.tree_widget._getNodeElement($element); - if (node_element && this.tree_widget.options.onCanMove) { - if (!this.tree_widget.options.onCanMove(node_element.node)) { - node_element = null; - } - } - this.current_item = node_element; - return this.current_item !== null; - }; - - DragAndDropHandler.prototype.mouseStart = function(event) { - var offsetX, offsetY, _ref3; - - this.refreshHitAreas(); - _ref3 = this.getOffsetFromEvent(event), offsetX = _ref3[0], offsetY = _ref3[1]; - this.drag_element = new DragElement(this.current_item.node, offsetX, offsetY, this.tree_widget.element); - this.is_dragging = true; - this.current_item.$element.addClass('jqtree-moving'); - return true; - }; - - DragAndDropHandler.prototype.mouseDrag = function(event) { - var area, can_move_to; - - this.drag_element.move(event.pageX, event.pageY); - area = this.findHoveredArea(event.pageX, event.pageY); - can_move_to = this.canMoveToArea(area); - if (area) { - if (this.hovered_area !== area) { - this.hovered_area = area; - if (this.mustOpenFolderTimer(area)) { - this.startOpenFolderTimer(area.node); - } - if (can_move_to) { - this.updateDropHint(); - } - } - } else { - this.removeHover(); - this.removeDropHint(); - this.stopOpenFolderTimer(); - } - return true; - }; - - DragAndDropHandler.prototype.canMoveToArea = function(area) { - var position_name; - - if (!area) { - return false; - } else if (this.tree_widget.options.onCanMoveTo) { - position_name = Position.getName(area.position); - return this.tree_widget.options.onCanMoveTo(this.current_item.node, area.node, position_name); - } else { - return true; - } - }; - - DragAndDropHandler.prototype.mouseStop = function(e) { - this.moveItem(e); - this.clear(); - this.removeHover(); - this.removeDropHint(); - this.removeHitAreas(); - this.current_item.$element.removeClass('jqtree-moving'); - this.is_dragging = false; - return false; - }; - - DragAndDropHandler.prototype.getOffsetFromEvent = function(event) { - var element_offset; - - element_offset = $(event.target).offset(); - return [event.pageX - element_offset.left, event.pageY - element_offset.top]; - }; - - DragAndDropHandler.prototype.refreshHitAreas = function() { - this.removeHitAreas(); - return this.generateHitAreas(); - }; - - DragAndDropHandler.prototype.removeHitAreas = function() { - return this.hit_areas = []; - }; - - DragAndDropHandler.prototype.clear = function() { - this.drag_element.remove(); - return this.drag_element = null; - }; - - DragAndDropHandler.prototype.removeDropHint = function() { - if (this.previous_ghost) { - return this.previous_ghost.remove(); - } - }; - - DragAndDropHandler.prototype.removeHover = function() { - return this.hovered_area = null; - }; - - DragAndDropHandler.prototype.generateHitAreas = function() { - var addPosition, getTop, groupPositions, handleAfterOpenFolder, handleClosedFolder, handleFirstNode, handleNode, handleOpenFolder, hit_areas, last_top, positions, - _this = this; - - positions = []; - last_top = 0; - getTop = function($element) { - return $element.offset().top; - }; - addPosition = function(node, position, top) { - positions.push({ - top: top, - node: node, - position: position - }); - return last_top = top; - }; - groupPositions = function(handle_group) { - var group, position, previous_top, _i, _len; - - previous_top = -1; - group = []; - for (_i = 0, _len = positions.length; _i < _len; _i++) { - position = positions[_i]; - if (position.top !== previous_top) { - if (group.length) { - handle_group(group, previous_top, position.top); - } - previous_top = position.top; - group = []; - } - group.push(position); - } - return handle_group(group, previous_top, _this.tree_widget.element.offset().top + _this.tree_widget.element.height()); - }; - handleNode = function(node, next_node, $element) { - var top; - - top = getTop($element); - if (node === _this.current_item.node) { - addPosition(node, Position.NONE, top); - } else { - addPosition(node, Position.INSIDE, top); - } - if (next_node === _this.current_item.node || node === _this.current_item.node) { - return addPosition(node, Position.NONE, top); - } else { - return addPosition(node, Position.AFTER, top); - } - }; - handleOpenFolder = function(node, $element) { - if (node === _this.current_item.node) { - return false; - } - if (node.children[0] !== _this.current_item.node) { - addPosition(node, Position.INSIDE, getTop($element)); - } - return true; - }; - handleAfterOpenFolder = function(node, next_node, $element) { - if (node === _this.current_item.node || next_node === _this.current_item.node) { - return addPosition(node, Position.NONE, last_top); - } else { - return addPosition(node, Position.AFTER, last_top); - } - }; - handleClosedFolder = function(node, next_node, $element) { - var top; - - top = getTop($element); - if (node === _this.current_item.node) { - return addPosition(node, Position.NONE, top); - } else { - addPosition(node, Position.INSIDE, top); - if (next_node !== _this.current_item.node) { - return addPosition(node, Position.AFTER, top); - } - } - }; - handleFirstNode = function(node, $element) { - if (node !== _this.current_item.node) { - return addPosition(node, Position.BEFORE, getTop($(node.element))); - } - }; - this.iterateVisibleNodes(handleNode, handleOpenFolder, handleClosedFolder, handleAfterOpenFolder, handleFirstNode); - hit_areas = []; - groupPositions(function(positions_in_group, top, bottom) { - var area_height, area_top, position, _i, _len; - - area_height = (bottom - top) / positions_in_group.length; - area_top = top; - for (_i = 0, _len = positions_in_group.length; _i < _len; _i++) { - position = positions_in_group[_i]; - hit_areas.push({ - top: area_top, - bottom: area_top + area_height, - node: position.node, - position: position.position - }); - area_top += area_height; - } - return null; - }); - return this.hit_areas = hit_areas; - }; - - DragAndDropHandler.prototype.iterateVisibleNodes = function(handle_node, handle_open_folder, handle_closed_folder, handle_after_open_folder, handle_first_node) { - var is_first_node, iterate, - _this = this; - - is_first_node = true; - iterate = function(node, next_node) { - var $element, child, children_length, i, must_iterate_inside, _i, _len, _ref3; - - must_iterate_inside = (node.is_open || !node.element) && node.hasChildren(); - if (node.element) { - $element = $(node.element); - if (!$element.is(':visible')) { - return; - } - if (is_first_node) { - handle_first_node(node, $element); - is_first_node = false; - } - if (!node.hasChildren()) { - handle_node(node, next_node, $element); - } else if (node.is_open) { - if (!handle_open_folder(node, $element)) { - must_iterate_inside = false; - } - } else { - handle_closed_folder(node, next_node, $element); - } - } - if (must_iterate_inside) { - children_length = node.children.length; - _ref3 = node.children; - for (i = _i = 0, _len = _ref3.length; _i < _len; i = ++_i) { - child = _ref3[i]; - if (i === (children_length - 1)) { - iterate(node.children[i], null); - } else { - iterate(node.children[i], node.children[i + 1]); - } - } - if (node.is_open) { - return handle_after_open_folder(node, next_node, $element); - } - } - }; - return iterate(this.tree_widget.tree); - }; - - DragAndDropHandler.prototype.findHoveredArea = function(x, y) { - var area, high, low, mid, tree_offset; - - tree_offset = this.tree_widget.element.offset(); - if (x < tree_offset.left || y < tree_offset.top || x > (tree_offset.left + this.tree_widget.element.width()) || y > (tree_offset.top + this.tree_widget.element.height())) { - return null; - } - low = 0; - high = this.hit_areas.length; - while (low < high) { - mid = (low + high) >> 1; - area = this.hit_areas[mid]; - if (y < area.top) { - high = mid; - } else if (y > area.bottom) { - low = mid + 1; - } else { - return area; - } - } - return null; - }; - - DragAndDropHandler.prototype.mustOpenFolderTimer = function(area) { - var node; - - node = area.node; - return node.isFolder() && !node.is_open && area.position === Position.INSIDE; - }; - - DragAndDropHandler.prototype.updateDropHint = function() { - var node_element; - - if (!this.hovered_area) { - return; - } - this.removeDropHint(); - node_element = this.tree_widget._getNodeElementForNode(this.hovered_area.node); - return this.previous_ghost = node_element.addDropHint(this.hovered_area.position); - }; - - DragAndDropHandler.prototype.startOpenFolderTimer = function(folder) { - var openFolder, - _this = this; - - openFolder = function() { - return _this.tree_widget._openNode(folder, _this.tree_widget.options.slide, function() { - _this.refreshHitAreas(); - return _this.updateDropHint(); - }); - }; - return this.open_folder_timer = setTimeout(openFolder, 500); - }; - - DragAndDropHandler.prototype.stopOpenFolderTimer = function() { - if (this.open_folder_timer) { - clearTimeout(this.open_folder_timer); - return this.open_folder_timer = null; - } - }; - - DragAndDropHandler.prototype.moveItem = function(original_event) { - var doMove, event, moved_node, position, previous_parent, target_node, - _this = this; - - if (this.hovered_area && this.hovered_area.position !== Position.NONE && this.canMoveToArea(this.hovered_area)) { - moved_node = this.current_item.node; - target_node = this.hovered_area.node; - position = this.hovered_area.position; - previous_parent = moved_node.parent; - if (position === Position.INSIDE) { - this.hovered_area.node.is_open = true; - } - doMove = function() { - _this.tree_widget.tree.moveNode(moved_node, target_node, position); - _this.tree_widget.element.empty(); - return _this.tree_widget._refreshElements(); - }; - event = this.tree_widget._triggerEvent('tree.move', { - move_info: { - moved_node: moved_node, - target_node: target_node, - position: Position.getName(position), - previous_parent: previous_parent, - do_move: doMove, - original_event: original_event - } - }); - if (!event.isDefaultPrevented()) { - return doMove(); - } - } - }; - - return DragAndDropHandler; - - })(); - - ScrollHandler = (function() { - function ScrollHandler(tree_widget) { - this.tree_widget = tree_widget; - this.previous_top = -1; - this._initScrollParent(); - } - - ScrollHandler.prototype._initScrollParent = function() { - var $scroll_parent, getParentWithOverflow, setDocumentAsScrollParent, - _this = this; - - getParentWithOverflow = function() { - var css_value, css_values, parent, scroll_parent, _i, _j, _len, _len1, _ref3, _ref4; - - css_values = ['overflow', 'overflow-y']; - scroll_parent = null; - _ref3 = _this.tree_widget.$el.parents(); - for (_i = 0, _len = _ref3.length; _i < _len; _i++) { - parent = _ref3[_i]; - for (_j = 0, _len1 = css_values.length; _j < _len1; _j++) { - css_value = css_values[_j]; - if ((_ref4 = $.css(parent, css_value)) === 'auto' || _ref4 === 'scroll') { - return $(parent); - } - } - } - return null; - }; - setDocumentAsScrollParent = function() { - _this.scroll_parent_top = 0; - return _this.$scroll_parent = null; - }; - if (this.tree_widget.$el.css('position') === 'fixed') { - setDocumentAsScrollParent(); - } - $scroll_parent = getParentWithOverflow(); - if ($scroll_parent && $scroll_parent.length && $scroll_parent[0].tagName !== 'HTML') { - this.$scroll_parent = $scroll_parent; - return this.scroll_parent_top = this.$scroll_parent.offset().top; - } else { - return setDocumentAsScrollParent(); - } - }; - - ScrollHandler.prototype.checkScrolling = function() { - var hovered_area; - - hovered_area = this.tree_widget.dnd_handler.hovered_area; - if (hovered_area && hovered_area.top !== this.previous_top) { - this.previous_top = hovered_area.top; - if (this.$scroll_parent) { - return this._handleScrollingWithScrollParent(hovered_area); - } else { - return this._handleScrollingWithDocument(hovered_area); - } - } - }; - - ScrollHandler.prototype._handleScrollingWithScrollParent = function(area) { - var distance_bottom; - - distance_bottom = this.scroll_parent_top + this.$scroll_parent[0].offsetHeight - area.bottom; - if (distance_bottom < 20) { - this.$scroll_parent[0].scrollTop += 20; - this.tree_widget.refreshHitAreas(); - return this.previous_top = -1; - } else if ((area.top - this.scroll_parent_top) < 20) { - this.$scroll_parent[0].scrollTop -= 20; - this.tree_widget.refreshHitAreas(); - return this.previous_top = -1; - } - }; - - ScrollHandler.prototype._handleScrollingWithDocument = function(area) { - var distance_top; - - distance_top = area.top - $(document).scrollTop(); - if (distance_top < 20) { - return $(document).scrollTop($(document).scrollTop() - 20); - } else if ($(window).height() - (area.bottom - $(document).scrollTop()) < 20) { - return $(document).scrollTop($(document).scrollTop() + 20); - } - }; - - ScrollHandler.prototype.scrollTo = function(top) { - var tree_top; - - if (this.$scroll_parent) { - return this.$scroll_parent[0].scrollTop = top; - } else { - tree_top = this.tree_widget.$el.offset().top; - return $(document).scrollTop(top + tree_top); - } - }; - - return ScrollHandler; - - })(); - -}).call(this); +/*! + * JqTree 1.4.9 + * + * Copyright 2018 Marco Braak + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */!function(e){var t={};function o(n){if(t[n])return t[n].exports;var r=t[n]={i:n,l:!1,exports:{}};return e[n].call(r.exports,r,r.exports,o),r.l=!0,r.exports}o.m=e,o.c=t,o.d=function(e,t,n){o.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},o.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.t=function(e,t){if(1&t&&(e=o(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)o.d(n,r,function(t){return e[t]}.bind(null,r));return n},o.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(t,"a",t),t},o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o.p="",o(o.s=16)}([function(e,t,o){"use strict";var n;t.__esModule=!0,function(e){e[e.Before=1]="Before",e[e.After=2]="After",e[e.Inside=3]="Inside",e[e.None=4]="None"}(n=t.Position||(t.Position={}));var r={before:n.Before,after:n.After,inside:n.Inside,none:n.None};t.getPositionName=function(e){for(var t in r)if(r.hasOwnProperty(t)&&r[t]===e)return t;return""},t.getPosition=function(e){return r[e]};var i=function(){function e(t,o,n){void 0===o&&(o=!1),void 0===n&&(n=e),this.name="",this.setData(t),this.children=[],this.parent=null,o&&(this.id_mapping={},this.tree=this,this.node_class=n)}return e.prototype.setData=function(e){var t=this,o=function(e){null!=e&&(t.name=e)};if(e)if("object"!=typeof e)o(e);else for(var n in e)if(e.hasOwnProperty(n)){var r=e[n];"label"===n?o(r):"children"!==n&&(this[n]=r)}},e.prototype.loadFromData=function(e){this.removeChildren();for(var t=0,o=e;t=0?this.parent.children[e]:null}return null},e.prototype.getNextSibling=function(){if(this.parent){var e=this.parent.getChildIndex(this)+1;return e/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")},t.getBoolString=function(e){return e?"true":"false"}},function(e,t){e.exports=jQuery},function(e,t,o){"use strict";t.__esModule=!0;var n=function(){function e(e,t){this.$el=jQuery(e);var o=this.constructor.defaults;this.options=jQuery.extend({},o,t)}return e.register=function(t,o){var n=function(){return"simple_widget_"+o};function r(t,o){var n=jQuery.data(t,o);return n&&n instanceof e?n:null}jQuery.fn[o]=function(o){for(var i=[],s=1;so.right||t>o.bottom)return null;for(var n=0,r=this.hit_areas.length;n>1,s=this.hit_areas[i];if(ts.bottom))return s;n=i+1}}return null},e.prototype.mustOpenFolderTimer=function(e){var t=e.node;return t.isFolder()&&!t.is_open&&e.position===s.Position.Inside},e.prototype.updateDropHint=function(){if(this.hovered_area){this.removeDropHint();var e=this.tree_widget._getNodeElementForNode(this.hovered_area.node);this.previous_ghost=e.addDropHint(this.hovered_area.position)}},e.prototype.startOpenFolderTimer=function(e){var t=this;this.stopOpenFolderTimer(),this.open_folder_timer=setTimeout(function(){t.tree_widget._openNode(e,t.tree_widget.options.slide,function(){t.refresh(),t.updateDropHint()})},this.tree_widget.options.openFolderDelay)},e.prototype.stopOpenFolderTimer=function(){this.open_folder_timer&&(clearTimeout(this.open_folder_timer),this.open_folder_timer=null)},e.prototype.moveItem=function(e){var t=this;if(this.current_item&&this.hovered_area&&this.hovered_area.position!==s.Position.None&&this.canMoveToArea(this.hovered_area)){var o=this.current_item.node,n=this.hovered_area.node,r=this.hovered_area.position,i=o.parent;r===s.Position.Inside&&(this.hovered_area.node.is_open=!0);var a=function(){t.tree_widget.tree.moveNode(o,n,r),t.tree_widget.element.empty(),t.tree_widget._refreshElements(null)};this.tree_widget._triggerEvent("tree.move",{move_info:{moved_node:o,target_node:n,position:s.getPositionName(r),previous_parent:i,do_move:a,original_event:e.original_event}}).isDefaultPrevented()||a()}},e.prototype.getTreeDimensions=function(){var e=this.tree_widget.element.offset();if(e){var t=this.tree_widget.element,o=t.width()||0,n=t.height()||0,r=e.left+this.tree_widget._getScrollLeft();return{left:r,top:e.top,right:r+o,bottom:e.top+n+16}}return{left:0,top:0,right:0,bottom:0}},e}();t.DragAndDropHandler=l;var d=function(e){function t(t,o,n){var r=e.call(this,t)||this;return r.current_node=o,r.tree_bottom=n,r}return r(t,e),t.prototype.generate=function(){return this.positions=[],this.last_top=0,this.iterate(),this.generateHitAreas(this.positions)},t.prototype.generateHitAreas=function(e){for(var t=-1,o=[],n=[],r=0,i=e;r'+e+""),this.$element.css("position","absolute"),n.append(this.$element)}return e.prototype.move=function(e,t){this.$element.offset({left:e-this.offset_x,top:t-this.offset_y})},e.prototype.remove=function(){this.$element.remove()},e}()},function(e,t,o){"use strict";t.__esModule=!0;var n=o(1),r=function(){function e(e){this.tree_widget=e,this.opened_icon_element=this.createButtonElement(e.options.openedIcon),this.closed_icon_element=this.createButtonElement(e.options.closedIcon)}return e.prototype.render=function(e){e&&e.parent?this.renderFromNode(e):this.renderFromRoot()},e.prototype.renderFromRoot=function(){var e=this.tree_widget.element;e.empty(),this.createDomElements(e[0],this.tree_widget.tree.children,!0,1)},e.prototype.renderFromNode=function(e){var t=jQuery(e.element),o=this.createLi(e,e.getLevel());this.attachNodeData(e,o),t.after(o),t.remove(),e.children&&this.createDomElements(o,e.children,!1,e.getLevel()+1)},e.prototype.createDomElements=function(e,t,o,n){var r=this.createUl(o);e.appendChild(r);for(var i=0,s=t;i1)){var n=o.changedTouches[0];return t._handleMouseDown(t._getPositionInfo(n))}},t.touchMove=function(e){var o=e.originalEvent;if(!(o.touches.length>1)){var n=o.changedTouches[0];return t._handleMouseMove(e,t._getPositionInfo(n))}},t.touchEnd=function(e){var o=e.originalEvent;if(!(o.touches.length>1)){var n=o.changedTouches[0];return t._handleMouseUp(t._getPositionInfo(n))}},t}return r(t,e),t.prototype.setMouseDelay=function(e){this.mouse_delay=e},t.prototype._init=function(){this.$el.on("mousedown.mousewidget",this.mouseDown),this.$el.on("touchstart.mousewidget",this.touchStart),this.is_mouse_started=!1,this.mouse_delay=0,this._mouse_delay_timer=null,this._is_mouse_delay_met=!0,this.mouse_down_info=null},t.prototype._deinit=function(){this.$el.off("mousedown.mousewidget"),this.$el.off("touchstart.mousewidget");var e=jQuery(document);e.off("mousemove.mousewidget"),e.off("mouseup.mousewidget")},t.prototype._handleMouseDown=function(e){if(this.is_mouse_started&&this._handleMouseUp(e),this.mouse_down_info=e,this._mouseCapture(e))return this._handleStartMouse(),!0},t.prototype._handleStartMouse=function(){var e=jQuery(document);e.on("mousemove.mousewidget",this.mouseMove),e.on("touchmove.mousewidget",this.touchMove),e.on("mouseup.mousewidget",this.mouseUp),e.on("touchend.mousewidget",this.touchEnd),this.mouse_delay&&this._startMouseDelayTimer()},t.prototype._startMouseDelayTimer=function(){var e=this;this._mouse_delay_timer&&clearTimeout(this._mouse_delay_timer),this._mouse_delay_timer=setTimeout(function(){e._is_mouse_delay_met=!0},this.mouse_delay),this._is_mouse_delay_met=!1},t.prototype._handleMouseMove=function(e,t){return this.is_mouse_started?(this._mouseDrag(t),e.preventDefault()):!(!this.mouse_delay||this._is_mouse_delay_met)||(this.mouse_down_info&&(this.is_mouse_started=!1!==this._mouseStart(this.mouse_down_info)),this.is_mouse_started?this._mouseDrag(t):this._handleMouseUp(t),!this.is_mouse_started)},t.prototype._getPositionInfo=function(e){return{page_x:e.pageX,page_y:e.pageY,target:e.target,original_event:e}},t.prototype._handleMouseUp=function(e){var t=jQuery(document);t.off("mousemove.mousewidget"),t.off("touchmove.mousewidget"),t.off("mouseup.mousewidget"),t.off("touchend.mousewidget"),this.is_mouse_started&&(this.is_mouse_started=!1,this._mouseStop(e))},t}(o(3).default);t.default=i},function(e,t,o){"use strict";t.__esModule=!0;var n=o(1),r=function(){function e(e){this.tree_widget=e}return e.prototype.saveState=function(){var e=JSON.stringify(this.getState());this.tree_widget.options.onSetStateFromStorage?this.tree_widget.options.onSetStateFromStorage(e):this.supportsLocalStorage()&&localStorage.setItem(this.getKeyName(),e)},e.prototype.getStateFromStorage=function(){var e=this._loadFromStorage();return e?this._parseState(e):null},e.prototype.getState=function(){var e,t=this;return{open_nodes:(e=[],t.tree_widget.tree.iterate(function(t){return t.is_open&&t.id&&t.hasChildren()&&e.push(t.id),!0}),e),selected_node:t.tree_widget.getSelectedNodes().map(function(e){return e.id})}},e.prototype.setInitialState=function(e){if(e){var t=!1;return e.open_nodes&&(t=this._openInitialNodes(e.open_nodes)),e.selected_node&&(this._resetSelection(),this._selectInitialNodes(e.selected_node)),t}return!1},e.prototype.setInitialStateOnDemand=function(e,t){e?this._setInitialStateOnDemand(e.open_nodes,e.selected_node,t):t()},e.prototype.getNodeIdToBeSelected=function(){var e=this.getStateFromStorage();return e&&e.selected_node?e.selected_node[0]:null},e.prototype._parseState=function(e){var t=jQuery.parseJSON(e);return t&&t.selected_node&&n.isInt(t.selected_node)&&(t.selected_node=[t.selected_node]),t},e.prototype._loadFromStorage=function(){return this.tree_widget.options.onGetStateFromStorage?this.tree_widget.options.onGetStateFromStorage():this.supportsLocalStorage()?localStorage.getItem(this.getKeyName()):void 0},e.prototype._openInitialNodes=function(e){for(var t=!1,o=0,n=e;o=r},e.prototype.getScrollLeft=function(){return this.$scroll_parent&&this.$scroll_parent.scrollLeft()||0},e.prototype.initScrollParent=function(){var e=this,t=function(){e.scroll_parent_top=0,e.$scroll_parent=null};"fixed"===this.tree_widget.$el.css("position")&&t();var o=function(){var t=["overflow","overflow-y"],o=function(e){for(var o=0,n=t;o0,s=o.left+n.clientWidth,a=o.left,l=e.page_x>s-20,d=e.page_x0,i=e.page_x>n-20,s=e.page_x-o<20;i?t.scrollLeft(o+20):s&&r&&t.scrollLeft(Math.max(o-20,0))},e}();t.default=n},function(e,t,o){"use strict";t.__esModule=!0;var n=function(){function e(e){this.tree_widget=e,this.clear()}return e.prototype.getSelectedNode=function(){var e=this.getSelectedNodes();return!!e.length&&e[0]},e.prototype.getSelectedNodes=function(){if(this.selected_single_node)return[this.selected_single_node];var e=[];for(var t in this.selected_nodes)if(this.selected_nodes.hasOwnProperty(t)){var o=this.tree_widget.getNodeById(t);o&&e.push(o)}return e},e.prototype.getSelectedNodesUnder=function(e){if(this.selected_single_node)return e.isParentOf(this.selected_single_node)?[this.selected_single_node]:[];var t=[];for(var o in this.selected_nodes)if(this.selected_nodes.hasOwnProperty(o)){var n=this.tree_widget.getNodeById(o);n&&e.isParentOf(n)&&t.push(n)}return t},e.prototype.isNodeSelected=function(e){return!!e&&(null!=e.id?!!this.selected_nodes[e.id]:!!this.selected_single_node&&this.selected_single_node.element===e.element)},e.prototype.clear=function(){this.selected_nodes={},this.selected_single_node=null},e.prototype.removeFromSelection=function(e,t){var o=this;void 0===t&&(t=!1),null==e.id?this.selected_single_node&&e.element===this.selected_single_node.element&&(this.selected_single_node=null):(delete this.selected_nodes[e.id],t&&e.iterate(function(){return delete o.selected_nodes[e.id],!0}))},e.prototype.addToSelection=function(e){null!=e.id?this.selected_nodes[e.id]=!0:this.selected_single_node=e},e}();t.default=n},function(e,t,o){"use strict";var n,r=this&&this.__extends||(n=function(e,t){return(n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var o in t)t.hasOwnProperty(o)&&(e[o]=t[o])})(e,t)},function(e,t){function o(){this.constructor=e}n(e,t),e.prototype=null===t?Object.create(t):(o.prototype=t.prototype,new o)});t.__esModule=!0;var i=o(0),s=function(){function e(e,t){this.init(e,t)}return e.prototype.init=function(e,t){this.node=e,this.tree_widget=t,e.element||(e.element=this.tree_widget.element.get(0)),this.$element=jQuery(e.element)},e.prototype.addDropHint=function(e){return this.mustShowBorderDropHint(e)?new l(this.$element,this.tree_widget._getScrollLeft()):new d(this.node,this.$element,e)},e.prototype.select=function(e){var t=this.getLi();t.addClass("jqtree-selected"),t.attr("aria-selected","true");var o=this.getSpan();o.attr("tabindex",this.tree_widget.options.tabIndex),e&&o.focus()},e.prototype.deselect=function(){var e=this.getLi();e.removeClass("jqtree-selected"),e.attr("aria-selected","false");var t=this.getSpan();t.removeAttr("tabindex"),t.blur()},e.prototype.getUl=function(){return this.$element.children("ul:first")},e.prototype.getSpan=function(){return this.$element.children(".jqtree-element").find("span.jqtree-title")},e.prototype.getLi=function(){return this.$element},e.prototype.mustShowBorderDropHint=function(e){return e===i.Position.Inside},e}();t.NodeElement=s;var a=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.open=function(e,t,o){var n=this;if(void 0===t&&(t=!0),void 0===o&&(o="fast"),!this.node.is_open){this.node.is_open=!0;var r=this.getButton();r.removeClass("jqtree-closed"),r.html("");var i=r.get(0);if(i){var s=this.tree_widget.renderer.opened_icon_element.cloneNode(!0);i.appendChild(s)}var a=function(){n.getLi().removeClass("jqtree-closed"),n.getSpan().attr("aria-expanded","true"),e&&e(n.node),n.tree_widget._triggerEvent("tree.open",{node:n.node})};t?this.getUl().slideDown(o,a):(this.getUl().show(),a())}},t.prototype.close=function(e,t){var o=this;if(void 0===e&&(e=!0),void 0===t&&(t="fast"),this.node.is_open){this.node.is_open=!1;var n=this.getButton();n.addClass("jqtree-closed"),n.html("");var r=n.get(0);if(r){var i=this.tree_widget.renderer.closed_icon_element.cloneNode(!0);r.appendChild(i)}var s=function(){o.getLi().addClass("jqtree-closed"),o.getSpan().attr("aria-expanded","false"),o.tree_widget._triggerEvent("tree.close",{node:o.node})};e?this.getUl().slideUp(t,s):(this.getUl().hide(),s())}},t.prototype.mustShowBorderDropHint=function(e){return!this.node.is_open&&e===i.Position.Inside},t.prototype.getButton=function(){return this.$element.children(".jqtree-element").find("a.jqtree-toggler")},t}(s);t.FolderElement=a;var l=function(){function e(e,t){var o=e.children(".jqtree-element"),n=e.width()||0,r=Math.max(n+t-4,0),i=o.outerHeight()||0,s=Math.max(i-4,0);this.$hint=jQuery(''),o.append(this.$hint),this.$hint.css({width:r,height:s})}return e.prototype.remove=function(){this.$hint.remove()},e}();t.BorderDropHint=l;var d=function(){function e(e,t,o){this.$element=t,this.node=e,this.$ghost=jQuery('
  • \n
  • '),o===i.Position.After?this.moveAfter():o===i.Position.Before?this.moveBefore():o===i.Position.Inside&&(e.isFolder()&&e.is_open?this.moveInsideOpenFolder():this.moveInside())}return e.prototype.remove=function(){this.$ghost.remove()},e.prototype.moveAfter=function(){this.$element.after(this.$ghost)},e.prototype.moveBefore=function(){this.$element.before(this.$ghost)},e.prototype.moveInsideOpenFolder=function(){jQuery(this.node.children[0].element).before(this.$ghost)},e.prototype.moveInside=function(){this.$element.after(this.$ghost),this.$ghost.addClass("jqtree-inside")},e}()},,function(e,t,o){e.exports=o(4)}]); \ No newline at end of file diff --git a/utils/indexer.php b/utils/indexer.php index db39597aa..9d9f75686 100644 --- a/utils/indexer.php +++ b/utils/indexer.php @@ -105,7 +105,7 @@ function tree($dms, $index, $indexconf, $folder, $indent='') { /* {{{ */ $created = 0; } $content = $document->getLatestContent(); - if($created >= $content->getDate()) { + if($created > $content->getDate()) { echo " (Document unchanged)\n"; } else { $index->delete($hit->id); diff --git a/views/bootstrap/class.ApprovalSummary.php b/views/bootstrap/class.ApprovalSummary.php index 4d3f2a76a..f3f0d809c 100644 --- a/views/bootstrap/class.ApprovalSummary.php +++ b/views/bootstrap/class.ApprovalSummary.php @@ -42,8 +42,9 @@ class SeedDMS_View_ApprovalSummary extends SeedDMS_Bootstrap_Style { $cachedir = $this->params['cachedir']; $previewwidth = $this->params['previewWidthList']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout, $xsendfile); $this->htmlStartPage(getMLText("approval_summary")); $this->globalNavigation(); diff --git a/views/bootstrap/class.AttributeMgr.php b/views/bootstrap/class.AttributeMgr.php index 919059616..f6b37d321 100644 --- a/views/bootstrap/class.AttributeMgr.php +++ b/views/bootstrap/class.AttributeMgr.php @@ -66,6 +66,7 @@ $(document).ready( function() { $enableRecursiveCount = $this->params['enableRecursiveCount']; $maxRecursiveCount = $this->params['maxRecursiveCount']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; if($selattrdef) { $this->contentHeading(getMLText("attrdef_info")); @@ -130,7 +131,7 @@ $(document).ready( function() { foreach($res['folders'] as $subFolder) { echo $this->folderListRow($subFolder); } - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout, $xsendfile); foreach($res['docs'] as $document) { echo $this->documentListRow($document, $previewer); } @@ -146,7 +147,7 @@ $(document).ready( function() { print "".getMLText("status")."\n"; print "".getMLText("action")."\n"; print "\n\n\n"; - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout, $xsendfile); foreach($res['contents'] as $content) { $doc = $content->getDocument(); echo $this->documentListRow($doc, $previewer); diff --git a/views/bootstrap/class.Bootstrap.php b/views/bootstrap/class.Bootstrap.php index d86e105ab..1eb4bb615 100644 --- a/views/bootstrap/class.Bootstrap.php +++ b/views/bootstrap/class.Bootstrap.php @@ -50,12 +50,14 @@ class SeedDMS_Bootstrap_Style extends SeedDMS_View_Common { /* We still need unsafe-eval, because printDocumentChooserHtml and * printFolderChooserHtml will include a javascript file with ajax * which is evaluated by jquery + * worker-src blob: is needed for cytoscape * X-WebKit-CSP is deprecated, Chrome understands Content-Security-Policy * since version 25+ * X-Content-Security-Policy is deprecated, Firefox understands * Content-Security-Policy since version 23+ + * 'worker-src blob:' is needed for cytoscape */ - $csp_rules = "script-src 'self' 'unsafe-eval';"; // style-src 'self';"; + $csp_rules = "script-src 'self' 'unsafe-eval'; worker-src blob:;"; // style-src 'self';"; foreach (array("X-WebKit-CSP", "X-Content-Security-Policy", "Content-Security-Policy") as $csp) { header($csp . ": " . $csp_rules); } @@ -594,7 +596,7 @@ background-image: linear-gradient(to bottom, #882222, #111111);; if ($this->params['enableusersview']){ $menuitems['users'] = array('link'=>"../out/out.UsrView.php", 'label'=>'users'); - $menuitems['users'] = array('link'=>"../out/out.GroupView.php", 'label'=>'groups'); + $menuitems['groups'] = array('link'=>"../out/out.GroupView.php", 'label'=>'groups'); } /* Check if hook exists because otherwise callHook() will override $menuitems */ @@ -1374,7 +1376,7 @@ $(document).ready(function() { } else { $content .= "\""; } - $content .= "".((!$norequire && $attrdef->getMinValues() > 0) ? ' required' : '')." class=\"chzn-select-deselect\" data-placeholder=\"".getMLText("select_value")."\">"; + $content .= "".((!$norequire && $attrdef->getMinValues() > 0) ? ' required' : '')." class=\"chzn-select\" data-placeholder=\"".getMLText("select_value")."\">"; if(!$attrdef->getMultipleValues()) { $content .= ""; } @@ -1465,9 +1467,9 @@ $(document).ready(function() { function getImgPath($img) { /* {{{ */ - if ( is_file($this->imgpath.$img) ) { +// if ( is_file($this->imgpath.$img) ) { return $this->imgpath.$img; - } +// } return ""; } /* }}} */ @@ -1571,27 +1573,28 @@ $(document).ready(function() { * and documents shown in the tree * @param boolean $showdocs set to true if tree shall contain documents * as well. + * @param integer $expandtree level to which the tree shall be opened */ function printNewTreeNavigationJs($folderid=0, $accessmode=M_READ, $showdocs=0, $formid='form1', $expandtree=0, $orderby='') { /* {{{ */ - function jqtree($path, $folder, $user, $accessmode, $showdocs=1, $expandtree=0, $orderby='') { - if($path || $expandtree) { + function jqtree($path, $folder, $user, $accessmode, $showdocs=1, $expandtree=0, $orderby='', $level=0) { + if($path || $expandtree>=$level) { if($path) $pathfolder = array_shift($path); $subfolders = $folder->getSubFolders($orderby); $subfolders = SeedDMS_Core_DMS::filterAccess($subfolders, $user, $accessmode); $children = array(); foreach($subfolders as $subfolder) { - $node = array('label'=>$subfolder->getName(), 'id'=>$subfolder->getID(), 'load_on_demand'=>($subfolder->hasSubFolders() || ($subfolder->hasDocuments() && $showdocs)) ? true : false, 'is_folder'=>true); - if($expandtree || $pathfolder->getID() == $subfolder->getID()) { + $node = array('label'=>$subfolder->getName(), 'id'=>$subfolder->getID(), 'load_on_demand'=>($subfolder->hasSubFolders() || ($subfolder->hasDocuments() && $showdocs)) ? false : false, 'is_folder'=>true); + if($expandtree>=$level || $pathfolder->getID() == $subfolder->getID()) { + $node['children'] = jqtree($path, $subfolder, $user, $accessmode, $showdocs, $expandtree, $orderby, $level+1); if($showdocs) { - $documents = $folder->getDocuments($orderby); + $documents = $subfolder->getDocuments($orderby); $documents = SeedDMS_Core_DMS::filterAccess($documents, $user, $accessmode); foreach($documents as $document) { $node2 = array('label'=>$document->getName(), 'id'=>$document->getID(), 'load_on_demand'=>false, 'is_folder'=>false); - $children[] = $node2; + $node['children'][] = $node2; } } - $node['children'] = jqtree($path, $subfolder, $user, $accessmode, $showdocs, $expandtree, $orderby); } $children[] = $node; } @@ -1601,7 +1604,7 @@ $(document).ready(function() { $subfolders = SeedDMS_Core_DMS::filterAccess($subfolders, $user, $accessmode); $children = array(); foreach($subfolders as $subfolder) { - $node = array('label'=>$subfolder->getName(), 'id'=>$subfolder->getID(), 'load_on_demand'=>($subfolder->hasSubFolders() || ($subfolder->hasDocuments() && $showdocs)) ? true : false, 'is_folder'=>true); + $node = array('label'=>$subfolder->getName(), 'id'=>$subfolder->getID(), 'load_on_demand'=>($subfolder->hasSubFolders() || ($subfolder->hasDocuments() && $showdocs)) ? false : false, 'is_folder'=>true); $children[] = $node; } return $children; @@ -1612,13 +1615,14 @@ $(document).ready(function() { if($folderid) { $folder = $this->params['dms']->getFolder($folderid); $path = $folder->getPath(); + /* Get the first folder (root folder) of path */ $folder = array_shift($path); - $node = array('label'=>$folder->getName(), 'id'=>$folder->getID(), 'load_on_demand'=>true, 'is_folder'=>true); + $node = array('label'=>$folder->getName(), 'id'=>$folder->getID(), 'load_on_demand'=>false, 'is_folder'=>true); if(!$folder->hasSubFolders()) { $node['load_on_demand'] = false; $node['children'] = array(); } else { - $node['children'] = jqtree($path, $folder, $this->params['user'], $accessmode, $showdocs, $expandtree, $orderby); + $node['children'] = jqtree($path, $folder, $this->params['user'], $accessmode, $showdocs, $expandtree, $orderby, 0); if($showdocs) { $documents = $folder->getDocuments($orderby); $documents = SeedDMS_Core_DMS::filterAccess($documents, $this->params['user'], $accessmode); @@ -1638,18 +1642,18 @@ $(document).ready(function() { } else { $root = $this->params['dms']->getFolder($this->params['rootfolderid']); - $tree = array(array('label'=>$root->getName(), 'id'=>$root->getID(), 'load_on_demand'=>true, 'is_folder'=>true)); + $tree = array(array('label'=>$root->getName(), 'id'=>$root->getID(), 'load_on_demand'=>false, 'is_folder'=>true)); } ?> var data = ; $(function() { $('#jqtree').tree({ - saveState: true, +// saveState: true, data: data, saveState: 'jqtree', - openedIcon: '', - closedIcon: '', + openedIcon: $(''), + closedIcon: $(''), _onCanSelectNode: function(node) { if(node.is_folder) { folderSelected(node.id, node.name); @@ -1666,20 +1670,50 @@ $(function() { $li.find('.jqtree-title').before(' '); } }); - // Unfold tree if folder is opened + // Unfold node for currently selected folder $('#jqtree').tree('openNode', $('#jqtree').tree('getNodeById', ), false); - $('#jqtree').bind( - 'tree.click', + $('#jqtree').on( + 'tree.select', function(event) { var node = event.node; $('#jqtree').tree('openNode', node); // event.preventDefault(); if(node.is_folder) { + if(typeof node.fetched == 'undefined') { + node.fetched = true; + $(this).tree('loadDataFromUrl', node, function () { + $(this).tree('openNode', node);} + ); + } folderSelected(node.id, node.name); } else documentSelected(node.id, node.name); } ); + $('#jqtree').on( + 'tree.contextmenu', + function(event) { + // The clicked node is 'event.node' + var node = event.node; + if(typeof node.fetched == 'undefined') { + node.fetched = true; + $(this).tree('loadDataFromUrl', node); + } + $(this).tree('openNode', node); + } + ); + $("#jqtree").on('dragenter', function (e) { + attr_rel = $(e.srcElement).attr('rel'); + if(typeof attr_rel == 'undefined') + return; + target_type = attr_rel.split("_")[0]; + target_id = attr_rel.split("_")[1]; + var node = $(this).tree('getNodeById', parseInt(target_id)); + if(typeof node.fetched == 'undefined') { + node.fetched = true; + $(this).tree('loadDataFromUrl', node, function() {$(this).tree('openNode', node);}); + } + }); }); "; - if($version) - $latestContent = $document->getContentByVersion($version); - else - $latestContent = $document->getLatestContent(); + if($version) { + $latestContent = $this->callHook('documentContent', $document, $version); + if($latestContent === null) + $latestContent = $document->getContentByVersion($version); + } else { + $latestContent = $this->callHook('documentLatestContent', $document); + if($latestContent === null) + $latestContent = $document->getLatestContent(); + } if($latestContent) { $previewer->createPreview($latestContent); @@ -2570,7 +2609,7 @@ $(document).ready(function() { echo ""; echo "".$rec['date']." - "; $updateuser = $dms->getUser($rec["userID"]); - if(!is_object($required)) + if(!is_object($updateuser)) echo getMLText("unknown_user"); else echo htmlspecialchars($updateuser->getFullName()." (".$updateuser->getLogin().")"); diff --git a/views/bootstrap/class.Calendar.php b/views/bootstrap/class.Calendar.php index 0b9ca0bee..8e49920b6 100644 --- a/views/bootstrap/class.Calendar.php +++ b/views/bootstrap/class.Calendar.php @@ -46,6 +46,7 @@ class SeedDMS_View_Calendar extends SeedDMS_Bootstrap_Style { $previewwidthlist = $this->params['previewWidthList']; $previewwidthdetail = $this->params['previewWidthDetail']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; if($document) { // $this->contentHeading(getMLText("timeline_selected_item")); @@ -56,7 +57,7 @@ class SeedDMS_View_Calendar extends SeedDMS_Bootstrap_Style { print "".getMLText("status")."\n"; print "".getMLText("action")."\n"; print "\n\n\n"; - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidthdetail, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidthdetail, $timeout, $xsendfile); echo $this->documentListRow($document, $previewer); echo "\n\n"; @@ -125,6 +126,7 @@ class SeedDMS_View_Calendar extends SeedDMS_Bootstrap_Style { $previewwidthlist = $this->params['previewWidthList']; $previewwidthdetail = $this->params['previewWidthDetail']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; if($this->params['start']) { $from = makeTsFromLongDate($this->params['start'].' 00:00:00'); @@ -141,7 +143,7 @@ class SeedDMS_View_Calendar extends SeedDMS_Bootstrap_Style { print "".getMLText("status")."\n"; print "".getMLText("action")."\n"; print "\n\n\n"; - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidthdetail, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidthdetail, $timeout, $xsendfile); foreach($data as $i=>$item) { /* Filter out timeline events for the documents not happened on the * selected day diff --git a/views/bootstrap/class.Categories.php b/views/bootstrap/class.Categories.php index fda5ddb50..ceb8b2ed3 100644 --- a/views/bootstrap/class.Categories.php +++ b/views/bootstrap/class.Categories.php @@ -56,6 +56,7 @@ $(document).ready( function() { $cachedir = $this->params['cachedir']; $previewwidth = $this->params['previewWidthList']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; if($selcat) { $this->contentHeading(getMLText("category_info")); @@ -73,7 +74,7 @@ $(document).ready( function() { print "".getMLText("status")."\n"; print "".getMLText("action")."\n"; print "\n\n\n"; - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout, $xsendfile); foreach($documents as $doc) { echo $this->documentListRow($doc, $previewer); } diff --git a/views/bootstrap/class.Clipboard.php b/views/bootstrap/class.Clipboard.php index fa03444eb..d912e2e57 100644 --- a/views/bootstrap/class.Clipboard.php +++ b/views/bootstrap/class.Clipboard.php @@ -103,8 +103,9 @@ class SeedDMS_View_Clipboard extends SeedDMS_Bootstrap_Style { $cachedir = $this->params['cachedir']; $previewwidth = $this->params['previewWidthList']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout, $xsendfile); $content = ''; $foldercount = $doccount = 0; if($clipboard['folders']) { @@ -134,7 +135,10 @@ class SeedDMS_View_Clipboard extends SeedDMS_Bootstrap_Style { if($document = $dms->getDocument($docid)) { $comment = $document->getComment(); if (strlen($comment) > 150) $comment = substr($comment, 0, 147) . "..."; - if($latestContent = $document->getLatestContent()) { + $latestContent = $this->callHook('documentLatestContent', $document); + if($latestContent === null) + $latestContent = $document->getLatestContent(); + if($latestContent) { $previewer->createPreview($latestContent); $version = $latestContent->getVersion(); $status = $latestContent->getStatus(); diff --git a/views/bootstrap/class.DefaultKeywords.php b/views/bootstrap/class.DefaultKeywords.php index bdac1fbeb..5aa4e4198 100644 --- a/views/bootstrap/class.DefaultKeywords.php +++ b/views/bootstrap/class.DefaultKeywords.php @@ -117,6 +117,23 @@ $(document).ready( function() { params['dms']; + $user = $this->params['user']; + $selcategoryid = $this->params['selcategoryid']; + + if($selcategoryid && $selcategoryid > 0) { +?> +
    + + + + +
    +params['dms']; $user = $this->params['user']; @@ -129,30 +146,27 @@ $(document).ready( function() { if(!$category) { ?> -
    + - : - "> +formField( + getMLText("name"), + array( + 'element'=>'input', + 'type'=>'text', + 'name'=>'name', + 'value'=>'' + ) + ); + $this->formSubmit(" ".getMLText('new_default_keyword_category')); +?>
    getOwner(); if ((!$user->isAdmin()) && ($owner->getID() != $user->getID())) return; ?> - -
    - -
    -
    - - - - -
    -
    -
    -
    @@ -229,14 +243,10 @@ $(document).ready( function() { ?>
    -contentContainerStart(); ?>
    -
    - -
    - +
    -
    -contentContainerEnd(); ?> +
    >
    diff --git a/views/bootstrap/class.DocumentAccess.php b/views/bootstrap/class.DocumentAccess.php index 8753f4cac..f45241a4a 100644 --- a/views/bootstrap/class.DocumentAccess.php +++ b/views/bootstrap/class.DocumentAccess.php @@ -189,11 +189,16 @@ $(document).ready( function() { getUser(); + $memusers[] = $userObj->getID(); + } $options = array(); $options[] = array(-1, getMLText('select_one')); foreach ($allUsers as $currUser) { - if (!$currUser->isGuest()) - $options[] = array($currUser->getID(), htmlspecialchars($currUser->getLogin()), ($currUser->getID()==$user->getID()), array(array('data-subtitle', htmlspecialchars($currUser->getFullName())))); + if (!$currUser->isGuest() && !in_array($currUser->getID(), $memusers)) + $options[] = array($currUser->getID(), htmlspecialchars($currUser->getLogin()), false, array(array('data-subtitle', htmlspecialchars($currUser->getFullName())))); } $this->formField( getMLText("user"), @@ -204,10 +209,16 @@ $(document).ready( function() { 'options'=>$options ) ); + $memgroups = array(); + foreach ($accessList["groups"] as $groupAccess) { + $groupObj = $groupAccess->getGroup(); + $memgroups[] = $groupObj->getID(); + } $options = array(); $options[] = array(-1, getMLText('select_one')); foreach ($allGroups as $groupObj) { - $options[] = array($groupObj->getID(), htmlspecialchars($groupObj->getName())); + if(!in_array($groupObj->getID(), $memgroups)) + $options[] = array($groupObj->getID(), htmlspecialchars($groupObj->getName())); } $this->formField( getMLText("group"), diff --git a/views/bootstrap/class.DocumentVersionDetail.php b/views/bootstrap/class.DocumentVersionDetail.php index 031ad5a8a..91b1781be 100644 --- a/views/bootstrap/class.DocumentVersionDetail.php +++ b/views/bootstrap/class.DocumentVersionDetail.php @@ -39,6 +39,7 @@ class SeedDMS_View_DocumentVersionDetail extends SeedDMS_Bootstrap_Style { function preview() { /* {{{ */ $document = $this->params['document']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; $showfullpreview = $this->params['showFullPreview']; $converttopdf = $this->params['convertToPdf']; $cachedir = $this->params['cachedir']; @@ -74,7 +75,7 @@ class SeedDMS_View_DocumentVersionDetail extends SeedDMS_Bootstrap_Style { break; } if($converttopdf) { - $pdfpreviewer = new SeedDMS_Preview_PdfPreviewer($cachedir, $timeout); + $pdfpreviewer = new SeedDMS_Preview_PdfPreviewer($cachedir, $timeout, $xsendfile); if($pdfpreviewer->hasConverter($version->getMimeType())) { $this->contentHeading(getMLText("preview")); ?> @@ -95,6 +96,7 @@ class SeedDMS_View_DocumentVersionDetail extends SeedDMS_Bootstrap_Style { $cachedir = $this->params['cachedir']; $previewwidthdetail = $this->params['previewWidthDetail']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; $status = $version->getStatus(); $reviewStatus = $version->getReviewStatus(); @@ -208,7 +210,7 @@ class SeedDMS_View_DocumentVersionDetail extends SeedDMS_Bootstrap_Style { print "
      "; print "
    "; - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidthdetail, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidthdetail, $timeout, $xsendfile); $previewer->createPreview($version); if($previewer->hasPreview($version)) { print("getID()."&version=".$version->getVersion()."&width=".$previewwidthdetail."\" title=\"".htmlspecialchars($version->getMimeType())."\">"); @@ -235,7 +237,7 @@ class SeedDMS_View_DocumentVersionDetail extends SeedDMS_Bootstrap_Style { print ""; print "
      "; @@ -401,7 +403,7 @@ class SeedDMS_View_DocumentVersionDetail extends SeedDMS_Bootstrap_Style { print ""; $previewer->createPreview($file, $previewwidthdetail); if($file_exists) { - if ($viewonlinefiletypes && in_array(strtolower($file->getFileType()), $viewonlinefiletypes)) { + if ($viewonlinefiletypes && (in_array(strtolower($file->getFileType()), $viewonlinefiletypes) || in_array(strtolower($file->getMimeType()), $viewonlinefiletypes))) { print "getID()."\">"; } else { print "getID()."\">"; @@ -434,7 +436,7 @@ class SeedDMS_View_DocumentVersionDetail extends SeedDMS_Bootstrap_Style { print "
        "; if ($file_exists) { print "
      • getID()."\">".getMLText('download')."
      • "; - if ($viewonlinefiletypes && in_array(strtolower($file->getFileType()), $viewonlinefiletypes)) { + if ($viewonlinefiletypes && (in_array(strtolower($file->getFileType()), $viewonlinefiletypes) || in_array(strtolower($file->getMimeType()), $viewonlinefiletypes))) { print "
      • getID()."\">" . getMLText("view_online") . "
      • "; } } else print "
      • getMimeIcon($file->getFileType())."\" title=\"".htmlspecialchars($file->getMimeType())."\">"; diff --git a/views/bootstrap/class.DropFolderChooser.php b/views/bootstrap/class.DropFolderChooser.php index 887f77711..1349641db 100644 --- a/views/bootstrap/class.DropFolderChooser.php +++ b/views/bootstrap/class.DropFolderChooser.php @@ -58,9 +58,10 @@ $('.folderselect').click(function(ev) { $cachedir = $this->params['cachedir']; $previewwidth = $this->params['previewWidthMenuList']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; $folderid = isset($_GET['folderid']) ? $_GET['folderid'] : 0; - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout, $xsendfile); $c = 0; // count files $filecontent = ''; @@ -116,9 +117,10 @@ $('.folderselect').click(function(ev) { $cachedir = $this->params['cachedir']; $previewwidth = $this->params['previewWidthList']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; $showfolders = $this->params['showfolders']; - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout, $xsendfile); $dir = $dropfolderdir.'/'.$user->getLogin(); /* Check if we are still looking in the configured directory and diff --git a/views/bootstrap/class.EditOnline.php b/views/bootstrap/class.EditOnline.php index 10995b10e..80c316d35 100644 --- a/views/bootstrap/class.EditOnline.php +++ b/views/bootstrap/class.EditOnline.php @@ -74,14 +74,13 @@ $(document).ready(function() {
        text(file_get_contents($dms->contentDir . $version->getPath())); ?>
        ".htmlspecialchars(file_get_contents($dms->contentDir . $version->getPath())).""; + echo "
        ".htmlspecialchars(file_get_contents($dms->contentDir . $version->getPath()), ENT_SUBSTITUTE)."
        "; ?>
        @@ -121,7 +120,7 @@ $this->contentHeading(getMLText("content")); diff --git a/views/bootstrap/class.ErrorDlg.php b/views/bootstrap/class.ErrorDlg.php index 10873999e..ef5cc64ed 100644 --- a/views/bootstrap/class.ErrorDlg.php +++ b/views/bootstrap/class.ErrorDlg.php @@ -37,9 +37,10 @@ class SeedDMS_View_ErrorDlg extends SeedDMS_Bootstrap_Style { $pagetitle = $this->params['pagetitle']; $errormsg = $this->params['errormsg']; $plain = $this->params['plain']; + $settings = $this->params['settings']; - if(!$plain) { - $this->htmlStartPage($pagetitle); + if(!$plain) { + $this->htmlStartPage($pagetitle, 'errorpage', $settings->_httpRoot."out"); $this->globalNavigation(); $this->contentStart(); } diff --git a/views/bootstrap/class.ExpiredDocuments.php b/views/bootstrap/class.ExpiredDocuments.php index bd682f529..4008df0a0 100644 --- a/views/bootstrap/class.ExpiredDocuments.php +++ b/views/bootstrap/class.ExpiredDocuments.php @@ -43,9 +43,10 @@ class SeedDMS_View_ExpiredDocuments extends SeedDMS_Bootstrap_Style { $cachedir = $this->params['cachedir']; $previewwidth = $this->params['previewWidthList']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; $db = $dms->getDB(); - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout, $xsendfile); $this->htmlStartPage(getMLText("expired_documents")); $this->globalNavigation(); @@ -67,7 +68,7 @@ class SeedDMS_View_ExpiredDocuments extends SeedDMS_Bootstrap_Style { print "".getMLText("expires")."\n"; print "\n\n\n"; - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout, $xsendfile); foreach ($docs as $document) { print "\n"; $latestContent = $document->getLatestContent(); diff --git a/views/bootstrap/class.ExtensionMgr.php b/views/bootstrap/class.ExtensionMgr.php index fffc882ea..18f607109 100644 --- a/views/bootstrap/class.ExtensionMgr.php +++ b/views/bootstrap/class.ExtensionMgr.php @@ -59,6 +59,13 @@ class SeedDMS_View_ExtensionMgr extends SeedDMS_Bootstrap_Style { var element = $(this); $('#'+element.data('extname')+'-import').submit(); }); + + $("#extensionfilter").on("keyup", function() { + var value = $(this).val().toLowerCase(); + $("#extensionlist tbody tr").filter(function() { + $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1) + }); + }); });
        + contentContainerStart(); - echo "\n"; + echo "
        \n"; print "\n\n"; print "\n"; print "\n"; diff --git a/views/bootstrap/class.FolderAccess.php b/views/bootstrap/class.FolderAccess.php index 4a5f18b9d..bf3905d05 100644 --- a/views/bootstrap/class.FolderAccess.php +++ b/views/bootstrap/class.FolderAccess.php @@ -193,7 +193,7 @@ $(document).ready(function() { $options[] = array(-1, getMLText('select_one')); foreach ($allUsers as $currUser) { if (!$currUser->isGuest()) - $options[] = array($currUser->getID(), htmlspecialchars($currUser->getLogin()), ($currUser->getID()==$user->getID()), array(array('data-subtitle', htmlspecialchars($currUser->getFullName())))); + $options[] = array($currUser->getID(), htmlspecialchars($currUser->getLogin()), false, array(array('data-subtitle', htmlspecialchars($currUser->getFullName())))); } $this->formField( getMLText("user"), diff --git a/views/bootstrap/class.GroupMgr.php b/views/bootstrap/class.GroupMgr.php index c70dbc59a..7fbed3d4c 100644 --- a/views/bootstrap/class.GroupMgr.php +++ b/views/bootstrap/class.GroupMgr.php @@ -113,9 +113,10 @@ $(document).ready( function() { $previewwidth = $this->params['previewWidthList']; $workflowmode = $this->params['workflowmode']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; if($selgroup) { - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout, $xsendfile); $this->contentHeading(getMLText("group_info")); echo "
        ".getMLText('name')."
        \n"; if($workflowmode == "traditional") { diff --git a/views/bootstrap/class.Help.php b/views/bootstrap/class.Help.php index 4df03d260..15d9d2898 100644 --- a/views/bootstrap/class.Help.php +++ b/views/bootstrap/class.Help.php @@ -45,12 +45,13 @@ class SeedDMS_View_Help extends SeedDMS_Bootstrap_Style {
        Table of contents params['session']->getLanguage()."/help"); + $dir = "../languages/".$this->params['session']->getLanguage()."/help"; + $d = dir($dir); echo "
          "; while (false !== ($entry = $d->read())) { if($entry != '..' && $entry != '.') { $path_parts = pathinfo($dir."/".$entry); - if($path_parts['extension'] == 'html' || $path_parts['extension'] == 'md') { + if(isset($path_parts['extension']) && ($path_parts['extension'] == 'html' || $path_parts['extension'] == 'md')) { echo "
        • ".getMLText('help_'.$path_parts['filename'], array(), $path_parts['filename'])."
        • "; } } diff --git a/views/bootstrap/class.Indexer.php b/views/bootstrap/class.Indexer.php index 31a2a62da..fc35be2bc 100644 --- a/views/bootstrap/class.Indexer.php +++ b/views/bootstrap/class.Indexer.php @@ -152,7 +152,7 @@ $(document).ready( function() { */ } else { /* Check if the attribute created is set or has a value older - * than the lasted content. Documents without such an attribute + * than the lastet content. Documents without such an attribute * where added when a new document was added to the dms. In such * a case the document content wasn't indexed. */ @@ -162,7 +162,7 @@ $(document).ready( function() { $created = 0; } $content = $document->getLatestContent(); - if($created >= $content->getDate() && !$forceupdate) { + if($created > $content->getDate() && !$forceupdate) { echo $indent."getID()."\" class=\"indexstatus\" data-docid=\"".$document->getID()."\">document unchanged"; } else { $index->delete($hit->id); diff --git a/views/bootstrap/class.Login.php b/views/bootstrap/class.Login.php index 3241f819a..68f5c37f4 100644 --- a/views/bootstrap/class.Login.php +++ b/views/bootstrap/class.Login.php @@ -32,6 +32,7 @@ require_once("class.Bootstrap.php"); class SeedDMS_View_Login extends SeedDMS_Bootstrap_Style { function js() { /* {{{ */ + header('Content-Type: application/javascript; charset=UTF-8'); ?> document.form1.login.focus(); function checkForm() diff --git a/views/bootstrap/class.ManageNotify.php b/views/bootstrap/class.ManageNotify.php index 6501545e9..da096a740 100644 --- a/views/bootstrap/class.ManageNotify.php +++ b/views/bootstrap/class.ManageNotify.php @@ -95,7 +95,7 @@ class SeedDMS_View_ManageNotify extends SeedDMS_Bootstrap_Style { printMLText("empty_notify_list"); } else { - $previewer = new SeedDMS_Preview_Previewer($this->cachedir, $this->previewwidth, $this->timeout); + $previewer = new SeedDMS_Preview_Previewer($this->cachedir, $this->previewwidth, $this->timeout, $this->xsendfile); print "
        "; print "\n\n"; @@ -153,6 +153,7 @@ class SeedDMS_View_ManageNotify extends SeedDMS_Bootstrap_Style { $this->previewwidth = $this->params['previewWidthList']; $this->db = $this->dms->getDB(); $this->timeout = $this->params['timeout']; + $this->xsendfile = $this->params['xsendfile']; $this->htmlStartPage(getMLText("my_account")); $this->globalNavigation(); diff --git a/views/bootstrap/class.MyDocuments.php b/views/bootstrap/class.MyDocuments.php index 0aeb7cdfd..a3a25d66a 100644 --- a/views/bootstrap/class.MyDocuments.php +++ b/views/bootstrap/class.MyDocuments.php @@ -45,9 +45,10 @@ class SeedDMS_View_MyDocuments extends SeedDMS_Bootstrap_Style { $workflowmode = $this->params['workflowmode']; $previewwidth = $this->params['previewWidthList']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; $db = $dms->getDB(); - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout, $xsendfile); $this->htmlStartPage(getMLText("my_documents")); $this->globalNavigation(); @@ -929,7 +930,7 @@ class SeedDMS_View_MyDocuments extends SeedDMS_Bootstrap_Style { print "\n"; print "\n\n\n"; - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout, $xsendfile); foreach ($resArr as $res) { $document = $dms->getDocument($res["documentID"]); $document->verifyLastestContentExpriry(); diff --git a/views/bootstrap/class.OverrideContentStatus.php b/views/bootstrap/class.OverrideContentStatus.php index f26db9794..d05d1ba4e 100644 --- a/views/bootstrap/class.OverrideContentStatus.php +++ b/views/bootstrap/class.OverrideContentStatus.php @@ -100,7 +100,7 @@ $(document).ready(function() { $options[] = array('', ''); if ($overallStatus["status"] == S_OBSOLETE) $options[] = array(S_RELEASED, getOverallStatusText(S_RELEASED)); - if ($overallStatus["status"] == S_RELEASED) + if ($overallStatus["status"] != S_OBSOLETE) $options[] = array(S_OBSOLETE, getOverallStatusText(S_OBSOLETE)); $this->formField( getMLText("status"), diff --git a/views/bootstrap/class.ReviewDocument.php b/views/bootstrap/class.ReviewDocument.php index ebf71f670..8937e40a4 100644 --- a/views/bootstrap/class.ReviewDocument.php +++ b/views/bootstrap/class.ReviewDocument.php @@ -143,7 +143,7 @@ $(document).ready(function() { ); $this->formField( getMLText("review_file"), - $this->getFileChooserHtml('review_file', false) + $this->getFileChooserHtml('reviewfile', false) ); $options = array(); if($reviewStatus['status'] != 1) diff --git a/views/bootstrap/class.ReviewSummary.php b/views/bootstrap/class.ReviewSummary.php index bbe2a2030..56a94973c 100644 --- a/views/bootstrap/class.ReviewSummary.php +++ b/views/bootstrap/class.ReviewSummary.php @@ -42,8 +42,9 @@ class SeedDMS_View_ReviewSummary extends SeedDMS_Bootstrap_Style { $cachedir = $this->params['cachedir']; $previewwidth = $this->params['previewWidthList']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout, $xsendfile); $this->htmlStartPage(getMLText("my_documents")); $this->globalNavigation(); diff --git a/views/bootstrap/class.Search.php b/views/bootstrap/class.Search.php index 838acf209..77d5b898d 100644 --- a/views/bootstrap/class.Search.php +++ b/views/bootstrap/class.Search.php @@ -97,6 +97,7 @@ class SeedDMS_View_Search extends SeedDMS_Bootstrap_Style { $cachedir = $this->params['cachedir']; $previewwidth = $this->params['previewWidthList']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; $this->htmlAddHeader(''."\n", 'js'); @@ -468,7 +469,7 @@ class SeedDMS_View_Search extends SeedDMS_Bootstrap_Style { print "\n\n\n"; } - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout, $xsendfile); foreach ($entries as $entry) { if(get_class($entry) == $dms->getClassname('document')) { $txt = $this->callHook('documentListItem', $entry, $previewer, false, 'search'); diff --git a/views/bootstrap/class.Settings.php b/views/bootstrap/class.Settings.php index 5e08f42c8..27ea716b2 100644 --- a/views/bootstrap/class.Settings.php +++ b/views/bootstrap/class.Settings.php @@ -349,6 +349,7 @@ $this->showStartPaneContent('site', (!$currenttab || $currenttab == 'site')); showConfigCheckbox('settings_enableLargeFileUpload', 'enableLargeFileUpload'); ?> showConfigText('settings_partitionSize', 'partitionSize'); ?> showConfigText('settings_maxUploadSize', 'maxUploadSize'); ?> +showConfigCheckbox('settings_enableXsendfile', 'enableXsendfile'); ?> @@ -484,7 +485,7 @@ $this->showStartPaneContent('site', (!$currenttab || $currenttab == 'site')); break; case 'select': if(!empty($conf['options'])) { - $selections = explode(",", $settings->_extensions[$extname][$confkey]); + $selections = empty($settings->_extensions[$extname][$confkey]) ? array() : explode(",", $settings->_extensions[$extname][$confkey]); echo "
        ".getMLText("expires")."
        + +
        diff --git a/views/bootstrap/class.Tasks.php b/views/bootstrap/class.Tasks.php index 4ab43fe2f..4f54348fe 100644 --- a/views/bootstrap/class.Tasks.php +++ b/views/bootstrap/class.Tasks.php @@ -40,42 +40,61 @@ class SeedDMS_View_Tasks extends SeedDMS_Bootstrap_Style { $dms = $this->params['dms']; $user = $this->params['user']; $workflowmode = $this->params['workflowmode']; - if($workflowmode == 'traditional') - $tasks['review'] = array(); - elseif($workflowmode == 'traditional' || $workflowmode == 'traditional_only_approval') + if($workflowmode == 'traditional' || $workflowmode == 'traditional_only_approval') { $tasks['approval'] = array(); - elseif($workflowmode == 'advanced') + if($workflowmode == 'traditional') + $tasks['review'] = array(); + } elseif($workflowmode == 'advanced') $tasks['workflow'] = array(); if($workflowmode == 'traditional' || $workflowmode == 'traditional_only_approval') { $resArr = $dms->getDocumentList('ApproveByMe', $user); if($resArr) { + $docs = array(); foreach ($resArr as $res) { $document = $dms->getDocument($res["id"]); if($document->getAccessMode($user) >= M_READ && $document->getLatestContent()) { - $tasks['approval'][] = array('id'=>$res['id'], 'name'=>$res['name']); + $docs[] = $document; +// $tasks['approval'][] = array('id'=>$res['id'], 'name'=>$res['name']); } } + if($this->hasHook('filterApprovalTaskList')) + $docs = $this->callHook('filterApprovalTaskList', $docs); + foreach($docs as $doc) + $tasks['approval'][] = array('id'=>$doc->getId(), 'name'=>$doc->getName()); } - } elseif($workflowmode == 'traditional') { - $resArr = $dms->getDocumentList('ReviewByMe', $user); - if($resArr) { - foreach ($resArr as $res) { - $document = $dms->getDocument($res["id"]); - if($document->getAccessMode($user) >= M_READ && $document->getLatestContent()) { - $tasks['review'][] = array('id'=>$res['id'], 'name'=>$res['name']); + if($workflowmode == 'traditional') { + $resArr = $dms->getDocumentList('ReviewByMe', $user); + if($resArr) { + $docs = array(); + foreach ($resArr as $res) { + $document = $dms->getDocument($res["id"]); + if($document->getAccessMode($user) >= M_READ && $document->getLatestContent()) { + $docs[] = $document; +// $tasks['review'][] = array('id'=>$res['id'], 'name'=>$res['name']); + } } + if($this->hasHook('filterReviewTaskList')) + $docs = $this->callHook('filterReviewTaskList', $docs); + foreach($docs as $doc) + $tasks['review'][] = array('id'=>$doc->getId(), 'name'=>$doc->getName()); } } } elseif($workflowmode == 'advanced') { $resArr = $dms->getDocumentList('WorkflowByMe', $user); if($resArr) { + $docs = array(); foreach ($resArr as $res) { $document = $dms->getDocument($res["id"]); if($document->getAccessMode($user) >= M_READ && $document->getLatestContent()) { - $tasks['workflow'][] = array('id'=>$res['id'], 'name'=>$res['name']); + $docs[] = $document; +// $tasks['workflow'][] = array('id'=>$res['id'], 'name'=>$res['name']); } } + if($this->hasHook('filterWorkflowTaskList')) + $docs = $this->callHook('filterWorkflowTaskList', $docs); + foreach($docs as $doc) + $tasks['workflow'][] = array('id'=>$doc->getId(), 'name'=>$doc->getName()); } } return $tasks; @@ -228,8 +247,9 @@ class SeedDMS_View_Tasks extends SeedDMS_Bootstrap_Style { $cachedir = $this->params['cachedir']; $previewwidth = $this->params['previewWidthList']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout, $xsendfile); $content = ''; $foldercount = $doccount = 0; if($clipboard['folders']) { diff --git a/views/bootstrap/class.Timeline.php b/views/bootstrap/class.Timeline.php index 578309311..ef38cd66d 100644 --- a/views/bootstrap/class.Timeline.php +++ b/views/bootstrap/class.Timeline.php @@ -44,6 +44,7 @@ class SeedDMS_View_Timeline extends SeedDMS_Bootstrap_Style { $previewwidthlist = $this->params['previewWidthList']; $previewwidthdetail = $this->params['previewWidthDetail']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; if($document && $version) { // $this->contentHeading(getMLText("timeline_selected_item")); @@ -54,7 +55,7 @@ class SeedDMS_View_Timeline extends SeedDMS_Bootstrap_Style { print "\n"; print "\n"; print "\n\n\n"; - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidthdetail, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidthdetail, $timeout, $xsendfile); echo $this->documentListRow($document, $previewer); echo "\n
        ".getMLText("status")."".getMLText("action")."
        \n"; diff --git a/views/bootstrap/class.TriggerWorkflow.php b/views/bootstrap/class.TriggerWorkflow.php index 05db1cc1b..b9a89bbd5 100644 --- a/views/bootstrap/class.TriggerWorkflow.php +++ b/views/bootstrap/class.TriggerWorkflow.php @@ -76,11 +76,6 @@ $(document).ready(function() { $this->contentStart(); $this->pageNavigation($this->getFolderPathHTML($folder, true, $document), "view_document", $document); $this->contentHeading(getMLText("trigger_workflow")); -?> - - -getAction(); $currentstate = $latestContent->getWorkflowState(); @@ -125,7 +120,7 @@ $(document).ready(function() {
        - +
        params['user']; $seluser = $this->params['seluser']; $quota = $this->params['quota']; - $workflowmode = $this->params['workflowmode']; $undeluserids = $this->params['undeluserids']; $enableemail = $this->params['enableemail']; diff --git a/views/bootstrap/class.ViewDocument.php b/views/bootstrap/class.ViewDocument.php index 8b7e178ab..413f2c775 100644 --- a/views/bootstrap/class.ViewDocument.php +++ b/views/bootstrap/class.ViewDocument.php @@ -186,7 +186,10 @@ class SeedDMS_View_ViewDocument extends SeedDMS_Bootstrap_Style { header('Content-Type: application/javascript'); if($user->isAdmin()) { - $this->printTimelineJs('out.ViewDocument.php?action=timelinedata&documentid='.$document->getID(), 300, '', date('Y-m-d')); + $latestContent = $this->callHook('documentLatestContent', $document); + if($latestContent === null) + $latestContent = $document->getLatestContent(); + $this->printTimelineJs('out.ViewDocument.php?action=timelinedata&documentid='.$latestContent->getDocument()->getID(), 300, '', date('Y-m-d')); } $this->printDocumentChooserJs("form1"); $this->printDeleteDocumentButtonJs(); @@ -330,6 +333,7 @@ class SeedDMS_View_ViewDocument extends SeedDMS_Bootstrap_Style { $dms = $this->params['dms']; $document = $this->params['document']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; $showfullpreview = $this->params['showFullPreview']; $converttopdf = $this->params['convertToPdf']; $pdfconverters = $this->params['pdfConverters']; @@ -337,7 +341,9 @@ class SeedDMS_View_ViewDocument extends SeedDMS_Bootstrap_Style { if(!$showfullpreview) return; - $latestContent = $document->getLatestContent(); + $latestContent = $this->callHook('documentLatestContent', $document); + if($latestContent === null) + $latestContent = $document->getLatestContent(); $txt = $this->callHook('preDocumentPreview', $latestContent); if(is_string($txt)) echo $txt; @@ -353,7 +359,7 @@ class SeedDMS_View_ViewDocument extends SeedDMS_Bootstrap_Style { $this->contentHeading(getMLText("preview")); ?> setConverters($pdfconverters); if($pdfpreviewer->hasConverter($latestContent->getMimeType())) { $this->contentHeading(getMLText("preview_pdf")); @@ -406,6 +412,9 @@ class SeedDMS_View_ViewDocument extends SeedDMS_Bootstrap_Style { function show() { /* {{{ */ parent::show(); + + $this->callHook('preViewDocument'); + $dms = $this->params['dms']; $user = $this->params['user']; $folder = $this->params['folder']; @@ -422,8 +431,11 @@ class SeedDMS_View_ViewDocument extends SeedDMS_Bootstrap_Style { $documentid = $document->getId(); $currenttab = $this->params['currenttab']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; - $versions = $document->getContent(); + $versions = $this->callHook('documentVersions', $document); + if($versions === null) + $versions = $document->getContent(); $this->htmlAddHeader(''."\n", 'js'); $this->htmlAddHeader(''."\n", 'css'); @@ -450,7 +462,9 @@ class SeedDMS_View_ViewDocument extends SeedDMS_Bootstrap_Style { } /* Retrieve latest content and attacheѕ files */ - $latestContent = $document->getLatestContent(); + $latestContent = $this->callHook('documentLatestContent', $document); + if($latestContent === null) + $latestContent = $document->getLatestContent(); $files = $document->getDocumentFiles($latestContent->getVersion()); $files = SeedDMS_Core_DMS::filterDocumentFiles($user, $files); @@ -485,6 +499,9 @@ class SeedDMS_View_ViewDocument extends SeedDMS_Bootstrap_Style {
        callHook('startLeftColumn', $document); + if(is_string($txt)) + echo $txt; $this->documentInfos(); $this->preview(); ?> @@ -559,11 +576,11 @@ class SeedDMS_View_ViewDocument extends SeedDMS_Bootstrap_Style { print "
      "; */ - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidthdetail, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidthdetail, $timeout, $xsendfile); $previewer->setConverters($previewconverters); $previewer->createPreview($latestContent); if ($file_exists) { - if ($viewonlinefiletypes && in_array(strtolower($latestContent->getFileType()), $viewonlinefiletypes)) { + if ($viewonlinefiletypes && (in_array(strtolower($latestContent->getFileType()), $viewonlinefiletypes) || in_array(strtolower($latestContent->getMimeType()), $viewonlinefiletypes))) { print "getVersion()."\">"; } else { print "getVersion()."\">"; @@ -621,7 +638,7 @@ class SeedDMS_View_ViewDocument extends SeedDMS_Bootstrap_Style { print ""; @@ -956,9 +973,9 @@ class SeedDMS_View_ViewDocument extends SeedDMS_Bootstrap_Style { $this->contentContainerStart(); if($user->isAdmin()) { if(SeedDMS_Core_DMS::checkIfEqual($workflow->getInitState(), $latestContent->getWorkflowState())) { - print "
      ".createHiddenFieldWithKey('removeworkflowfromdocument')."getVersion()."\" />
      "; + print "
      getVersion()."\" />
      "; } else { - print "
      ".createHiddenFieldWithKey('rewindworkflow')."getVersion()."\" />
      "; + print "
      getVersion()."\" />
      "; } } @@ -1058,7 +1075,7 @@ class SeedDMS_View_ViewDocument extends SeedDMS_Bootstrap_Style { echo ""; if($latestContent->triggerWorkflowTransitionIsAllowed($user, $transition)) { $action = $transition->getAction(); - print "
      ".createHiddenFieldWithKey('triggerworkflow')."getVersion()."\" />getID()."\" />getName()), array(), $action->getName())."\" />
      "; + print "
      getVersion()."\" />getID()."\" />getName()), array(), $action->getName())."\" />
      "; $allowedtransitions[] = $transition; } echo ""; @@ -1077,7 +1094,7 @@ class SeedDMS_View_ViewDocument extends SeedDMS_Bootstrap_Style { } } if($subworkflows) { - echo "
      ".createHiddenFieldWithKey('runsubworkflow')."getVersion()."\" />"; + echo "getVersion()."\" />"; echo "getVersion()."\" />"; + echo "getVersion()."\" />"; echo ""; echo "
      "; } else { @@ -1124,7 +1141,7 @@ class SeedDMS_View_ViewDocument extends SeedDMS_Bootstrap_Style { foreach($transitions as $transition) { if($latestContent->triggerWorkflowTransitionIsAllowed($user, $transition)) { echo "Triggering transition is allowed
      "; - echo "
      ".createHiddenFieldWithKey('returnfromsubworkflow')."getVersion()."\" />getID()."\" />"; + echo "getVersion()."\" />getID()."\" />"; echo ""; echo "
      "; @@ -1177,7 +1194,7 @@ class SeedDMS_View_ViewDocument extends SeedDMS_Bootstrap_Style { print "\n"; print ""; if($file_exists) { - if ($viewonlinefiletypes && in_array(strtolower($version->getFileType()), $viewonlinefiletypes)) { + if ($viewonlinefiletypes && (in_array(strtolower($version->getFileType()), $viewonlinefiletypes) || in_array(strtolower($version->getMimeType()), $viewonlinefiletypes))) { print "getVersion()."\">"; } else { print "getVersion()."\">"; @@ -1222,7 +1239,7 @@ class SeedDMS_View_ViewDocument extends SeedDMS_Bootstrap_Style { print ""; print "
    isAdmin()) { - $timeline = $document->getTimeline(); + $timeline = $latestContent->getDocument()->getTimeline(); if($timeline) { $this->contentHeading(getMLText("timeline")); foreach($timeline as &$item) { @@ -1473,7 +1490,7 @@ class SeedDMS_View_ViewDocument extends SeedDMS_Bootstrap_Style { $msg = getMLText('timeline_'.$item['type'], array('document'=>$item['document']->getName(), 'version'=> $item['version'], 'status'=> getOverallStatusText($item['status']))); break; default: - $msg = $this->callHook('getTimelineMsg', $document, $item); + $msg = $this->callHook('getTimelineMsg', $latestContent->getDocument(), $item); if(!is_string($msg)) $msg = '???'; } diff --git a/views/bootstrap/class.ViewFolder.php b/views/bootstrap/class.ViewFolder.php index 91173fdeb..88b80a07c 100644 --- a/views/bootstrap/class.ViewFolder.php +++ b/views/bootstrap/class.ViewFolder.php @@ -90,6 +90,7 @@ class SeedDMS_View_ViewFolder extends SeedDMS_Bootstrap_Style { $expandFolderTree = $this->params['expandFolderTree']; $enableDropUpload = $this->params['enableDropUpload']; $maxItemsPerPage = $this->params['maxItemsPerPage']; + $showtree = $this->params['showtree']; header('Content-Type: application/javascript; charset=UTF-8'); parent::jsTranslations(array('cancel', 'splash_move_document', 'confirm_move_document', 'move_document', 'splash_move_folder', 'confirm_move_folder', 'move_folder')); @@ -134,7 +135,8 @@ $('#loadmore').click(function(e) { }); printNewTreeNavigationJs($folder->getID(), M_READ, 0, '', $expandFolderTree == 2, $orderby); + if($showtree == 1) + $this->printNewTreeNavigationJs($folder->getID(), M_READ, 0, '', ($expandFolderTree == 1) ? -1 : 3, $orderby); if ($enableDropUpload && $folder->getAccessMode($user) >= M_READWRITE) { echo "SeedDMSUpload.setUrl('../op/op.Ajax.php');"; @@ -157,12 +159,13 @@ $('#loadmore').click(function(e) { $previewwidth = $this->params['previewWidthList']; $previewconverters = $this->params['previewConverters']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; $offset = $this->params['offset']; $limit = $this->params['limit']; header('Content-Type: application/json'); - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout, $xsendfile); $previewer->setConverters($previewconverters); $subFolders = $this->callHook('folderGetSubFolders', $folder, $orderby); @@ -237,6 +240,7 @@ $('#loadmore').click(function(e) { $previewwidth = $this->params['previewWidthList']; $previewconverters = $this->params['previewConverters']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; $folderid = $folder->getId(); @@ -254,7 +258,7 @@ $('#loadmore').click(function(e) { $this->pageNavigation($this->getFolderPathHTML($folder), "view_folder", $folder); } - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout, $xsendfile); $previewer->setConverters($previewconverters); echo $this->callHook('preContent'); @@ -279,7 +283,7 @@ $('#loadmore').click(function(e) { * access expandFolderTree with $this->params because it can * be changed by preContent hook. */ - $this->printNewTreeNavigationHtml($folderid, M_READ, 0, '', $this->params['expandFolderTree'] == 2, $orderby); + $this->printNewTreeNavigationHtml($folderid, M_READ, 0, '', ($this->params['expandFolderTree'] == 1) ? -1 : 3, $orderby); $this->contentContainerEnd(); } else { $this->contentHeading("", true); diff --git a/views/bootstrap/class.WorkflowActionsMgr.php b/views/bootstrap/class.WorkflowActionsMgr.php index 3b833ff46..5963025e1 100644 --- a/views/bootstrap/class.WorkflowActionsMgr.php +++ b/views/bootstrap/class.WorkflowActionsMgr.php @@ -100,18 +100,34 @@ $(document).ready( function() { } } /* }}} */ + function actionmenu() { /* {{{ */ + $dms = $this->params['dms']; + $user = $this->params['user']; + $selworkflowaction = $this->params['selworkflowaction']; + + if($selworkflowaction && !$selworkflowaction->isUsed()) { +?> +
    + + + + + +
    +isUsed()) { $this->infoMsg(getMLText('workflow_action_in_use')); - } else { -?> -
    - - - -
    - @@ -169,8 +185,7 @@ $(document).ready( function() {
    - contentContainerStart(); ?> -
    + getID(), htmlspecialchars($currWorkflowAction->getName()), $selworkflowaction && $currWorkflowAction->getID()==$selworkflowaction->getID()); } $this->formField( - getMLText("selection"), + null, //getMLText("selection"), array( 'element'=>'select', 'id'=>'selector', + 'class'=>'chzn-select', 'options'=>$options ) ); ?> -
    - contentContainerEnd(); ?> + +
    getID()."\"" : "") ?>>
    getID()."\"" : "") ?>>
    diff --git a/views/bootstrap/class.WorkflowGraph.php b/views/bootstrap/class.WorkflowGraph.php index d4d7daa72..f9b5cbd0c 100644 --- a/views/bootstrap/class.WorkflowGraph.php +++ b/views/bootstrap/class.WorkflowGraph.php @@ -154,7 +154,7 @@ cy.on('tap', 'node', function(evt) { var scratch = node.scratch('app'); if(typeof scratch !== 'undefined') { noty({ - text: (scratch.users ? '

    : ' + scratch.users + '

    ' : '') + (scratch.groups ? ': ' + scratch.groups + '

    ' : ''), + text: (scratch.users ? '

    ' ?> ' + scratch.users + '

    ' : '') + (scratch.groups ? ' ' ?> ' + scratch.groups + '

    ' : ''), type: 'information', dismissQueue: true, layout: 'topCenter', @@ -217,7 +217,7 @@ $(document).ready(function() { $transusers = $transition->getUsers(); $unames = array(); foreach($transusers as $transuser) { - $unames[] = $transuser->getUser()->getFullName(); + $unames[] = $transuser->getUser()->getLogin().' - '.$transuser->getUser()->getFullName(); } $transgroups = $transition->getGroups(); $gnames = array(); diff --git a/views/bootstrap/class.WorkflowMgr.php b/views/bootstrap/class.WorkflowMgr.php index 685495b1b..b0de06218 100644 --- a/views/bootstrap/class.WorkflowMgr.php +++ b/views/bootstrap/class.WorkflowMgr.php @@ -73,13 +73,39 @@ $(document).ready(function() { $dms = $this->params['dms']; $user = $this->params['user']; $selworkflow = $this->params['selworkflow']; - if($selworkflow) { ?> + if($selworkflow && $selworkflow->getTransitions()) { ?>
    params['dms']; + $user = $this->params['user']; + $selworkflow = $this->params['selworkflow']; + $workflows = $this->params['allworkflows']; + $workflowstates = $this->params['allworkflowstates']; + + if($selworkflow && !$selworkflow->isUsed()) { +?> +
    + + + + + +
    +params['dms']; $user = $this->params['user']; @@ -137,26 +163,16 @@ $(document).ready(function() { contentContainerStart(); ?>
    - - -isUsed()) { -?> -
    - -
    formField( @@ -214,12 +230,12 @@ $(document).ready(function() { echo ""; foreach($transusers as $transuser) { $u = $transuser->getUser(); - echo getMLText('user').": ".$u->getFullName(); + echo ' '.htmlspecialchars($u->getLogin()." - ".$u->getFullName()); echo "
    "; } foreach($transgroups as $transgroup) { $g = $transgroup->getGroup(); - echo getMLText('at_least_n_users_of_group', + echo ' '.getMLText('at_least_n_users_of_group', array("number_of_users" => $transgroup->getNumOfUsers(), "group" => $g->getName())); echo "
    "; @@ -318,8 +334,7 @@ $(document).ready(function() {
    - contentContainerStart(); ?> - + getID(), htmlspecialchars($currWorkflow->getName()),$selworkflow && $currWorkflow->getID()==$selworkflow->getID()); } $this->formField( - getMLText("selection"), + null, //getMLText("selection"), array( 'element'=>'select', 'id'=>'selector', + 'class'=>'chzn-select', 'options'=>$options ) ); ?> - - contentContainerEnd(); ?> -
    getID()."\"" : "") ?>>
    + +
    getID()."\"" : "") ?>>
    +
    getID()."\"" : "") ?>>
    diff --git a/views/bootstrap/class.WorkflowStatesMgr.php b/views/bootstrap/class.WorkflowStatesMgr.php index 1781a966e..ea30447b5 100644 --- a/views/bootstrap/class.WorkflowStatesMgr.php +++ b/views/bootstrap/class.WorkflowStatesMgr.php @@ -101,18 +101,34 @@ $(document).ready(function() { } } /* }}} */ + function actionmenu() { /* {{{ */ + $dms = $this->params['dms']; + $user = $this->params['user']; + $selworkflowstate = $this->params['selworkflowstate']; + + if($selworkflowstate && !$selworkflowstate->isUsed()) { +?> +
    + + + + + +
    +isUsed()) { $this->infoMsg(getMLText('workflow_state_in_use')); - } else { -?> -
    - - - -
    - @@ -182,8 +198,7 @@ $(document).ready(function() {
    - contentContainerStart(); ?> -
    + getID(), htmlspecialchars($currWorkflowState->getName()), $selworkflowstate && $currWorkflowState->getID()==$selworkflowstate->getID()); } $this->formField( - getMLText("selection"), + null, //getMLText("selection"), array( 'element'=>'select', 'id'=>'selector', + 'class'=>'chzn-select', 'options'=>$options ) ); ?> -
    - contentContainerEnd(); ?> + +
    getID()."\"" : "") ?>>
    getID()."\"" : "") ?>>
    diff --git a/views/bootstrap/class.WorkflowSummary.php b/views/bootstrap/class.WorkflowSummary.php index 1f9408d98..d0711044a 100644 --- a/views/bootstrap/class.WorkflowSummary.php +++ b/views/bootstrap/class.WorkflowSummary.php @@ -42,6 +42,7 @@ class SeedDMS_View_WorkflowSummary extends SeedDMS_Bootstrap_Style { $cachedir = $this->params['cachedir']; $previewwidth = $this->params['previewWidthList']; $timeout = $this->params['timeout']; + $xsendfile = $this->params['xsendfile']; $this->htmlStartPage(getMLText("my_documents")); $this->globalNavigation(); @@ -54,7 +55,7 @@ class SeedDMS_View_WorkflowSummary extends SeedDMS_Bootstrap_Style { // Get document list for the current user. $workflowStatus = $user->getWorkflowStatus(); - $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout); + $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout, $xsendfile); $printheader=true; $iRev = array();