├── LICENSE ├── Makefile ├── _build.sh ├── bower.json ├── composer.json ├── karma.conf.js ├── package.json ├── phpunit.xml.dist ├── src ├── CmfTreeBrowserBundle.php ├── DependencyInjection │ ├── CmfTreeBrowserExtension.php │ └── Configuration.php ├── Description │ └── IconEnhancer.php ├── Form │ └── Type │ │ └── TreeSelectType.php └── Resources │ ├── assets │ ├── css │ │ └── fontawesome-style.css │ └── js │ │ ├── adapter │ │ └── fancytree.js │ │ ├── jquery.cmf_context_menu.js │ │ └── jquery.cmf_tree.js │ ├── config │ └── services.xml │ ├── meta │ └── LICENSE │ ├── public │ ├── css │ │ └── cmf_tree_browser.fancytree.css │ ├── img │ │ ├── 31fff8ba5fc319adf944c4e61ba1479b.gif │ │ ├── 4f2a6ae3a4a188d3fe875d12128792b8.gif │ │ ├── 55bf3587e165200ca5895d89c967cd69.gif │ │ └── bbd31d4bb16ad743558c721f51b16345.gif │ ├── js │ │ └── cmf_tree_browser.fancytree.js │ └── vendor │ │ ├── jquery-ui │ │ └── jquery-ui.min.js │ │ └── jquery │ │ └── dist │ │ └── jquery.min.js │ ├── translations │ ├── CmfTreeBrowserBundle.en.xlf │ ├── CmfTreeBrowserBundle.fr.xlf │ └── CmfTreeBrowserBundle.nl.xlf │ └── views │ ├── Base │ ├── scripts.html.twig │ └── tree.html.twig │ └── Form │ └── fields.html.twig ├── tests ├── Unit │ └── Form │ │ └── Type │ │ └── TreeSelectTypeTest.php ├── js │ ├── adapter │ │ └── fancytreeSpec.js │ ├── cmfContextMenuSpec.js │ └── cmfTreeSpec.js └── tests.cmf_tree_browser.js ├── travis.php.ini └── webpack.config.js /LICENSE: -------------------------------------------------------------------------------- 1 | TreeBrowserBundle 2 | 3 | The MIT License 4 | 5 | Copyright (c) 2011-2012 Symfony2 CMF 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ####################################################### 2 | # DO NOT EDIT THIS FILE! # 3 | # # 4 | # It's auto-generated by symfony-cmf/dev-kit package. # 5 | ####################################################### 6 | 7 | ############################################################################ 8 | # This file is part of the Symfony CMF package. # 9 | # # 10 | # (c) 2011-2017 Symfony CMF # 11 | # # 12 | # For the full copyright and license information, please view the LICENSE # 13 | # file that was distributed with this source code. # 14 | ############################################################################ 15 | 16 | TESTING_SCRIPTS_DIR=vendor/symfony-cmf/testing/bin 17 | CONSOLE=${TESTING_SCRIPTS_DIR}/console 18 | VERSION=dev-master 19 | ifdef BRANCH 20 | VERSION=dev-${BRANCH} 21 | endif 22 | PACKAGE=symfony-cmf/tree-browser-bundle 23 | list: 24 | @echo 'test: will run all tests' 25 | @echo 'unit_tests: will run unit tests only' 26 | 27 | 28 | @echo 'test_installation: will run installation test' 29 | include ${TESTING_SCRIPTS_DIR}/make/unit_tests.mk 30 | include ${TESTING_SCRIPTS_DIR}/make/test_installation.mk 31 | 32 | .PHONY: test 33 | test: unit_tests 34 | -------------------------------------------------------------------------------- /_build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | MODE=$1||development 5 | 6 | echo " * Installing Bower dependencies..." 7 | bower install 8 | 9 | echo "" 10 | echo " * Executing webpack..." 11 | # Compile all javascript files and minify them together with Fancytree 12 | webpack --mode ${MODE} -p --progress 13 | 14 | echo "" 15 | echo " * Copying required vendor files to public directory..." 16 | # jQuery 17 | if [ ! -d "./src/Resources/public/vendor/jquery" ]; then 18 | mkdir -p ./src/Resources/public/vendor/jquery/dist 19 | fi 20 | cp ./bower_components/jquery/dist/jquery.min.js ./src/Resources/public/vendor/jquery/dist/jquery.min.js 21 | 22 | # jQuery UI 23 | if [ ! -d "./src/Resources/public/vendor/jquery-ui" ]; then 24 | mkdir ./src/Resources/public/vendor/jquery-ui 25 | fi 26 | cp ./bower_components/jquery-ui/jquery-ui.min.js ./src/Resources/public/vendor/jquery-ui/jquery-ui.min.js 27 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "symfony-cmf-tree-browser-bundle", 3 | "homepage": "http://cmf.symfony.com", 4 | "keywords": ["Symfony CMF", "tree", "phpcr"], 5 | "authors": [ 6 | { 7 | "name": "Symfony CMF Community", 8 | "homepage": "https://github.com/symfony-cmf/TreeBrowserBundle/contributors" 9 | } 10 | ], 11 | "license": "MIT", 12 | "dependencies": { 13 | "fancytree": "2.21.*" 14 | }, 15 | "private": true, 16 | "ignore": ["*"] 17 | } 18 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "symfony-cmf/tree-browser-bundle", 3 | "type": "symfony-bundle", 4 | "description": "Symfony CMF Tree Browser Bundle", 5 | "keywords": [ 6 | "Symfony CMF", 7 | "tree", 8 | "phpcr" 9 | ], 10 | "homepage": "http://cmf.symfony.com", 11 | "license": "MIT", 12 | "authors": [ 13 | { 14 | "name": "Symfony CMF Community", 15 | "homepage": "https://github.com/symfony-cmf/TreeBrowserBundle/contributors" 16 | } 17 | ], 18 | "require": { 19 | "php": "^7.1", 20 | "symfony-cmf/resource-rest-bundle": "^1.0" 21 | }, 22 | "require-dev": { 23 | "symfony/form": "^2.8 || ^3.3 || ^4.0", 24 | "symfony-cmf/testing": "^2.1.8", 25 | "symfony/phpunit-bridge": "^4.2.2" 26 | }, 27 | "autoload": { 28 | "psr-4": { 29 | "Symfony\\Cmf\\Bundle\\TreeBrowserBundle\\": "src" 30 | } 31 | }, 32 | "autoload-dev": { 33 | "psr-4": { 34 | "Symfony\\Cmf\\Bundle\\TreeBrowserBundle\\Tests\\": "tests" 35 | } 36 | }, 37 | "extra": { 38 | "branch-alias": { 39 | "dev-master": "2.1-dev" 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var webpackConfig = require('./webpack.config.js'); 3 | webpackConfig.devtool = 'inline-source-map'; 4 | webpackConfig.resolve.alias.bundle = path.resolve(__dirname, 'src/Resources/assets/js'); 5 | 6 | 7 | module.exports = function(config) { 8 | config.set({ 9 | 10 | // base path that will be used to resolve all patterns (eg. files, exclude) 11 | basePath: '', 12 | 13 | 14 | // frameworks to use 15 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 16 | frameworks: ['jasmine'], 17 | 18 | 19 | // list of files / patterns to load in the browser 20 | files: [ 21 | // vendors 22 | 'bower_components/jquery/dist/jquery.js', 23 | 'bower_components/jquery-ui/jquery-ui.js', 24 | 25 | // jasmine helpers 26 | 'node_modules/jasmine-jquery/lib/jasmine-jquery.js', 27 | 'node_modules/jasmine-ajax/lib/mock-ajax.js', 28 | 29 | // specs 30 | 'tests/tests.cmf_tree_browser.js' 31 | ], 32 | 33 | 34 | // list of files to exclude 35 | exclude: ['*.swp', '*~'], 36 | 37 | 38 | // preprocess matching files before serving them to the browser 39 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 40 | preprocessors: { 41 | 'tests/tests.cmf_tree_browser.js': ['webpack', 'sourcemap'] 42 | }, 43 | 44 | 45 | // test results reporter to use 46 | // possible values: 'dots', 'progress' 47 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 48 | reporters: ['dots'], 49 | 50 | webpack: webpackConfig, 51 | webpackMiddleware: {stats: 'errors-only'}, 52 | 53 | // web server port 54 | port: 9876, 55 | 56 | // enable / disable colors in the output (reporters and logs) 57 | colors: true, 58 | 59 | 60 | // level of logging 61 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 62 | logLevel: config.LOG_INFO, 63 | 64 | 65 | // enable / disable watching file and executing tests whenever any file changes 66 | autoWatch: true, 67 | 68 | 69 | // start these browsers 70 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 71 | browsers: ['Chrome'],//, 'Firefox', 'IE'], 72 | 73 | 74 | // Continuous Integration mode 75 | // if true, Karma captures browsers, runs the tests and exits 76 | singleRun: false 77 | }); 78 | }; 79 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "symfony-cmf-tree-browser-bundle", 3 | "license": "MIT", 4 | "devDependencies": { 5 | "babel-core": "^6.26.3", 6 | "babel-loader": "^7.1.4", 7 | "babel-preset-env": "^1.7.0", 8 | "babel-preset-es2015": "^6.24.1", 9 | "core-js": "^1.2.6", 10 | "css-loader": "^0.23.0", 11 | "eslint": "^4.19.1", 12 | "extract-text-webpack-plugin": "^4.0.0-beta.0", 13 | "file-loader": "^0.8.5", 14 | "jasmine-ajax": "^3.1.0", 15 | "jasmine-core": "^2.2.0", 16 | "jasmine-jquery": "^2.0.6", 17 | "karma": "^2.0.4", 18 | "karma-chrome-launcher": "^0.1.7", 19 | "karma-firefox-launcher": "^0.1.4", 20 | "karma-ie-launcher": "^0.1.5", 21 | "karma-jasmine": "^0.3.5", 22 | "karma-phantomjs-launcher": "^1.0.4", 23 | "karma-sourcemap-loader": "^0.3.7", 24 | "karma-webpack": "^3.0.0", 25 | "style-loader": "^0.13.2", 26 | "webpack": "^4.0.1", 27 | "webpack-cli": "^3.0.8", 28 | "webpack-dev-middleware": "^2.0.6" 29 | }, 30 | "scripts": { 31 | "pretravis:install": "npm install -g bower && npm set progress=false", 32 | "travis:install": "npm install && bower install", 33 | "test": "\"node_modules/karma/bin/karma\" start --single-run --browsers PhantomJS", 34 | "build:dev": "sh _build.sh development", 35 | "build:prod": "sh _build.sh production" 36 | }, 37 | "repository": { 38 | "type": "git", 39 | "url": "https://github.com/symfony-cmf/TreeBrowserBundle.git" 40 | }, 41 | "homepage": "https://github.com/symfony-cmf/TreeBrowserBundle" 42 | } 43 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 11 | ./tests/Unit 12 | 13 | 14 | 15 | 16 | 17 | src 18 | 19 | Resources/ 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/CmfTreeBrowserBundle.php: -------------------------------------------------------------------------------- 1 | getParameter('kernel.bundles'); 28 | 29 | if (!isset($bundles['TwigBundle'])) { 30 | return; 31 | } 32 | 33 | $container->prependExtensionConfig('twig', [ 34 | 'form_themes' => [ 35 | '@CmfTreeBrowser/Form/fields.html.twig', 36 | ], 37 | ]); 38 | } 39 | 40 | /** 41 | * {@inheritdoc} 42 | */ 43 | public function load(array $configs, ContainerBuilder $container) 44 | { 45 | $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); 46 | $loader->load('services.xml'); 47 | 48 | $config = $this->processConfiguration(new Configuration(), $configs); 49 | $container->setParameter('cmf_tree_browser.description.icon_map', $config['icons']); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/DependencyInjection/Configuration.php: -------------------------------------------------------------------------------- 1 | root('cmf_tree_browser'); 23 | 24 | $rootNode 25 | ->children() 26 | ->arrayNode('icons') 27 | ->useAttributeAsKey('class') 28 | ->prototype('scalar')->end() 29 | ->info('A mapping of classes/interfaces and icon classes or icon URLs used by the tree browser.') 30 | ->end() 31 | ->end() 32 | ; 33 | 34 | return $treeBuilder; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Description/IconEnhancer.php: -------------------------------------------------------------------------------- 1 | 23 | */ 24 | class IconEnhancer implements DescriptionEnhancerInterface 25 | { 26 | private $iconMap; 27 | 28 | private $classMap = []; 29 | 30 | public function __construct(array $iconMap) 31 | { 32 | $this->iconMap = $iconMap; 33 | } 34 | 35 | public function enhance(Description $description) 36 | { 37 | $class = get_class($description->getResource()->getPayload()); 38 | if (isset($this->classMap[$class])) { 39 | $class = $this->classMap[$class]; 40 | } 41 | 42 | $description->set('icon', $this->iconMap[$class]); 43 | } 44 | 45 | public function supports(PuliResource $resource) 46 | { 47 | if (!$resource instanceof CmfResource) { 48 | return false; 49 | } 50 | 51 | $payload = $resource->getPayload(); 52 | $payloadClass = get_class($payload); 53 | 54 | if (isset($this->iconMap[$payloadClass]) || isset($this->classMap[$payloadClass])) { 55 | return true; 56 | } 57 | 58 | foreach (array_keys($this->iconMap) as $class) { 59 | if (is_a($payload, $class) || is_subclass_of($payload, $class)) { 60 | $this->classMap[$payloadClass] = $class; 61 | 62 | return true; 63 | } 64 | } 65 | 66 | return false; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Form/Type/TreeSelectType.php: -------------------------------------------------------------------------------- 1 | 32 | */ 33 | class TreeSelectType extends AbstractType 34 | { 35 | public function buildView(FormView $view, FormInterface $form, array $options) 36 | { 37 | parent::buildView($view, $form, $options); 38 | 39 | $view->vars['type'] = ('compact' === $options['widget']) ? 'text' : 'hidden'; 40 | $view->vars['widget'] = $options['widget']; 41 | $view->vars['root_node'] = $options['root_node']; 42 | $view->vars['repository_name'] = $options['repository_name']; 43 | } 44 | 45 | public function configureOptions(OptionsResolver $resolver) 46 | { 47 | $resolver->setDefault('widget', 'compact'); 48 | $resolver->setAllowedValues('widget', ['browser', 'compact']); 49 | 50 | $resolver->setDefault('root_node', '/'); 51 | $resolver->setAllowedValues('root_node', function ($value) { 52 | return '/' === $value[0]; 53 | }); 54 | 55 | $resolver->setDefault('repository_name', 'default'); 56 | } 57 | 58 | public function getBlockPrefix() 59 | { 60 | return 'cmf_tree_select'; 61 | } 62 | 63 | public function getParent() 64 | { 65 | return TextType::class; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Resources/assets/css/fontawesome-style.css: -------------------------------------------------------------------------------- 1 | ul.fancytree-container { 2 | font-family: 'Source Sans Pro', sans-serif; 3 | font-size: 14px; 4 | border: none; 5 | } 6 | ul.fancytree-container:focus { 7 | outline:none; 8 | } 9 | .fancytree-loading span.fancytree-expander, 10 | .fancytree-loading span.fancytree-expander:hover { 11 | background: initial; 12 | } 13 | 14 | .fancytree-loading span.fancytree-expander:before, 15 | .fancytree-loading span.fancytree-expander:hover:before, 16 | .fancytree-statusnode-wait span.fancytree-icon:before, 17 | .fancytree-statusnode-wait span.fancytree-icon:hover:before{ 18 | font-family: FontAwesome; 19 | content: ' \f110'; 20 | -webkit-animation: fa-spin 2s infinite linear; 21 | animation: fa-spin 2s infinite linear; 22 | } 23 | 24 | @-webkit-keyframes fa-spin { 25 | 0% { 26 | -webkit-transform: rotate(0deg); 27 | transform: rotate(0deg); 28 | } 29 | 100% { 30 | -webkit-transform: rotate(359deg); 31 | transform: rotate(359deg); 32 | } 33 | } 34 | @keyframes fa-spin { 35 | 0% { 36 | -webkit-transform: rotate(0deg); 37 | transform: rotate(0deg); 38 | } 39 | 100% { 40 | -webkit-transform: rotate(359deg); 41 | transform: rotate(359deg); 42 | } 43 | } 44 | 45 | .fancytree-container .fancytree-icon { 46 | background: initial !important; 47 | } 48 | .fancytree-container .fancytree-icon:before { 49 | display: inline-block; 50 | font-family: FontAwesome; 51 | font-style: normal; 52 | font-weight: normal; 53 | font-size: 14px; 54 | line-height: 1; 55 | color: #333; 56 | -webkit-font-smoothing: antialiased; 57 | -moz-osx-font-smoothing: grayscale; 58 | } 59 | .fancytree-node .fancytree-icon:before { 60 | content: " \f016"; /* fa-file-o */ 61 | } 62 | .fancytree-expanded .fancytree-icon:before, 63 | .fancytree-folder .fancytree-icon:before { 64 | content: " \f07b"; /* fa-folder */ 65 | } 66 | 67 | .fancytree-statusnode-wait .fancytree-icon:before { 68 | content: ""; 69 | } 70 | -------------------------------------------------------------------------------- /src/Resources/assets/js/adapter/fancytree.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Symfony CMF package. 3 | * 4 | * (c) 2011-2017 Symfony CMF 5 | * 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | import Map from 'core-js/es6/map' 11 | import '../jquery.cmf_context_menu' 12 | import 'fancytree/src/jquery.fancytree.js' 13 | import 'fancytree/src/jquery.fancytree.dnd.js' 14 | import 'fancytree/skin-win8/ui.fancytree.css' 15 | import '../../css/fontawesome-style.css' 16 | 17 | var cache = new Map(); 18 | 19 | function getPropertyFromString(name, list) { 20 | var isOptional = name.substr(0, 1) === '?'; 21 | var nameWithoutPrefix = (isOptional ? name.substr(1) : name); 22 | 23 | if (undefined === list[nameWithoutPrefix]) { 24 | if (isOptional) { 25 | return undefined; 26 | } 27 | 28 | throw 'Attribute "' + props[prop] + '" does not exists'; 29 | } 30 | 31 | return list[nameWithoutPrefix]; 32 | } 33 | 34 | /** 35 | * A tree browser adapter for the Fancytree library. 36 | * 37 | * @author Wouter J 38 | * @see https://github.com/mar10/fancytree 39 | */ 40 | export class FancytreeAdapter { 41 | constructor(options) { 42 | if (!window.jQuery || !jQuery.fn.fancytree) { 43 | throw 'The FancytreeAdapter requires both jQuery and the FancyTree library.'; 44 | } 45 | 46 | if (!options.request) { 47 | throw 'The FancytreeAdapter requires a request option.'; 48 | } 49 | 50 | this.requestData = options.request; 51 | this.rootNode = options.root_node || '/'; 52 | this.useCache = undefined === options.use_cache ? true : options.use_cache; 53 | this.boundToInput = false; 54 | this.sortableBy = undefined == options.sortableBy ? false : options.sortableBy; 55 | 56 | if (options.dnd && undefined == options.dnd.enabled) { 57 | options.dnd.enabled = true; 58 | } 59 | var alwaysTrueFunction = () => { return true }; 60 | this.dndOptions = jQuery.extend({ 61 | enabled: false, 62 | isNodeDraggable: alwaysTrueFunction, 63 | nodeAcceptsDraggable: alwaysTrueFunction 64 | }, options.dnd); 65 | 66 | if (this.dndOptions.enabled && !options.request.move) { 67 | throw 'The move request needs to be configured when drag \'n drop is enabled, pass it using the `request.move` option.'; 68 | } 69 | this.dndOptions.request = options.request.move; 70 | 71 | // available actions (array) 72 | this.actions = new Array(); 73 | // the Fancytree instance (FancytreeTree) 74 | this.tree = null; 75 | // the tree element (jQuery) 76 | this.$tree = null; 77 | // a map of path and related keys 78 | this.pathKeyMap = {}; 79 | } 80 | 81 | bindToElement($elem) { 82 | if (this.$tree) { 83 | throw 'Cannot bind to multiple elements.'; 84 | } 85 | 86 | if (!$elem instanceof jQuery) { 87 | throw 'FancytreeAdapter can only be adapted to a jQuery object.'; 88 | } 89 | 90 | this.$tree = $elem; 91 | var actions = this.actions; 92 | var parseUrl = function (url, node) { 93 | if (typeof url == 'object' && url.hasOwnProperty('data')) { 94 | return getPropertyFromString(url.data, node.descriptors); 95 | } 96 | 97 | if (typeof url == 'function') { 98 | return url(requestNode); 99 | } 100 | 101 | if (typeof url == 'string') { 102 | return url; 103 | } 104 | }; 105 | var requestNodeToFancytreeNode = (requestNode) => { 106 | if (requestNode.length === 0) { 107 | return; 108 | } 109 | 110 | if ('//' == requestNode.path || '/' == requestNode.path) { 111 | return requestNodeToFancytreeNode(requestNode.children[Object.keys(requestNode.children)[0]]); 112 | } 113 | 114 | var refPath = requestNode.path.replace('\/', '/').replace('//', '/'); 115 | var key = this.pathKeyMap[refPath] || "" + jQuery.ui.fancytree._nextNodeKey++; 116 | var fancytreeNode = { 117 | title: requestNode.label, 118 | key: key, 119 | children: [], 120 | actions: {}, 121 | refPath: refPath, 122 | type: requestNode.payload_type, 123 | unselectable: true 124 | }; 125 | 126 | this.pathKeyMap[refPath] = key; 127 | 128 | if (requestNode.descriptors.hasOwnProperty('icon')) { 129 | fancytreeNode.icon = requestNode.descriptors.icon; 130 | } 131 | 132 | if(requestNode.descriptors.hasOwnProperty('position')) { 133 | fancytreeNode.position = requestNode.descriptors.position; 134 | } 135 | 136 | for (let actionName in actions) { 137 | var action = actions[actionName]; 138 | var url = parseUrl(action.url, requestNode); 139 | 140 | if (url === undefined) { 141 | continue; 142 | } 143 | fancytreeNode['actions'][actionName] = { label: actionName, iconClass: action.icon, url: url }; 144 | } 145 | 146 | var childrenCount = 0; 147 | for (name in requestNode.children) { 148 | if (!requestNode.children.hasOwnProperty(name)) { 149 | continue; 150 | } 151 | 152 | var child = requestNodeToFancytreeNode(requestNode.children[name]); 153 | if (child) { 154 | fancytreeNode.children.push(child); 155 | } 156 | childrenCount++; 157 | } 158 | 159 | if (0 != childrenCount) { 160 | fancytreeNode.folder = true; 161 | fancytreeNode.lazy = true; 162 | 163 | if (0 === fancytreeNode.children.length) { 164 | fancytreeNode.children = null; 165 | } 166 | } 167 | 168 | return fancytreeNode; 169 | }; 170 | 171 | var requestData = this.requestData; 172 | var useCache = this.useCache; 173 | var fancytreeOptions = { 174 | // the start data (root node + children) 175 | source: (useCache && cache.has(this.rootNode)) ? cache.get(this.rootNode) : requestData.load(this.rootNode), 176 | 177 | // lazy load the children when a node is collapsed 178 | lazyLoad: function (event, data) { 179 | var path = data.node.data.refPath; 180 | if (useCache && cache.has(path)) { 181 | data.result = cache.get(path); 182 | } else { 183 | var loadData = requestData.load(path); 184 | 185 | if (Array.isArray(loadData)) { 186 | data.result = loadData; 187 | } else { 188 | data.result = jQuery.extend({ 189 | data: {} 190 | }, loadData); 191 | } 192 | } 193 | }, 194 | 195 | // transform the JSON response into a data structure that's supported by FancyTree 196 | postProcess: function (event, data) { 197 | if (data.hasOwnProperty('error') && null != data.error) { 198 | data.result = { 199 | // todo: maybe use a more admin friendly error message in prod? 200 | error: 'An error occured while retrieving the nodes: ' + data.error 201 | }; 202 | 203 | return; 204 | } 205 | 206 | let result = requestNodeToFancytreeNode(data.response); 207 | let nodeIsDuplicate = function (node, parentPath) { 208 | return parentPath == node.refPath; 209 | }; 210 | 211 | if (nodeIsDuplicate(result, data.node.data.refPath)) { 212 | result = result.children; 213 | } else { 214 | result = [result]; 215 | } 216 | 217 | if (result.length == 1 && undefined !== result[0].folder) { 218 | result[0].expanded = true; 219 | } 220 | 221 | data.result = result; 222 | if (useCache) { 223 | cache.set(data.node.data.refPath, result); 224 | } 225 | }, 226 | 227 | // always show the active node 228 | activeVisible: true 229 | }; 230 | 231 | if (this.sortableBy) { 232 | fancytreeOptions.sortChildren = (a, b) => { 233 | var current = a.data[this.sortableBy]; 234 | var next = b.data[this.sortableBy]; 235 | if (current == next) { 236 | return 0; 237 | } else if (current < next) { 238 | return -1; 239 | } else { 240 | return 1; 241 | } 242 | }; 243 | } 244 | 245 | if (this.dndOptions.enabled) { 246 | fancytreeOptions.extensions = ['dnd']; 247 | fancytreeOptions.dnd = { 248 | dragStart: (node, data) => { 249 | return this.dndOptions.isNodeDraggable(node, data); 250 | }, 251 | dragEnter: (node, data) => { 252 | return this.dndOptions.nodeAcceptsDraggable(node, data); 253 | }, 254 | dragExpand: (node, data) => { 255 | return true; 256 | }, 257 | dragDrop: (node, data) => { 258 | let dropedNode = data.otherNode; 259 | let dropedAtNode = data.node; 260 | 261 | let dropNodePath = dropedNode.data.refPath; 262 | let dropedAtPath = dropedAtNode.data.refPath; 263 | let positionBefore = 'over' != data.hitMode && 'child' != data.hitMode; 264 | let parentNode = positionBefore ? dropedAtNode.parent : dropedAtNode; 265 | let parenPath = parentNode.data.refPath; 266 | let targetPath = parenPath + '/' + dropNodePath.substr(1 + dropNodePath.lastIndexOf('/')); 267 | 268 | let formerIcon = dropedNode.icon; 269 | 270 | let moveNodeInTree = (responseData) => { 271 | dropedNode.remove(); 272 | if (positionBefore) { 273 | parentNode.children.forEach((node) => { 274 | if (node.data.position >= responseData.descriptors.position) { 275 | node.data.position++; 276 | } 277 | }); 278 | } 279 | parentNode.addChildren(requestNodeToFancytreeNode(responseData)); 280 | }; 281 | 282 | let setIcon = (nodeToSetOn, icon) => { 283 | nodeToSetOn.icon = icon; 284 | dropedNode.renderTitle(); 285 | }; 286 | 287 | setIcon(dropedNode, 'fa fa-spinner fa-spin') 288 | 289 | let onError = (jqxhr) => { 290 | let message = 'Failed to move node'; 291 | let formerLabel = dropedNode.title; 292 | if (jqxhr.hasOwnProperty('responseJSON') && jqxhr.responseJSON.hasOwnProperty('message')) { 293 | message += ': ' + jqxhr.responseJSON.message; 294 | } 295 | let details = null; 296 | if (jqxhr.hasOwnProperty('responseJSON')) { 297 | details = jqxhr.responseJSON; 298 | } 299 | dropedNode._error = { message: message, details: details}; 300 | dropedNode.renderStatus(); 301 | 302 | dropedNode.title += '[' + message + ']'; 303 | dropedNode.renderTitle(); 304 | 305 | console.error(message); 306 | setIcon(dropedNode, formerIcon); 307 | 308 | setTimeout(function () { 309 | dropedNode._error = null; 310 | dropedNode.title = formerLabel; 311 | dropedNode.renderTitle(); 312 | dropedNode.renderStatus(); 313 | }, 1000); 314 | }; 315 | this.requestData.move(dropNodePath, targetPath).done((responseData) => { 316 | if (positionBefore && this.dndOptions.reorder) { 317 | this.requestData.reorder(parenPath, dropedAtPath, targetPath, data.hitMode).done((responseData) => { 318 | moveNodeInTree(responseData); 319 | if (fancytreeOptions.hasOwnProperty('sortChildren')) { 320 | parentNode.sortChildren(fancytreeOptions.sortChildren, true); 321 | } 322 | setIcon(dropedNode, formerIcon); 323 | }).fail( (jqxhr) => { 324 | onError(jqxhr); 325 | setTimeout(() => { 326 | this.requestData.move(targetPath, dropNodePath).done((responseData) => { 327 | if (fancytreeOptions.hasOwnProperty('sortChildren')) { 328 | parentNode.sortChildren(fancytreeOptions.sortChildren, true); 329 | } 330 | setIcon(dropedNode, formerIcon); 331 | }); 332 | }, 1000); 333 | 334 | }); 335 | } else { 336 | dropedNode.icon = formerIcon; 337 | moveNodeInTree(responseData); 338 | } 339 | }).fail(onError); 340 | } 341 | }; 342 | } 343 | 344 | this.$tree.fancytree(fancytreeOptions); 345 | 346 | if (this.actions) { 347 | this.$tree.cmfContextMenu({ 348 | delegate: 'span.fancytree-title', 349 | wrapperTemplate: '', 350 | actionTemplate: '
  • {{ label }}
  • ', 351 | actions: function ($node) { 352 | return jQuery.ui.fancytree.getNode($node).data.actions; 353 | } 354 | }); 355 | } 356 | 357 | this.tree = this.$tree.fancytree('getTree'); 358 | 359 | this.tree.getNodeByRefPath = function (refPath) { 360 | return this.findFirst((node) => { 361 | return node.data.refPath == refPath; 362 | }); 363 | }; 364 | 365 | // We do not want to do anything on activation atm. 366 | this.$tree.fancytree('option', 'activate', (event, data) => { 367 | if (!this.boundToInput) { 368 | data.node.setActive(false); 369 | data.node.setFocus(false); 370 | } 371 | }); 372 | } 373 | 374 | bindToInput($input) { 375 | this.boundToInput = true; 376 | 377 | // output active node to input field 378 | this.$tree.fancytree('option', 'activate', (event, data) => { 379 | $input.val(data.node.data.refPath); 380 | }); 381 | 382 | var showPath = (path) => { 383 | if (!this.pathKeyMap.hasOwnProperty(path)) { 384 | var parts = path.split('/'); 385 | 386 | while (!this.pathKeyMap.hasOwnProperty(parts.join('/')) && parts.pop()); 387 | 388 | if (parts.length === 0) { 389 | return; 390 | } 391 | 392 | var loadedPath = parts.join('/'); 393 | var pathsToLoad = path.substr(loadedPath.length + 1).split('/'); 394 | 395 | pathsToLoad.forEach((pathToLoad) => { 396 | this.pathKeyMap[loadedPath += '/' + pathToLoad] = "" + jQuery.ui.fancytree._nextNodeKey++; 397 | }); 398 | } 399 | 400 | this.tree.loadKeyPath(generateKeyPath(path), function (node, status) { 401 | if ('ok' == status) { 402 | node.setExpanded(); 403 | node.setActive(); 404 | } 405 | }); 406 | }; 407 | var generateKeyPath = (path) => { 408 | var keyPath = ''; 409 | var refPath = ''; 410 | var subPaths = path.split('/'); 411 | 412 | subPaths.forEach((subPath) => { 413 | if (subPath == '' || !this.pathKeyMap.hasOwnProperty(refPath += '/' + subPath)) { 414 | return; 415 | } 416 | 417 | keyPath += '/' + this.pathKeyMap[refPath]; 418 | }); 419 | 420 | return keyPath; 421 | }; 422 | 423 | // use initial input value as active node 424 | this.$tree.bind('fancytreeinit', function (event, data) { 425 | showPath($input.val()); 426 | }); 427 | 428 | // change active node when the value of the input field changed 429 | $input.on('change', function (e) { 430 | showPath($(this).val()); 431 | }); 432 | } 433 | 434 | addAction(name, url, icon) { 435 | this.actions[name] = { url: url, icon: icon }; 436 | } 437 | 438 | static _resetCache() { 439 | cache.clear(); 440 | } 441 | } 442 | -------------------------------------------------------------------------------- /src/Resources/assets/js/jquery.cmf_context_menu.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Symfony CMF package. 3 | * 4 | * (c) 2011-2017 Symfony CMF 5 | * 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | import jQuery from 'jquery'; 11 | 12 | /** 13 | * A very flexible and simple jQuery context menu plugin. 14 | * 15 | * @author Wouter J 16 | */ 17 | jQuery.fn.cmfContextMenu = function (options) { 18 | var options = jQuery.extend({ 19 | /** 20 | * The selector used to delegate the contextmenu event too. 21 | * 22 | * $('#tree').cmfContextMenu({ delegate: '.hasMenu' }) 23 | * 24 | * Will delegate the contextmenu event to all `.hasMenu` 25 | * childs in `#tree`. 26 | * 27 | * @var string|null 28 | */ 29 | delegate: null, 30 | 31 | /** 32 | * A list of actions in the context menu or a callback. 33 | * 34 | * In case of a callback, it will be called with the target 35 | * element. This means the action list can be build dynamically 36 | * based on the target. 37 | * 38 | * The contextmenu will not be shown if this list is empty or if 39 | * the callback returned `false`. 40 | * 41 | * @var object|function 42 | */ 43 | actions: [], 44 | 45 | /** 46 | * A callback that's called when an action is selected. 47 | * 48 | * The callback will be provided with the element the contextmenu was 49 | * bound to and the click event. 50 | * 51 | * @var function 52 | */ 53 | select: function ($action, event) { }, 54 | 55 | /** 56 | * The template to use for the wrapper element. 57 | * 58 | * @var string 59 | */ 60 | wrapperTemplate: '
      ', 61 | 62 | /** 63 | * The template to use for each action element. 64 | * 65 | * You can include vars with the `{{ varName }}` syntax. The available 66 | * vars are the properties of the action object set in `actions`. 67 | * 68 | * @var string 69 | */ 70 | actionTemplate: '
    • {{ label }}
    • ' 71 | }, options); 72 | 73 | var $body = jQuery('body'); 74 | var $menu; 75 | 76 | // respond to right click 77 | jQuery(this).on('contextmenu', options.delegate, function (e) { 78 | e.preventDefault(); 79 | 80 | var $target = jQuery(this); 81 | 82 | // remove already shown menu 83 | $menu && $menu.remove(); 84 | 85 | // generate actions 86 | var actions = options.actions; 87 | if (typeof actions === 'function') { 88 | actions = actions($target); 89 | } 90 | 91 | if (false === actions || jQuery.isEmptyObject(actions)) { 92 | return; 93 | } 94 | 95 | // generate the menu element 96 | $menu = (function () { 97 | var $wrapper = jQuery(options.wrapperTemplate); 98 | var $menu = $wrapper.is('ul') ? $wrapper : $wrapper.find('ul'); 99 | for (var cmd in actions) { 100 | var action = actions[cmd]; 101 | var $action = jQuery((function () { 102 | var tmp = options.actionTemplate; 103 | for (var prop in action) { 104 | if (!action.hasOwnProperty(prop)) { 105 | continue; 106 | } 107 | 108 | tmp = tmp.replace('{{ ' + prop + ' }}', action[prop]); 109 | } 110 | 111 | return tmp; 112 | })()); 113 | 114 | $action.data('cmd', cmd); 115 | 116 | $menu.append($action); 117 | } 118 | 119 | return $wrapper; 120 | })(); 121 | 122 | // align it on the page 123 | $menu.css({ 124 | top: e.pageY, 125 | left: e.pageX 126 | }); 127 | 128 | $body.append($menu); 129 | 130 | var select = options.select; 131 | // respond to a click on an action 132 | $menu.on('click', 'li', function (e) { 133 | e.stopPropagation(); 134 | 135 | select($target, e); 136 | }); 137 | }); 138 | 139 | // when clicked anywhere outside of the contextmenu, hide the menu 140 | jQuery('html').on('click', function (e) { 141 | $menu && $menu.remove(); 142 | }); 143 | }; 144 | -------------------------------------------------------------------------------- /src/Resources/assets/js/jquery.cmf_tree.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Symfony CMF package. 3 | * 4 | * (c) 2011-2017 Symfony CMF 5 | * 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | import jQuery from 'jquery'; 11 | import {FancytreeAdapter} from './adapter/fancytree'; 12 | 13 | /** 14 | * A simple layer between the jQuery front-end and the JS tree library used. 15 | * 16 | * By default, it uses the FancytreeAdapter. You can pass other adapters by 17 | * changing the `adapter` setting. 18 | * 19 | * @author Wouter J 20 | */ 21 | jQuery.fn.cmfTree = function (options) { 22 | options = jQuery.extend({ 23 | adapter: null, 24 | request: { 25 | load: null 26 | }, 27 | actions: {} 28 | }, options); 29 | 30 | // configure options 31 | var $treeOutput = jQuery(this); 32 | var selectElement = function (selector) { 33 | if ('string' == typeof(selector)) { 34 | return jQuery(selector); 35 | } else if (selector instanceof jQuery) { 36 | return selector; 37 | } 38 | 39 | throw 'Cannot handle selector ' + selector + '. You may want to pass a jQuery object or a jQuery selector.'; 40 | }; 41 | 42 | if (!options.request.load) { 43 | throw 'cmfTree needs an AJAX URL to lazy load the tree, pass it using the `request.load` option.'; 44 | } 45 | 46 | if (!options.adapter) { 47 | options.adapter = new FancytreeAdapter(options); 48 | } 49 | var adapter = options.adapter; 50 | 51 | if (!adapter.bindToElement) { 52 | throw 'cmfTree adapters must have a bindToElement() method to specify the output element of the tree.'; 53 | } 54 | 55 | for (let actionName in options.actions) { 56 | if (!options.actions.hasOwnProperty(actionName)) { 57 | continue; 58 | } 59 | 60 | if (!adapter.addAction) { 61 | throw 'The configured cmfTree adapter does not support actions, implement the addAction() method or use another adapter.'; 62 | } 63 | var action = options.actions[actionName]; 64 | 65 | if (!action.url) { 66 | throw 'actions should have a url defined, "' + actionName + '" does not.'; 67 | } 68 | 69 | adapter.addAction(actionName, action.url, action.icon); 70 | } 71 | 72 | // render tree 73 | adapter.bindToElement($treeOutput); 74 | 75 | // optionally bind the tree to an input element 76 | if (options.path_output) { 77 | if (!adapter.bindToInput) { 78 | throw 'The configured cmfTree adapter does not support binding to an input field, implement the bindToInput() method or use another adapter.'; 79 | } 80 | 81 | adapter.bindToInput(selectElement(options.path_output)); 82 | } 83 | 84 | return adapter; 85 | }; 86 | -------------------------------------------------------------------------------- /src/Resources/config/services.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 10 | %cmf_tree_browser.description.icon_map% 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/Resources/meta/LICENSE: -------------------------------------------------------------------------------- 1 | Symfony Cmf Tree Browser Bundle 2 | 3 | The MIT License 4 | 5 | Copyright (c) 2011-2017 Symfony CMF 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /src/Resources/public/css/cmf_tree_browser.fancytree.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Fancytree "Win8" skin. 3 | * 4 | * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from 5 | * the LESS templates. 6 | */.ui-helper-hidden{display:none}ul.fancytree-container{font-family:tahoma,arial,helvetica;font-size:10pt;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;min-height:0;position:relative}ul.fancytree-container ul{padding:0 0 0 16px;margin:0}ul.fancytree-container ul>li:before{content:none}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}ul.fancytree-connectors.fancytree-container li{background-image:url("data:image/gif;base64,R0lGODlhEAAQAPcAAAAAANPT0wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAQABAAAAgxAP8JHPgvAMGDCA0iXFiQ4UKFDglCjChwIkWLETE61MiQ40OKEkEO9JhQZEWTDRcGBAA7");background-position:0 0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio,span.fancytree-vline{width:16px;height:16px;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-position:0;background-image:url(../img/31fff8ba5fc319adf944c4e61ba1479b.gif);background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio{margin-top:2px}span.fancytree-custom-icon{width:16px;height:16px;display:inline-block;margin-left:3px;background-position:0 0}img.fancytree-icon{width:16px;height:16px;margin-left:3px;margin-top:2px;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-nl span.fancytree-expander,.fancytree-exp-n span.fancytree-expander{background-image:none;cursor:default}.fancytree-connectors .fancytree-exp-nl span.fancytree-expander,.fancytree-connectors .fancytree-exp-n span.fancytree-expander{background-image:url(../img/31fff8ba5fc319adf944c4e61ba1479b.gif);margin-top:0}.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-connectors .fancytree-exp-n span.fancytree-expander:hover{background-position:0 -64px}.fancytree-connectors .fancytree-exp-nl span.fancytree-expander,.fancytree-connectors .fancytree-exp-nl span.fancytree-expander:hover{background-position:-16px -64px}.fancytree-exp-c span.fancytree-expander{background-position:0 -80px}.fancytree-exp-c span.fancytree-expander:hover{background-position:-16px -80px}.fancytree-exp-cl span.fancytree-expander{background-position:0 -96px}.fancytree-exp-cl span.fancytree-expander:hover{background-position:-16px -96px}.fancytree-exp-cd span.fancytree-expander{background-position:-64px -80px}.fancytree-exp-cd span.fancytree-expander:hover{background-position:-80px -80px}.fancytree-exp-cdl span.fancytree-expander{background-position:-64px -96px}.fancytree-exp-cdl span.fancytree-expander:hover{background-position:-80px -96px}.fancytree-exp-ed span.fancytree-expander,.fancytree-exp-e span.fancytree-expander{background-position:-32px -80px}.fancytree-exp-ed span.fancytree-expander:hover,.fancytree-exp-e span.fancytree-expander:hover{background-position:-48px -80px}.fancytree-exp-edl span.fancytree-expander,.fancytree-exp-el span.fancytree-expander{background-position:-32px -96px}.fancytree-exp-edl span.fancytree-expander:hover,.fancytree-exp-el span.fancytree-expander:hover{background-position:-48px -96px}.fancytree-fade-expander span.fancytree-expander{transition:opacity 1.5s;opacity:0}.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander:hover span.fancytree-expander,.fancytree-fade-expander [class*=fancytree-statusnode-] span.fancytree-expander{transition:opacity .6s;opacity:1}span.fancytree-checkbox{margin-left:3px;background-position:0 -32px}span.fancytree-checkbox:hover{background-position:-16px -32px}.fancytree-partsel span.fancytree-checkbox{background-position:-64px -32px}.fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -32px}.fancytree-selected span.fancytree-checkbox{background-position:-32px -32px}.fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -32px}.fancytree-unselectable span.fancytree-checkbox{opacity:.4;filter:alpha(opacity=40)}.fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -32px}.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover{background-position:-64px -32px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover{background-position:-32px -32px}.fancytree-radio span.fancytree-checkbox{background-position:0 -48px}.fancytree-radio span.fancytree-checkbox:hover{background-position:-16px -48px}.fancytree-radio .fancytree-partsel span.fancytree-checkbox{background-position:-64px -48px}.fancytree-radio .fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -48px}.fancytree-radio .fancytree-selected span.fancytree-checkbox{background-position:-32px -48px}.fancytree-radio .fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -48px}.fancytree-radio .fancytree-unselectable span.fancytree-checkbox,.fancytree-radio .fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -48px}span.fancytree-icon{margin-left:3px;background-position:0 0}.fancytree-ico-c span.fancytree-icon:hover{background-position:-16px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon{background-position:-32px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover{background-position:-48px 0}.fancytree-ico-e span.fancytree-icon{background-position:-64px 0}.fancytree-ico-e span.fancytree-icon:hover{background-position:-80px 0}.fancytree-ico-cf span.fancytree-icon{background-position:0 -16px}.fancytree-ico-cf span.fancytree-icon:hover{background-position:-16px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon{background-position:-32px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover{background-position:-48px -16px}.fancytree-ico-ef span.fancytree-icon{background-position:-64px -16px}.fancytree-ico-ef span.fancytree-icon:hover{background-position:-80px -16px}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-loading span.fancytree-icon,.fancytree-statusnode-loading span.fancytree-icon:hover{background-image:url("data:image/gif;base64,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");background-position:0 0}.fancytree-statusnode-error span.fancytree-icon,.fancytree-statusnode-error span.fancytree-icon:hover{background-position:0 -112px}span.fancytree-node{display:inherit;width:100%;margin-top:0;min-height:20px}span.fancytree-title{color:#000;cursor:pointer;display:inline-block;vertical-align:top;min-height:20px;padding:0 3px;margin:0 0 0 3px;border:1px solid transparent;border-radius:0}span.fancytree-node.fancytree-error span.fancytree-title{color:red}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:none;font-weight:bolder}div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img{background-position:-32px -112px}div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img{background-position:-16px -112px}#fancytree-drop-marker{width:32px;position:absolute;background-position:0 -128px;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:64px;background-position:0 -144px}#fancytree-drop-marker.fancytree-drop-copy{background-position:-64px -128px}#fancytree-drop-marker.fancytree-drop-move{background-position:-32px -128px}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}.fancytree-container.fancytree-rtl #fancytree-drop-marker,.fancytree-container.fancytree-rtl span.fancytree-connector,.fancytree-container.fancytree-rtl span.fancytree-drag-helper-img,.fancytree-container.fancytree-rtl span.fancytree-expander,.fancytree-container.fancytree-rtl span.fancytree-icon{background-image:url(../img/bbd31d4bb16ad743558c721f51b16345.gif)}.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander,.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander{background-image:none}.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-nl span.fancytree-expander,.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-n span.fancytree-expander{background-image:url(../img/bbd31d4bb16ad743558c721f51b16345.gif)}ul.fancytree-container.fancytree-rtl ul{padding:0 16px 0 0}ul.fancytree-container.fancytree-rtl.fancytree-connectors li{background-position:right 0;background-image:url(../img/4f2a6ae3a4a188d3fe875d12128792b8.gif)}ul.fancytree-container.fancytree-rtl.fancytree-no-connector>li,ul.fancytree-container.fancytree-rtl li.fancytree-lastsib{background-image:none}table.fancytree-ext-table{border-collapse:collapse}table.fancytree-ext-table span.fancytree-node{display:inline-block;box-sizing:border-box}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#cbe8f6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px;background-position:0 -80px}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover{background-position:-16px -80px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander{visibility:hidden}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander{visibility:visible}.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{min-width:100%;box-sizing:border-box}ul.fancytree-ext-wide,ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;min-width:100%;margin-left:0;margin-right:0;box-sizing:border-box}.fancytree-ext-fixed-wrapper .fancytree-fixed-hidden{display:none}.fancytree-ext-fixed-wrapper div.scrollBorderBottom{border-bottom:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.scrollBorderRight{border-right:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-fixed-wrapper-tl{position:absolute;overflow:hidden;z-index:3;top:0;left:0}.fancytree-ext-fixed-wrapper div.fancytree-fixed-wrapper-tr{position:absolute;overflow:hidden;z-index:2;top:0}.fancytree-ext-fixed-wrapper div.fancytree-fixed-wrapper-bl{position:absolute;overflow:hidden;z-index:2;left:0}.fancytree-ext-fixed-wrapper div.fancytree-fixed-wrapper-br{position:absolute;overflow:scroll;z-index:1}.fancytree-plain span.fancytree-title{border:1px solid transparent}.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-focused span.fancytree-title{border-color:#39f}.fancytree-plain span.fancytree-active span.fancytree-title,.fancytree-plain span.fancytree-selected span.fancytree-title{background-color:#f7f7f7;border-color:#dedede}.fancytree-plain span.fancytree-node span.fancytree-selected span.fancytree-title{font-style:italic}.fancytree-plain span.fancytree-node:hover span.fancytree-title{background-color:#eff9fe;border-color:#70c0e7}.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-active span.fancytree-title,.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-selected span.fancytree-title{background-color:#cbe8f6;border-color:#26a0da}table.fancytree-ext-table tbody tr td{border:1px solid #ededed}table.fancytree-ext-table tbody span.fancytree-node,table.fancytree-ext-table tbody span.fancytree-node:hover{border:none;background:none}table.fancytree-ext-table tbody tr:hover{background-color:#e5f3fb;outline:1px solid #70c0e7}table.fancytree-ext-table tbody tr.fancytree-focused span.fancytree-title{outline:1px dotted #000}table.fancytree-ext-table tbody tr.fancytree-active:hover,table.fancytree-ext-table tbody tr.fancytree-selected:hover{background-color:#cbe8f6;outline:1px solid #26a0da}table.fancytree-ext-table tbody tr.fancytree-active{background-color:#f7f7f7;outline:1px solid #dedede}table.fancytree-ext-table tbody tr.fancytree-selected{background-color:#f7f7f7}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active{background-color:#cbe8f6;outline:1px solid #26a0da}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected{background-color:#cbe8f6}ul.fancytree-container{font-family:Source Sans Pro,sans-serif;font-size:14px;border:none}ul.fancytree-container:focus{outline:none}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover{background:initial}.fancytree-loading span.fancytree-expander:before,.fancytree-loading span.fancytree-expander:hover:before,.fancytree-statusnode-wait span.fancytree-icon:before,.fancytree-statusnode-wait span.fancytree-icon:hover:before{font-family:FontAwesome;content:" \F110";-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fancytree-container .fancytree-icon{background:initial!important}.fancytree-container .fancytree-icon:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:400;font-size:14px;line-height:1;color:#333;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fancytree-node .fancytree-icon:before{content:" \F016"}.fancytree-expanded .fancytree-icon:before,.fancytree-folder .fancytree-icon:before{content:" \F07B"}.fancytree-statusnode-wait .fancytree-icon:before{content:""} -------------------------------------------------------------------------------- /src/Resources/public/img/31fff8ba5fc319adf944c4e61ba1479b.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/symfony-cmf/tree-browser-bundle/fbcfd36bffbfb5acaff3d3e02714f7993d520b23/src/Resources/public/img/31fff8ba5fc319adf944c4e61ba1479b.gif -------------------------------------------------------------------------------- /src/Resources/public/img/4f2a6ae3a4a188d3fe875d12128792b8.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/symfony-cmf/tree-browser-bundle/fbcfd36bffbfb5acaff3d3e02714f7993d520b23/src/Resources/public/img/4f2a6ae3a4a188d3fe875d12128792b8.gif -------------------------------------------------------------------------------- /src/Resources/public/img/55bf3587e165200ca5895d89c967cd69.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/symfony-cmf/tree-browser-bundle/fbcfd36bffbfb5acaff3d3e02714f7993d520b23/src/Resources/public/img/55bf3587e165200ca5895d89c967cd69.gif -------------------------------------------------------------------------------- /src/Resources/public/img/bbd31d4bb16ad743558c721f51b16345.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/symfony-cmf/tree-browser-bundle/fbcfd36bffbfb5acaff3d3e02714f7993d520b23/src/Resources/public/img/bbd31d4bb16ad743558c721f51b16345.gif -------------------------------------------------------------------------------- /src/Resources/public/js/cmf_tree_browser.fancytree.js: -------------------------------------------------------------------------------- 1 | !function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=53)}([function(e,t,n){var r=n(49)("wks"),i=n(14),o=n(2).Symbol;e.exports=function(e){return r[e]||(r[e]=o&&o[e]||(o||i)("Symbol."+e))}},function(e,t,n){var r=n(3),i=n(23);e.exports=n(13)?function(e,t,n){return r.setDesc(e,t,i(1,n))}:function(e,t,n){return e[t]=n,e}},function(e,t){var n=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=n)},function(e,t){var n=Object;e.exports={create:n.create,getProto:n.getPrototypeOf,isEnum:{}.propertyIsEnumerable,getDesc:n.getOwnPropertyDescriptor,setDesc:n.defineProperty,setDescs:n.defineProperties,getKeys:n.keys,getNames:n.getOwnPropertyNames,getSymbols:n.getOwnPropertySymbols,each:[].forEach}},function(e,t){e.exports={}},function(e,t,n){var r=n(2),i=n(1),o=n(14)("src"),a=Function.toString,s=(""+a).split("toString");n(6).inspectSource=function(e){return a.call(e)},(e.exports=function(e,t,n,a){"function"==typeof n&&(n.hasOwnProperty(o)||i(n,o,e[t]?""+e[t]:s.join(String(t))),n.hasOwnProperty("name")||i(n,"name",t)),e===r?e[t]=n:(a||delete e[t],i(e,t,n))})(Function.prototype,"toString",function(){return"function"==typeof this&&this[o]||a.call(this)})},function(e,t){var n=e.exports={version:"1.2.6"};"number"==typeof __e&&(__e=n)},function(e,t){e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},function(e,t,n){var r=n(3).setDesc,i=n(9),o=n(0)("toStringTag");e.exports=function(e,t,n){e&&!i(e=n?e:e.prototype,o)&&r(e,o,{configurable:!0,value:t})}},function(e,t){var n={}.hasOwnProperty;e.exports=function(e,t){return n.call(e,t)}},function(e,t,n){var r=n(45);e.exports=function(e,t,n){if(r(e),void 0===t)return e;switch(n){case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,i){return e.call(t,n,r,i)}}return function(){return e.apply(t,arguments)}}},function(e,t,n){"use strict";var r=n(46),i=n(20),o=n(5),a=n(1),s=n(9),l=n(4),d=n(44),c=n(8),u=n(3).getProto,h=n(0)("iterator"),f=!([].keys&&"next"in[].keys()),p=function(){return this};e.exports=function(e,t,n,g,v,y,b){d(n,t,g);var m,x,_=function(e){if(!f&&e in S)return S[e];switch(e){case"keys":case"values":return function(){return new n(this,e)}}return function(){return new n(this,e)}},k=t+" Iterator",N="values"==v,w=!1,S=e.prototype,C=S[h]||S["@@iterator"]||v&&S[v],E=C||_(v);if(C){var T=u(E.call(new e));c(T,k,!0),!r&&s(S,"@@iterator")&&a(T,h,p),N&&"values"!==C.name&&(w=!0,E=function(){return C.call(this)})}if(r&&!b||!f&&!w&&S[h]||a(S,h,E),l[t]=E,l[k]=p,v)if(m={values:N?E:_("values"),keys:y?E:_("keys"),entries:N?_("entries"):E},b)for(x in m)x in S||o(S,x,m[x]);else i(i.P+i.F*(f||w),t,m);return m}},function(e,t){e.exports=function(e){if(void 0==e)throw TypeError("Can't call method on "+e);return e}},function(e,t,n){e.exports=!n(22)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(e,t){var n=0,r=Math.random();e.exports=function(e){return"Symbol(".concat(void 0===e?"":e,")_",(++n+r).toString(36))}},function(e,t,n){var r=n(7);e.exports=function(e){if(!r(e))throw TypeError(e+" is not an object!");return e}},function(e,t,n){var r=n(10),i=n(36),o=n(35),a=n(15),s=n(34),l=n(33);e.exports=function(e,t,n,d){var c,u,h,f=l(e),p=r(n,d,t?2:1),g=0;if("function"!=typeof f)throw TypeError(e+" is not iterable!");if(o(f))for(c=s(e.length);c>g;g++)t?p(a(u=e[g])[0],u[1]):p(e[g]);else for(h=f.call(e);!(u=h.next()).done;)i(h,p,u.value,t)}},function(e,t){e.exports=function(e,t,n){if(!(e instanceof t))throw TypeError(n+": use the 'new' operator!");return e}},function(e,t,n){var r=n(5);e.exports=function(e,t){for(var n in t)r(e,n,t[n]);return e}},function(e,t){e.exports=function(e,t){return{value:t,done:!!e}}},function(e,t,n){var r=n(2),i=n(6),o=n(1),a=n(5),s=n(10),l=function(e,t,n){var d,c,u,h,f=e&l.F,p=e&l.G,g=e&l.S,v=e&l.P,y=e&l.B,b=p?r:g?r[t]||(r[t]={}):(r[t]||{}).prototype,m=p?i:i[t]||(i[t]={}),x=m.prototype||(m.prototype={});for(d in p&&(n=t),n)u=((c=!f&&b&&d in b)?b:n)[d],h=y&&c?s(u,r):v&&"function"==typeof u?s(Function.call,u):u,b&&!c&&a(b,d,u),m[d]!=u&&o(m,d,h),v&&x[d]!=u&&(x[d]=u)};r.core=i,l.F=1,l.G=2,l.S=4,l.P=8,l.B=16,l.W=32,e.exports=l},function(e,t){var n=Math.ceil,r=Math.floor;e.exports=function(e){return isNaN(e=+e)?0:(e>0?r:n)(e)}},function(e,t){e.exports=function(e){try{return!!e()}catch(e){return!0}}},function(e,t){e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},function(e,t){var n={}.toString;e.exports=function(e){return n.call(e).slice(8,-1)}},function(e,t,n){var r=n(24),i=n(0)("toStringTag"),o="Arguments"==r(function(){return arguments}());e.exports=function(e){var t,n,a;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(n=(t=Object(e))[i])?n:o?r(t):"Object"==(a=r(t))&&"function"==typeof t.callee?"Arguments":a}},function(e,t){e.exports=jQuery},function(e,t,n){"use strict"; 2 | /*! 3 | * jquery.fancytree.dnd.js 4 | * 5 | * Drag-and-drop support (jQuery UI draggable/droppable). 6 | * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/) 7 | * 8 | * Copyright (c) 2008-2017, Martin Wendt (http://wwWendt.de) 9 | * 10 | * Released under the MIT license 11 | * https://github.com/mar10/fancytree/wiki/LicenseInfo 12 | * 13 | * @version 2.21.0 14 | * @date 2017-01-15T17:21:28Z 15 | */!function(e,t,n,r){var i=!1;function o(t){var n=t.options.dnd||null,r=t.options.glyph||null;n&&(i||(e.ui.plugin.add("draggable","connectToFancytree",{start:function(t,n){var r=e(this).data("ui-draggable")||e(this).data("draggable"),i=n.helper.data("ftSourceNode")||null;if(i)return r.offset.click.top=-2,r.offset.click.left=16,i.tree.ext.dnd._onDragEvent("start",i,null,t,n,r)},drag:function(t,n){var r,i=e(this).data("ui-draggable")||e(this).data("draggable"),o=n.helper.data("ftSourceNode")||null,a=n.helper.data("ftTargetNode")||null,s=e.ui.fancytree.getNode(t.target),l=o&&o.tree.options.dnd;t.target&&!s&&e(t.target).closest("div.fancytree-drag-helper,#fancytree-drop-marker").length>0?(o||a||e.ui.fancytree).debug("Drag event over helper: ignored."):(n.helper.data("ftTargetNode",s),l&&l.updateHelper&&(r=o.tree._makeHookContext(o,t,{otherNode:s,ui:n,draggable:i,dropMarker:e("#fancytree-drop-marker")}),l.updateHelper.call(o.tree,o,r)),a&&a!==s&&a.tree.ext.dnd._onDragEvent("leave",a,o,t,n,i),s&&s.tree.options.dnd.dragDrop&&(s===a?s.tree.ext.dnd._onDragEvent("over",s,o,t,n,i):(s.tree.ext.dnd._onDragEvent("enter",s,o,t,n,i),s.tree.ext.dnd._onDragEvent("over",s,o,t,n,i))))},stop:function(t,n){var r=e(this).data("ui-draggable")||e(this).data("draggable"),i=n.helper.data("ftSourceNode")||null,o=n.helper.data("ftTargetNode")||null,a="mouseup"===t.type&&1===t.which;a||(i||o||e.ui.fancytree).debug("Drag was cancelled"),o&&(a&&o.tree.ext.dnd._onDragEvent("drop",o,i,t,n,r),o.tree.ext.dnd._onDragEvent("leave",o,i,t,n,r)),i&&i.tree.ext.dnd._onDragEvent("stop",i,null,t,n,r)}}),i=!0)),n&&n.dragStart&&t.widget.element.draggable(e.extend({addClasses:!1,appendTo:t.$container,containment:!1,delay:0,distance:4,revert:!1,scroll:!0,scrollSpeed:7,scrollSensitivity:10,connectToFancytree:!0,helper:function(t){var n,i,o,a=e.ui.fancytree.getNode(t.target);return a?(o=a.tree.options.dnd,i=e(a.span),(n=e("
      ").css({zIndex:3,position:"relative"}).append(i.find("span.fancytree-title").clone())).data("ftSourceNode",a),r&&n.find(".fancytree-drag-helper-img").addClass(r.map.dragHelper),o.initHelper&&o.initHelper.call(a.tree,a,{node:a,tree:a.tree,originalEvent:t,ui:{helper:n}}),n):"
      ERROR?: helper requested but sourceNode not found
      "},start:function(e,t){return!!t.helper.data("ftSourceNode")}},t.options.dnd.draggable)),n&&n.dragDrop&&t.widget.element.droppable(e.extend({addClasses:!1,tolerance:"intersect",greedy:!1},t.options.dnd.droppable))}e.ui.fancytree.registerExtension({name:"dnd",version:"2.21.0",options:{autoExpandMS:1e3,draggable:null,droppable:null,focusOnClick:!1,preventVoidMoves:!0,preventRecursiveMoves:!0,smartRevert:!0,dragStart:null,dragStop:null,initHelper:null,updateHelper:null,dragEnter:null,dragOver:null,dragExpand:null,dragDrop:null,dragLeave:null},treeInit:function(t){var n=t.tree;this._superApply(arguments),n.options.dnd.dragStart&&n.$container.on("mousedown",function(n){if(t.options.dnd.focusOnClick){var r=e.ui.fancytree.getNode(n);r&&r.debug("Re-enable focus that was prevented by jQuery UI draggable."),setTimeout(function(){e(n.target).closest(":tabbable").focus()},10)}}),o(n)},_setDndStatus:function(t,n,r,i,o){var a,s="center",l=this._local,d=this.options.glyph||null,c=t?e(t.span):null,u=e(n.span),h=u.find(">span.fancytree-title");if(l.$dropMarker||(l.$dropMarker=e("
      ").hide().css({"z-index":1e3}).prependTo(e(this.$div).parent()),d&&l.$dropMarker.addClass(d.map.dropMarker)),"after"===i||"before"===i||"over"===i){switch(a=-24,i){case"before":s="top",a-=16;break;case"after":s="bottom",a-=16}l.$dropMarker.toggleClass("fancytree-drop-after","after"===i).toggleClass("fancytree-drop-over","over"===i).toggleClass("fancytree-drop-before","before"===i).show().position(e.ui.fancytree.fixPositionOptions({my:"left"+function(e){return 0===e?"":e>0?"+"+e:""+e}(a)+" center",at:"left "+s,of:h}))}else l.$dropMarker.hide();c&&c.toggleClass("fancytree-drop-accept",!0===o).toggleClass("fancytree-drop-reject",!1===o),u.toggleClass("fancytree-drop-target","after"===i||"before"===i||"over"===i).toggleClass("fancytree-drop-after","after"===i).toggleClass("fancytree-drop-before","before"===i).toggleClass("fancytree-drop-accept",!0===o).toggleClass("fancytree-drop-reject",!1===o),r.toggleClass("fancytree-drop-accept",!0===o).toggleClass("fancytree-drop-reject",!1===o)},_onDragEvent:function(t,r,i,o,a,s){var l,d,c,u,h,f,p,g,v,y=this.options.dnd,b=this._makeHookContext(r,o,{otherNode:i,ui:a,draggable:s}),m=null,x=this,_=e(r.span);switch(y.smartRevert&&(s.options.revert="invalid"),t){case"start":r.isStatusNode()?m=!1:y.dragStart&&(m=y.dragStart(r,b)),!1===m?(this.debug("tree.dragStart() cancelled"),a.helper.trigger("mouseup").hide()):(y.smartRevert&&(u=r[b.tree.nodeContainerAttrName].getBoundingClientRect(),c=e(s.options.appendTo)[0].getBoundingClientRect(),s.originalPosition.left=Math.max(0,u.left-c.left),s.originalPosition.top=Math.max(0,u.top-c.top)),_.addClass("fancytree-drag-source"),e(n).on("keydown.fancytree-dnd,mousedown.fancytree-dnd",function(t){"keydown"===t.type&&t.which===e.ui.keyCode.ESCAPE?x.ext.dnd._cancelDrag():"mousedown"===t.type&&x.ext.dnd._cancelDrag()}));break;case"enter":m=!!(v=(!y.preventRecursiveMoves||!r.isDescendantOf(i))&&(y.dragEnter?y.dragEnter(r,b):null))&&(e.isArray(v)?{over:e.inArray("over",v)>=0,before:e.inArray("before",v)>=0,after:e.inArray("after",v)>=0}:{over:!0===v||"over"===v,before:!0===v||"before"===v,after:!0===v||"after"===v}),a.helper.data("enterResponse",m);break;case"over":g=null,!1===(p=a.helper.data("enterResponse"))||("string"==typeof p?g=p:(d=_.offset(),f={x:(h={x:o.pageX-d.left,y:o.pageY-d.top}).x/_.width(),y:h.y/_.height()},p.after&&f.y>.75?g="after":!p.over&&p.after&&f.y>.5?g="after":p.before&&f.y<=.25?g="before":!p.over&&p.before&&f.y<=.5?g="before":p.over&&(g="over"),y.preventVoidMoves&&(r===i?(this.debug(" drop over source node prevented"),g=null):"before"===g&&i&&r===i.getNextSibling()?(this.debug(" drop after source node prevented"),g=null):"after"===g&&i&&r===i.getPrevSibling()?(this.debug(" drop before source node prevented"),g=null):"over"===g&&i&&i.parent===r&&i.isLastSibling()&&(this.debug(" drop last child over own parent prevented"),g=null)),a.helper.data("hitMode",g))),"before"===g||"after"===g||!y.autoExpandMS||!1===r.hasChildren()||r.expanded||y.dragExpand&&!1===y.dragExpand(r,b)||r.scheduleAction("expand",y.autoExpandMS),g&&y.dragOver&&(b.hitMode=g,m=y.dragOver(r,b)),l=!1!==m&&null!==g,y.smartRevert&&(s.options.revert=!l),this._local._setDndStatus(i,r,a.helper,g,l);break;case"drop":(g=a.helper.data("hitMode"))&&y.dragDrop&&(b.hitMode=g,y.dragDrop(r,b));break;case"leave":r.scheduleAction("cancel"),a.helper.data("enterResponse",null),a.helper.data("hitMode",null),this._local._setDndStatus(i,r,a.helper,"out",void 0),y.dragLeave&&y.dragLeave(r,b);break;case"stop":_.removeClass("fancytree-drag-source"),e(n).off(".fancytree-dnd"),y.dragStop&&y.dragStop(r,b);break;default:e.error("Unsupported drag event: "+t)}return m},_cancelDrag:function(){var t=e.ui.ddmanager.current;t&&t.cancel()}})}(jQuery,window,document)},function(e,t,n){"use strict";var r="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}; 16 | /*! 17 | * jquery.fancytree.js 18 | * Tree view control with support for lazy loading and much more. 19 | * https://github.com/mar10/fancytree/ 20 | * 21 | * Copyright (c) 2008-2017, Martin Wendt (http://wwWendt.de) 22 | * Released under the MIT license 23 | * https://github.com/mar10/fancytree/wiki/LicenseInfo 24 | * 25 | * @version 2.21.0 26 | * @date 2017-01-15T17:21:28Z 27 | */!function(e,t,n,i){if(e.ui&&e.ui.fancytree)e.ui.fancytree.warn("Fancytree: ignored duplicate include");else{var o,a,s=null,l=new RegExp(/\.|\//),d=/[&<>"'\/]/g,c=/[<>"'\/]/g,u={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"},h={16:!0,17:!0,18:!0},f={8:"backspace",9:"tab",10:"return",13:"return",19:"pause",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"insert",46:"del",59:";",61:"=",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9",106:"*",107:"+",109:"-",110:".",111:"/",112:"f1",113:"f2",114:"f3",115:"f4",116:"f5",117:"f6",118:"f7",119:"f8",120:"f9",121:"f10",122:"f11",123:"f12",144:"numlock",145:"scroll",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},p={0:"",1:"left",2:"middle",3:"right"},g="active expanded focus folder hideCheckbox lazy selected unselectable".split(" "),v={},y="expanded extraClasses folder hideCheckbox icon key lazy refKey selected statusNodeType title tooltip unselectable".split(" "),b={},m={},x={active:!0,children:!0,data:!0,focus:!0};for(o=0;o=0,"insertBefore must be an existing child"),this.children.splice.apply(this.children,[o,0].concat(s))),(!this.parent||this.parent.ul||this.tr)&&this.render(),3===this.tree.options.selectMode&&this.fixSelection3FromEndNodes(),this.triggerModifyChild("add",1===s.length?s[0]:null),a},addClass:function(e){return this.toggleClass(e,!0)},addNode:function(e,t){switch(t!==i&&"over"!==t||(t="child"),t){case"after":return this.getParent().addChildren(e,this.getNextSibling());case"before":return this.getParent().addChildren(e,this);case"firstChild":var n=this.children?this.children[0]:null;return this.addChildren(e,n);case"child":case"over":return this.addChildren(e)}_(!1,"Invalid mode: "+t)},addPagingNode:function(t,n){var r,i;if(n=n||"child",!1!==t)return t=e.extend({title:this.tree.options.strings.moreData,statusNodeType:"paging",icon:!1},t),this.partload=!0,this.addNode(t,n);for(r=this.children.length-1;r>=0;r--)"paging"===(i=this.children[r]).statusNodeType&&this.removeChild(i);this.partload=!1},appendSibling:function(e){return this.addNode(e,"after")},applyPatch:function(t){if(null===t)return this.remove(),S(this);var n,r,i={children:!0,expanded:!0,parent:!0};for(n in t)r=t[n],i[n]||e.isFunction(r)||(b[n]?this[n]=r:this.data[n]=r);return t.hasOwnProperty("children")&&(this.removeChildren(),t.children&&this._setChildren(t.children)),this.isVisible()&&(this.renderTitle(),this.renderStatus()),t.hasOwnProperty("expanded")?this.setExpanded(t.expanded):S(this)},collapseSiblings:function(){return this.tree._callHook("nodeCollapseSiblings",this)},copyTo:function(e,t,n){return e.addNode(this.toDict(!0,n),t)},countChildren:function(e){var t,n,r,i=this.children;if(!i)return 0;if(r=i.length,!1!==e)for(t=0,n=r;t=2&&(Array.prototype.unshift.call(arguments,this.toString()),k("log",arguments))},discard:function(){return this.warn("FancytreeNode.discard() is deprecated since 2014-02-16. Use .resetLazy() instead."),this.resetLazy()},discardMarkup:function(e){var t=e?"nodeRemoveMarkup":"nodeRemoveChildMarkup";this.tree._callHook(t,this)},findAll:function(t){t=e.isFunction(t)?t:A(t);var n=[];return this.visit(function(e){t(e)&&n.push(e)}),n},findFirst:function(t){t=e.isFunction(t)?t:A(t);var n=null;return this.visit(function(e){if(t(e))return n=e,!1}),n},_changeSelectStatusAttrs:function(e){var t=!1;switch(e){case!1:t=this.selected||this.partsel,this.selected=!1,this.partsel=!1;break;case!0:t=!this.selected||!this.partsel,this.selected=!0,this.partsel=!0;break;case i:t=this.selected||!this.partsel,this.selected=!1,this.partsel=!0;break;default:_(!1,"invalid state: "+e)}return t&&this.renderStatus(),t},fixSelection3AfterClick:function(){var e=this.isSelected();this.visit(function(t){t._changeSelectStatusAttrs(e)}),this.fixSelection3FromEndNodes()},fixSelection3FromEndNodes:function(){_(3===this.tree.options.selectMode,"expected selectMode 3"),function e(t){var n,r,o,a,s,l,d=t.children;if(d&&d.length){for(s=!0,l=!1,n=0,r=d.length;n=1&&(Array.prototype.unshift.call(arguments,this.toString()),k("info",arguments))},isActive:function(){return this.tree.activeNode===this},isChildOf:function(e){return this.parent&&this.parent===e},isDescendantOf:function(e){if(!e||e.tree!==this.tree)return!1;for(var t=this.parent;t;){if(t===e)return!0;t=t.parent}return!1},isExpanded:function(){return!!this.expanded},isFirstSibling:function(){var e=this.parent;return!e||e.children[0]===this},isFolder:function(){return!!this.folder},isLastSibling:function(){var e=this.parent;return!e||e.children[e.children.length-1]===this},isLazy:function(){return!!this.lazy},isLoaded:function(){return!this.lazy||this.hasChildren()!==i},isLoading:function(){return!!this._isLoading},isRoot:function(){return this.isRootNode()},isPartload:function(){return!!this.partload},isRootNode:function(){return this.tree.rootNode===this},isSelected:function(){return!!this.selected},isStatusNode:function(){return!!this.statusNodeType},isPagingNode:function(){return"paging"===this.statusNodeType},isTopLevel:function(){return this.tree.rootNode===this.parent},isUndefined:function(){return this.hasChildren()===i},isVisible:function(){var e,t,n=this.getParentList(!1,!1);for(e=0,t=n.length;e=0;n--)i.push(a[n].setExpanded(!0,t));return e.when.apply(e,i).done(function(){d?r.scrollIntoView(l).done(function(){o.resolve()}):o.resolve()}),o.promise()},moveTo:function(t,n,r){n===i||"over"===n?n="child":"firstChild"===n&&(t.children&&t.children.length?(n="before",t=t.children[0]):n="child");var o,a=this.parent,s="child"===n?t:t.parent;if(this!==t){if(this.parent?s.isDescendantOf(this)&&e.error("Cannot move a node to its own descendant"):e.error("Cannot move system root"),s!==a&&a.triggerModifyChild("remove",this),1===this.parent.children.length){if(this.parent===s)return;this.parent.children=this.parent.lazy?[]:null,this.parent.expanded=!1}else _((o=e.inArray(this,this.parent.children))>=0,"invalid source parent"),this.parent.children.splice(o,1);if(this.parent=s,s.hasChildren())switch(n){case"child":s.children.push(this);break;case"before":_((o=e.inArray(t,s.children))>=0,"invalid target parent"),s.children.splice(o,0,this);break;case"after":_((o=e.inArray(t,s.children))>=0,"invalid target parent"),s.children.splice(o+1,0,this);break;default:e.error("Invalid mode "+n)}else s.children=[this];r&&t.visit(r,!0),s===a?s.triggerModifyChild("move",this):s.triggerModifyChild("add",this),this.tree!==t.tree&&(this.warn("Cross-tree moveTo is experimantal!"),this.visit(function(e){e.tree=t.tree},!0)),a.isDescendantOf(s)||a.render(),s.isDescendantOf(a)||s===a||s.render()}},navigate:function(t,n){var r,i,o,a=e.ui.keyCode,s=null;function l(r){if(r){try{r.makeVisible({scrollIntoView:!1})}catch(e){}return e(r.span).is(":visible")?!1===n?r.setFocus():r.setActive():(r.debug("Navigate: skipping hidden node"),void r.navigate(t,n))}}switch(t){case a.BACKSPACE:this.parent&&this.parent.parent&&(o=l(this.parent));break;case a.HOME:this.tree.visit(function(t){if(e(t.span).is(":visible"))return o=l(t),!1});break;case a.END:this.tree.visit(function(t){e(t.span).is(":visible")&&(o=t)}),o&&(o=l(o));break;case a.LEFT:this.expanded?(this.setExpanded(!1),o=l(this)):this.parent&&this.parent.parent&&(o=l(this.parent));break;case a.RIGHT:this.expanded||!this.children&&!this.lazy?this.children&&this.children.length&&(o=l(this.children[0])):(this.setExpanded(),o=l(this));break;case a.UP:for(s=this.getPrevSibling();s&&!e(s.span).is(":visible");)s=s.getPrevSibling();for(;s&&s.expanded&&s.children&&s.children.length;)s=s.children[s.children.length-1];!s&&this.parent&&this.parent.parent&&(s=this.parent),o=l(s);break;case a.DOWN:if(this.expanded&&this.children&&this.children.length)s=this.children[0];else for(r=(i=this.getParentList(!1,!0)).length-1;r>=0;r--){for(s=i[r].getNextSibling();s&&!e(s.span).is(":visible");)s=s.getNextSibling();if(s)break}o=l(s);break;default:!1}return o||S()},remove:function(){return this.parent.removeChild(this)},removeChild:function(e){return this.tree._callHook("nodeRemoveChild",this,e)},removeChildren:function(){return this.tree._callHook("nodeRemoveChildren",this)},removeClass:function(e){return this.toggleClass(e,!1)},render:function(e,t){return this.tree._callHook("nodeRender",this,e,t)},renderTitle:function(){return this.tree._callHook("nodeRenderTitle",this)},renderStatus:function(){return this.tree._callHook("nodeRenderStatus",this)},replaceWith:function(t){var n,r=this.parent,i=e.inArray(this,r.children),a=this;return _(this.isPagingNode(),"replaceWith() currently requires a paging status node"),(n=this.tree._callHook("nodeLoadChildren",this,t)).done(function(e){var t=a.children;for(o=0;oy+v-g&&(k=s+h-v+g,x&&(_(x.isRootNode()||e(x.span).is(":visible"),"topNode must be visible"),ar?1:-1},i.sort(e),t)for(n=0,r=i.length;n=0,n=n===i?!o:!!n)o||(c+=r+" ",l=!0);else for(;c.indexOf(" "+r+" ")>-1;)c=c.replace(" "+r+" "," ");return this.extraClasses=e.trim(c),l},toggleExpanded:function(){return this.tree._callHook("nodeToggleExpanded",this)},toggleSelected:function(){return this.tree._callHook("nodeToggleSelected",this)},toString:function(){return""},triggerModifyChild:function(t,n,r){var i,o=this.tree.options.modifyChild;o&&(n&&n.parent!==this&&e.error("childNode "+n+" is not a child of "+this),i={node:this,tree:this.tree,operation:t,childNode:n||null},r&&e.extend(i,r),o({type:"modifyChild"},i))},triggerModify:function(e,t){this.parent.triggerModifyChild(e,this,t)},visit:function(e,t){var n,r,i=!0,o=this.children;if(!0===t&&(!1===(i=e(this))||"skip"===i))return i;if(o)for(n=0,r=o.length;n=2&&(Array.prototype.unshift.call(arguments,this.toString()),k("log",arguments))},enableUpdate:function(e){return e=!1!==e,!!this._enableUpdate==!!e?e:(this._enableUpdate=e,e?(this.debug("enableUpdate(true): redraw ",this._dirtyRoots),this.render()):this.debug("enableUpdate(false)..."),!e)},findAll:function(e){return this.rootNode.findAll(e)},findFirst:function(e){return this.rootNode.findFirst(e)},findNextNode:function(t,n,r){var i=null,o=n.parent.children,a=null;return t="string"==typeof t?function(e){var t=new RegExp("^"+e,"i");return function(e){return t.test(e.title)}}(t):t,function e(t,n,r){var i,o,a=t.children,s=a.length,l=a[n];if(l&&!1===r(l))return!1;if(l&&l.children&&l.expanded&&!1===e(l,0,r))return!1;for(i=n+1;i
      ",{id:s}).hide().insertAfter(this.$container),!1!==n&&this.activeNode&&l.append(e("",{type:"radio",name:a,value:this.activeNode.key,checked:!0})),r.filter?this.visit(function(e){var t=r.filter(e);if("skip"===t)return t;!1!==t&&c(e)}):!1!==t&&(i=this.getSelectedNodes(d),e.each(i,function(e,t){c(t)}))},getActiveNode:function(){return this.activeNode},getFirstChild:function(){return this.rootNode.getFirstChild()},getFocusNode:function(){return this.focusNode},getNodeByKey:function(e,t){var r,i;return!t&&(r=n.getElementById(this.options.idPrefix+e))?r.ftnode?r.ftnode:null:(t=t||this.rootNode,i=null,t.visit(function(t){if(t.key===e)return i=t,!1},!0),i)},getRootNode:function(){return this.rootNode},getSelectedNodes:function(e){return this.rootNode.getSelectedNodes(e)},hasFocus:function(){return!!this._hasFocus},info:function(e){this.options.debugLevel>=1&&(Array.prototype.unshift.call(arguments,this.toString()),k("info",arguments))},loadKeyPath:function(t,n,r){var o,a,s,l,d,c,u,h,f,p=this.options.keyPathSeparator,g=this;for(n=n||e.noop,e.isArray(t)||(t=[t]),c={},s=0;s"},_triggerNodeEvent:function(e,t,n,r){var o=this._makeHookContext(t,n,r),a=this.widget._trigger(e,n,o);return!1!==a&&o.result!==i?o.result:a},_triggerTreeEvent:function(e,t,n){var r=this._makeHookContext(this,t,n),o=this.widget._trigger(e,t,r);return!1!==o&&r.result!==i?r.result:o},visit:function(e){return this.rootNode.visit(e,!1)},warn:function(e){Array.prototype.unshift.call(arguments,this.toString()),k("warn",arguments)}},e.extend(F.prototype,{nodeClick:function(e){var t,n,r=e.targetType,i=e.node;if("expander"===r){if(i.isLoading())return void i.debug("Got 2nd click while loading: ignored");this._callHook("nodeToggleExpanded",e)}else if("checkbox"===r)this._callHook("nodeToggleSelected",e),e.options.focusOnSelect&&this._callHook("nodeSetFocus",e,!0);else{if(n=!1,t=!0,i.folder)switch(e.options.clickFolderMode){case 2:n=!0,t=!1;break;case 3:t=!0,n=!0}t&&(this.nodeSetFocus(e),this._callHook("nodeSetActive",e,!0)),n&&this._callHook("nodeToggleExpanded",e)}},nodeCollapseSiblings:function(e,t){var n,r,i,o=e.node;if(o.parent)for(r=0,i=(n=o.parent.children).length;r500&&(l.lastQuicksearchTerm=""),l.lastQuicksearchTime=r,l.lastQuicksearchTerm+=u,(n=l.findNextNode(l.lastQuicksearchTerm,l.getActiveNode()))&&n.setActive(),void o.preventDefault();switch(s.eventToString(o)){case"+":case"=":l.nodeSetExpanded(t,!0);break;case"-":l.nodeSetExpanded(t,!1);break;case"space":a.isPagingNode()?l._triggerNodeEvent("clickPaging",t,o):d.checkbox?l.nodeToggleSelected(t):l.nodeSetActive(t,!0);break;case"return":l.nodeSetActive(t,!0);break;case"home":case"end":case"backspace":case"left":case"right":case"up":case"down":a.navigate(o.which,v,!0);break;default:g=!1}g&&o.preventDefault()},nodeLoadChildren:function(t,n){var r,i,o,a=t.tree,s=t.node,l=(new Date).getTime();return e.isFunction(n)&&(n=n.call(a,{type:"source"},t),_(!e.isFunction(n),"source callback must not return another function")),n.url&&(s._requestId&&s.warn("Recursive load request #"+l+" while #"+s._requestId+" is pending."),r=e.extend({},t.options.ajax,n),s._requestId=l,r.debugDelay?(i=r.debugDelay,e.isArray(i)&&(i=i[0]+Math.random()*(i[1]-i[0])),s.warn("nodeLoadChildren waiting debugDelay "+Math.round(i)+" ms ..."),r.debugDelay=!1,o=e.Deferred(function(t){setTimeout(function(){e.ajax(r).done(function(){t.resolveWith(this,arguments)}).fail(function(){t.rejectWith(this,arguments)})},i)})):o=e.ajax(r),n=new e.Deferred,o.done(function(r,i,o){var d,c;if("json"!==this.dataType&&"jsonp"!==this.dataType||"string"!=typeof r||e.error("Ajax request returned a string (did you get the JSON dataType wrong?)."),s._requestId&&s._requestId>l)n.rejectWith(this,["$recursive_request"]);else{if(t.options.postProcess){try{c=a._triggerNodeEvent("postProcess",t,t.originalEvent,{response:r,error:null,dataType:this.dataType})}catch(e){c={error:e,message:""+e,details:"postProcess failed"}}if(c.error)return d=e.isPlainObject(c.error)?c.error:{message:c.error},d=a._makeHookContext(s,null,d),void n.rejectWith(this,[d]);r=e.isArray(c)?c:r}else r&&r.hasOwnProperty("d")&&t.options.enableAspx&&(r="string"==typeof r.d?e.parseJSON(r.d):r.d);n.resolveWith(this,[r])}}).fail(function(e,t,r){var i=a._makeHookContext(s,null,{error:e,args:Array.prototype.slice.call(arguments),message:r,details:e.status+": "+r});n.rejectWith(this,[i])})),e.isFunction(n.then)&&e.isFunction(n.catch)&&(o=n,n=new e.Deferred,o.then(function(e){n.resolve(e)},function(e){n.reject(e)})),e.isFunction(n.promise)&&(a.nodeSetStatus(t,"loading"),n.done(function(e){a.nodeSetStatus(t,"ok"),s._requestId=null}).fail(function(e){var n;"$recursive_request"!==e?(e.node&&e.error&&e.message?n=e:"[object Object]"===(n=a._makeHookContext(s,null,{error:e,args:Array.prototype.slice.call(arguments),message:e?e.message||e.toString():""})).message&&(n.message=""),s.warn("Load children failed ("+n.message+")",n),!1!==a._triggerNodeEvent("loadError",n,null)&&a.nodeSetStatus(t,"error",n.message,n.details)):s.warn("Ignored response for obsolete load request #"+l+" (expected #"+s._requestId+")")})),e.when(n).done(function(t){var n;e.isPlainObject(t)&&(_(s.isRootNode(),"source may only be an object for root nodes (expecting an array of child objects otherwise)"),_(e.isArray(t.children),"if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')"),n=t,t=t.children,delete n.children,e.extend(a.data,n)),_(e.isArray(t),"expected array of children"),s._setChildren(t),a._triggerNodeEvent("loadChildren",s)})},nodeLoadKeyPath:function(e,t){},nodeRemoveChild:function(t,n){var r,i=t.node,o=e.extend({},t,{node:n}),a=i.children;if(1===a.length)return _(n===a[0],"invalid single child"),this.nodeRemoveChildren(t);this.activeNode&&(n===this.activeNode||this.activeNode.isDescendantOf(n))&&this.activeNode.setActive(!1),this.focusNode&&(n===this.focusNode||this.focusNode.isDescendantOf(n))&&(this.focusNode=null),this.nodeRemoveMarkup(o),this.nodeRemoveChildren(o),_((r=e.inArray(n,a))>=0,"invalid child"),i.triggerModifyChild("remove",n),n.visit(function(e){e.parent=null},!0),this._callHook("treeRegisterNode",this,!1,n),a.splice(r,1)},nodeRemoveChildMarkup:function(t){var n=t.node;n.ul&&(n.isRootNode()?e(n.ul).empty():(e(n.ul).remove(),n.ul=null),n.visit(function(e){e.li=e.ul=null}))},nodeRemoveChildren:function(t){var n=t.tree,r=t.node;r.children&&(this.activeNode&&this.activeNode.isDescendantOf(r)&&this.activeNode.setActive(!1),this.focusNode&&this.focusNode.isDescendantOf(r)&&(this.focusNode=null),this.nodeRemoveChildMarkup(t),e.extend({},t),r.triggerModifyChild("remove",null),r.visit(function(e){e.parent=null,n._callHook("treeRegisterNode",n,!1,e)}),r.lazy?r.children=[]:r.children=null,r.isRootNode()||(r.expanded=!1),this.nodeRenderStatus(t))},nodeRemoveMarkup:function(t){var n=t.node;n.li&&(e(n.li).remove(),n.li=null),this.nodeRemoveChildMarkup(t)},nodeRender:function(t,r,i,o,a){var s,l,d,c,u,h,f,p=t.node,g=t.tree,v=t.options,y=v.aria,b=!1,m=p.parent,x=!m,k=p.children,N=null;if(!1!==g._enableUpdate&&(x||m.ul)){if(_(x||m.ul,"parent UL must exist"),x||(p.li&&(r||p.li.parentNode!==p.parent.ul)&&(p.li.parentNode===p.parent.ul?N=p.li.nextSibling:this.debug("Unlinking "+p+" (must be child of "+p.parent+")"),this.nodeRemoveMarkup(t)),p.li?this.nodeRenderStatus(t):(b=!0,p.li=n.createElement("li"),p.li.ftnode=p,p.key&&v.generateIds&&(p.li.id=v.idPrefix+p.key),p.span=n.createElement("span"),p.span.className="fancytree-node",y&&e(p.li).attr("aria-labelledby","ftal_"+v.idPrefix+p.key),p.li.appendChild(p.span),this.nodeRenderTitle(t),v.createNode&&v.createNode.call(g,{type:"createNode"},t)),v.renderNode&&v.renderNode.call(g,{type:"renderNode"},t)),k){if(x||p.expanded||!0===i){for(p.ul||(p.ul=n.createElement("ul"),(!0!==o||a)&&p.expanded||(p.ul.style.display="none"),y&&e(p.ul).attr("role","group"),p.li?p.li.appendChild(p.ul):p.tree.$div.append(p.ul)),c=0,u=k.length;c1&&(g?y.push(""):y.push(""))):g?y.push(""):y.push(""),p.checkbox&&!0!==h.hideCheckbox&&!h.isStatusNode()&&(g?y.push(""):y.push("")),h.data.iconClass!==i&&(h.icon?e.error("'iconClass' node option is deprecated since v2.14.0: use 'icon' only instead"):(h.warn("'iconClass' node option is deprecated since v2.14.0: use 'icon' instead"),h.icon=h.data.iconClass)),e.isFunction(p.icon)?null==(o=p.icon.call(f,{type:"icon"},t))&&(o=h.icon):o=null!=h.icon?h.icon:p.icon,null==o?o=!0:"boolean"!=typeof o&&(o=""+o),!1!==o&&(s=g?" role='img'":"","string"==typeof o?l.test(o)?(o="/"===o.charAt(0)?o:(p.imagePath||"")+o,y.push("")):y.push(""):y.push("")),a="",p.renderTitle&&(a=p.renderTitle.call(f,{type:"renderTitle"},t)||""),a||(h.tooltip?d=h.tooltip:p.tooltip&&(d=!0===p.tooltip?h.title:p.tooltip.call(f,h)),d=d?" title='"+function(e){return(""+e).replace(c,function(e){return u[e]})}(d)+"'":"",r=g?" id='ftal_"+p.idPrefix+h.key+"'":"",a=""+(p.escapeTitles?P(h.title):h.title)+""),y.push(a),h.span.innerHTML=y.join(""),this.nodeRenderStatus(t),p.enhanceTitle&&(t.$title=e(">span.fancytree-title",h.span),a=p.enhanceTitle.call(f,{type:"enhanceTitle"},t)||""))},nodeRenderStatus:function(t){var n=t.node,r=t.tree,i=t.options,o=n.hasChildren(),a=n.isLastSibling(),s=i.aria,l=e(n.span).find(".fancytree-title"),d=i._classNames,c=[],u=n[r.statusClassPropName];u&&!1!==r._enableUpdate&&(c.push(d.node),r.activeNode===n&&c.push(d.active),r.focusNode===n&&c.push(d.focused),n.expanded?(c.push(d.expanded),s&&l.attr("aria-expanded",!0)):s&&(o?l.attr("aria-expanded",!1):l.removeAttr("aria-expanded")),n.folder&&c.push(d.folder),!1!==o&&c.push(d.hasChildren),a&&c.push(d.lastsib),n.lazy&&null==n.children&&c.push(d.lazy),n.partload&&c.push(d.partload),n.partsel&&c.push(d.partsel),n.unselectable&&c.push(d.unselectable),n._isLoading&&c.push(d.loading),n._error&&c.push(d.error),n.statusNodeType&&c.push(d.statusNodePrefix+n.statusNodeType),n.selected?(c.push(d.selected),s&&l.attr("aria-selected",!0)):s&&l.attr("aria-selected",!1),n.extraClasses&&c.push(n.extraClasses),!1===o?c.push(d.combinedExpanderPrefix+"n"+(a?"l":"")):c.push(d.combinedExpanderPrefix+(n.expanded?"e":"c")+(n.lazy&&null==n.children?"d":"")+(a?"l":"")),c.push(d.combinedIconPrefix+(n.expanded?"e":"c")+(n.folder?"f":"")),u.className=c.join(" "),n.li&&(n.li.className=a?d.lastsib:""))},nodeSetActive:function(t,n,r){r=r||{};var i,o=t.node,a=t.tree,s=t.options,l=!0===r.noEvents,d=!0===r.noFocus;return o===a.activeNode===(n=!1!==n)?S(o):n&&!l&&!1===this._triggerNodeEvent("beforeActivate",o,t.originalEvent)?C(o,["rejected"]):(n?(a.activeNode&&(_(a.activeNode!==o,"node was active (inconsistency)"),i=e.extend({},t,{node:a.activeNode}),a.nodeSetActive(i,!1),_(null===a.activeNode,"deactivate was out of sync?")),s.activeVisible&&o.makeVisible({scrollIntoView:d&&null==a.focusNode}),a.activeNode=o,a.nodeRenderStatus(t),d||a.nodeSetFocus(t),l||a._triggerNodeEvent("activate",o,t.originalEvent)):(_(a.activeNode===o,"node was not active (inconsistency)"),a.activeNode=null,this.nodeRenderStatus(t),l||t.tree._triggerNodeEvent("deactivate",o,t.originalEvent)),S(o))},nodeSetExpanded:function(t,n,r){r=r||{};var o,a,s,l,d,c,u=t.node,h=t.tree,f=t.options,p=!0===r.noAnimation,g=!0===r.noEvents;if(n=!1!==n,u.expanded&&n||!u.expanded&&!n)return S(u);if(n&&!u.lazy&&!u.hasChildren())return S(u);if(!n&&u.getLevel()ul.fancytree-container").empty(),t.rootNode.children=null},treeCreate:function(e){},treeDestroy:function(e){this.$div.find(">ul.fancytree-container").remove(),this.$source&&this.$source.removeClass("ui-helper-hidden")},treeInit:function(e){this.treeLoad(e)},treeLoad:function(t,n){var r,i,o,a=t.tree,s=t.widget.element,l=e.extend({},t,{node:this.rootNode});if(a.rootNode.children&&this.treeClear(t),n=n||this.options.source)"string"==typeof n&&e.error("Not implemented");else switch(i=s.data("type")||"html"){case"html":(o=s.find(">ul:first")).addClass("ui-fancytree-source ui-helper-hidden"),n=e.ui.fancytree.parseHtml(o),this.data=e.extend(this.data,T(o));break;case"json":n=e.parseJSON(s.text()),s.contents().filter(function(){return 3===this.nodeType}).remove(),e.isPlainObject(n)&&(_(e.isArray(n.children),"if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')"),r=n,n=n.children,delete r.children,e.extend(a.data,r));break;default:e.error("Invalid data-type: "+i)}return this.nodeLoadChildren(l,n).done(function(){a.render(),3===t.options.selectMode&&a.rootNode.fixSelection3FromEndNodes(),a.activeNode&&a.options.activeVisible&&a.activeNode.makeVisible(),a._triggerTreeEvent("init",null,{status:!0})}).fail(function(){a.render(),a._triggerTreeEvent("init",null,{status:!1})})},treeRegisterNode:function(e,t,n){},treeSetFocus:function(t,n,r){(n=!1!==n)!==this.hasFocus()&&(this._hasFocus=n,!n&&this.focusNode?this.focusNode.setFocus(!1):!n||r&&r.calledByNode||e(this.$container).focus(),this.$container.toggleClass("fancytree-treefocus",n),this._triggerTreeEvent(n?"focusTree":"blurTree"),n&&!this.activeNode&&this.getFirstChild()&&this.getFirstChild().setFocus())},treeSetOption:function(t,n,i){var o=t.tree,a=!0,s=!1;switch(n){case"aria":case"checkbox":case"icon":case"minExpandLevel":case"tabindex":o._callHook("treeCreate",o),s=!0;break;case"escapeTitles":case"tooltip":s=!0;break;case"rtl":!1===i?o.$container.attr("DIR",null).removeClass("fancytree-rtl"):o.$container.attr("DIR","RTL").addClass("fancytree-rtl"),s=!0;break;case"source":a=!1,o._callHook("treeLoad",o,i),s=!0}o.debug("set option "+n+"="+i+" <"+(void 0===i?"undefined":r(i))+">"),a&&(this.widget._super?this.widget._super.call(this.widget,n,i):e.Widget.prototype._setOption.call(this.widget,n,i)),s&&o.render(!0,!1)}}),e.widget("ui.fancytree",{options:{activeVisible:!0,ajax:{type:"GET",cache:!1,dataType:"json"},aria:!1,autoActivate:!0,autoCollapse:!1,autoScroll:!1,checkbox:!1,clickFolderMode:4,debugLevel:null,disabled:!1,enableAspx:!0,escapeTitles:!1,extensions:[],toggleEffect:{effect:"blind",options:{direction:"vertical",scale:"box"},duration:200},generateIds:!1,icon:!0,idPrefix:"ft_",focusOnSelect:!1,keyboard:!0,keyPathSeparator:"/",minExpandLevel:1,quicksearch:!1,rtl:!1,scrollOfs:{top:0,bottom:0},scrollParent:null,selectMode:2,strings:{loading:"Loading…",loadError:"Load error!",moreData:"More…",noData:"No data."},tabindex:"0",titlesTabbable:!1,tooltip:!1,_classNames:{node:"fancytree-node",folder:"fancytree-folder",combinedExpanderPrefix:"fancytree-exp-",combinedIconPrefix:"fancytree-ico-",hasChildren:"fancytree-has-children",active:"fancytree-active",selected:"fancytree-selected",expanded:"fancytree-expanded",lazy:"fancytree-lazy",focused:"fancytree-focused",partload:"fancytree-partload",partsel:"fancytree-partsel",unselectable:"fancytree-unselectable",lastsib:"fancytree-lastsib",loading:"fancytree-loading",error:"fancytree-error",statusNodePrefix:"fancytree-statusnode-"},lazyLoad:null,postProcess:null},_create:function(){this.tree=new F(this),this.$source=this.source||"json"===this.element.data("type")?this.element:this.element.find(">ul:first");var t,n,r,o=this.options,a=o.extensions;this.tree;for(r=0;rs;return!0}(e.ui.version,1,9)},assert:function(e,t){return _(e,t)},debounce:function(e,t,n,r){var i;return 3===arguments.length&&"boolean"!=typeof n&&(r=n,n=!1),function(){var o=arguments;r=r||this,n&&!i&&t.apply(r,o),clearTimeout(i),i=setTimeout(function(){n||t.apply(r,o),i=null},e)}},debug:function(t){e.ui.fancytree.debugLevel>=2&&k("log",arguments)},error:function(e){k("error",arguments)},escapeHtml:P,fixPositionOptions:function(t){if((t.offset||(""+t.my+t.at).indexOf("%")>=0)&&e.error("expected new position syntax (but '%' is not supported)"),!e.ui.fancytree.jquerySupports.positionMyOfs){var n=/(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(t.my),r=/(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(t.at),i=(n[2]?+n[2]:0)+(r[2]?+r[2]:0),o=(n[4]?+n[4]:0)+(r[4]?+r[4]:0);t=e.extend({},t,{my:n[1]+" "+n[3],at:r[1]+" "+r[3]}),(i||o)&&(t.offset=i+" "+o)}return t},getEventTargetType:function(e){return this.getEventTarget(e).type},getEventTarget:function(t){var n=t&&t.target?t.target.className:"",r={node:this.getNode(t.target),type:i};return/\bfancytree-title\b/.test(n)?r.type="title":/\bfancytree-expander\b/.test(n)?r.type=!1===r.node.hasChildren()?"prefix":"expander":/\bfancytree-checkbox\b/.test(n)||/\bfancytree-radio\b/.test(n)?r.type="checkbox":/\bfancytree-icon\b/.test(n)?r.type="icon":/\bfancytree-node\b/.test(n)?r.type="title":t&&t.target&&e(t.target).closest(".fancytree-title").length&&(r.type="title"),r},getNode:function(e){if(e instanceof O)return e;for(e.selector!==i?e=e[0]:e.originalEvent!==i&&(e=e.target);e;){if(e.ftnode)return e.ftnode;e=e.parentNode}return null},getTree:function(t){var n;return t instanceof F?t:(t===i&&(t=0),"number"==typeof t?t=e(".fancytree-container").eq(t):"string"==typeof t?t=e(t).eq(0):t.selector!==i?t=t.eq(0):t.originalEvent!==i&&(t=e(t.target)),(n=(t=t.closest(":ui-fancytree")).data("ui-fancytree")||t.data("fancytree"))?n.tree:null)},eventToString:function(e){var t=e.which,n=e.type,r=[];return e.altKey&&r.push("alt"),e.ctrlKey&&r.push("ctrl"),e.metaKey&&r.push("meta"),e.shiftKey&&r.push("shift"),"click"===n||"dblclick"===n?r.push(p[e.button]+n):h[t]||r.push(f[t]||String.fromCharCode(t).toLowerCase()),r.join("+")},info:function(t){e.ui.fancytree.debugLevel>=1&&k("info",arguments)},keyEventToString:function(e){return this.warn("keyEventToString() is deprecated: use eventToString()"),this.eventToString(e)},overrideMethod:function(t,n,r){var i,o=t[n]||e.noop;t[n]=function(){try{return i=this._super,this._super=o,r.apply(this,arguments)}finally{this._super=i}}},parseHtml:function(t){var n,r,o,a,s,l,d,c,u=[];return t.find(">li").each(function(){var h,f,p=e(this),b=p.find(">span:first",this),x=b.length?null:p.find(">a:first"),_={tooltip:null,data:{}};for(b.length?_.title=b.html():x&&x.length?(_.title=x.html(),_.data.href=x.attr("href"),_.data.target=x.attr("target"),_.tooltip=x.attr("title")):(_.title=p.html(),(s=_.title.search(/