added socket.io

root 2021-05-27 15:57:44 +02:00
parent d54f47c06f
commit 35f0dbe451
538 changed files with 190502 additions and 55 deletions

View File

@ -9,22 +9,26 @@ import traceback
from .nextcloud_exc import *
from .helpers import filter_roles_list, filter_roles_listofdicts
socketio = SocketIO(app)
class Admin():
def __init__(self):
self.keycloak=Keycloak(verify=app.config['VERIFY'])
self.moodle=Moodle(verify=app.config['VERIFY'])
self.nextcloud=Nextcloud(verify=app.config['VERIFY'])
# self.internal={'users':self.get_mix_users(),
# 'groups':self.get_mix_groups(),
# 'roles':[]}
self.internal={}
self.resync_data()
self.external={'users':[],
'groups':[],
'roles':[]}
#pprint(self.get_moodle_groups())
# pprint(self.get_moodle_users())
# pprint(self.get_keycloak_users())
# pprint(self.get_nextcloud_users())
def resync_data(self):
self.internal={'users':self._get_mix_users(),
'groups':self._get_mix_groups(),
'roles':self._get_roles()}
return True
def get_moodle_users(self):
return self.moodle.get_users_with_groups_and_roles()
@ -85,6 +89,9 @@ class Admin():
# return self.internal['users']
def get_mix_users(self):
return self.internal['users']
def _get_mix_users(self):
kusers=self.get_keycloak_users()
musers=self.get_moodle_users()
nusers=self.get_nextcloud_users()
@ -131,6 +138,9 @@ class Admin():
return users
def get_roles(self):
return self.internal['roles']
def _get_roles(self):
return filter_roles_listofdicts(self.keycloak.get_roles())
def get_keycloak_groups(self):
@ -145,10 +155,10 @@ class Admin():
log.warning('Loading nextcloud groups... can take a long time...')
return self.nextcloud.get_groups_list()
# def get_ram_groups(self):
# return self.internal['groups']
def get_mix_groups(self):
return self.internal['groups']
def _get_mix_groups(self):
kgroups=self.get_keycloak_groups()
mgroups=self.get_moodle_groups()
ngroups=self.get_nextcloud_groups()
@ -236,15 +246,13 @@ class Admin():
self.keycloak.add_user(u['username'],u['first'],u['last'],u['email'],'1Provaprovaprova',group=u['groups'][0])
def sync_to_moodle(self):
users=self.get_mix_users()
for u in users:
for u in self.internal['users']:
if not u['moodle']:
log.error('Creating moodle user: '+u['username'])
self.moodle.create_user(u['email'],u['username'],'-1Provaprovaprova',u['first'],u['last'])
def sync_to_nextcloud(self):
users=self.get_mix_users()
for u in users:
for u in self.internal['users']:
if not u['nextcloud']:
log.error('Creating nextcloud user: '+u['username'])
group=u['keycloak_groups'][0] if len(u['keycloak_groups']) else False
@ -258,21 +266,25 @@ class Admin():
# <div>Las contraseñas deben tener al menos 1 dígito(s).</div><div>Las contraseñas deben tener al menos 1 mayúscula(s).</div><div>Las contraseñas deben tener al menos 1 caracter(es) no alfanumérico(s) como *,-,
def delete_keycloak_users(self):
users=self.get_keycloak_users()
for u in users:
for u in self.internal['users']:
if not u['keycloak']: continue
# Do not remove admin users!!! What to do with managers???
if 'admin' in u['roles']: continue
if 'manager' in u['roles']: continue
log.info('Removing keycloak user: '+u['username'])
try:
self.keycloak.delete_user(u['id'])
socketio.emit('update',
json.dumps({'status':True,'item':'user','action':'delete','itemdata':u}),
namespace='/isard-sso-admin/sio',
room='admin')
except:
log.error(traceback.format_exc())
log.warning('Could not remove user: '+u['username'])
def delete_keycloak_groups(self):
groups=self.get_keycloak_groups()
for g in groups:
for g in self.internal['groups']:
if not g['keycloak']: continue
# Do not remove admin group. It should not exist in keycloak, only in nextcloud
if g['name'] == ['admin']: continue
log.info('Removing keycloak group: '+g['name'])

View File

@ -127,11 +127,11 @@ class Keycloak():
log.error(uid)
if group:
try:
gid=self.keycloak_admin.get_group_by_path(path='/'+group,search_in_subgroups=False)['id']
gid=self.keycloak_admin.get_group_by_path(path=group,search_in_subgroups=False)['id']
log.error('group created with gid: '+str(gid))
except:
self.keycloak_admin.create_group({"name":group})
gid=self.keycloak_admin.get_group_by_path('/'+group)['id']
gid=self.keycloak_admin.get_group_by_path(group)['id']
log.error(gid)
self.keycloak_admin.group_user_add(uid,gid)

View File

@ -350,5 +350,4 @@ $(document).ready(function() {
$BOX_PANEL.remove();
});
});
});

View File

@ -5,6 +5,24 @@ $(document).on('shown.bs.modal', '#modalAddDesktop', function () {
$(document).ready(function() {
$('.btn-global-resync').on('click', function () {
$.ajax({
type: "GET",
url:"/isard-sso-admin/resync",
success: function(data)
{
table.ajax.reload();
// $("#modalImport").modal('hide');
// users_table.ajax.reload();
// groups_table.ajax.reload();
},
error: function(data)
{
alert('Something went wrong on our side...')
}
});
});
$('.btn-new').on('click', function () {
$("#modalAdd")[0].reset();
$('#modalAddDesktop').modal({
@ -14,6 +32,24 @@ $(document).ready(function() {
$('#modalAdd').parsley();
});
$('.btn-delete_keycloak').on('click', function () {
$.ajax({
type: "DELETE",
url:"/isard-sso-admin/groups/keycloak",
success: function(data)
{
console.log('SUCCESS')
// $("#modalImport").modal('hide');
// users_table.ajax.reload();
// groups_table.ajax.reload();
},
error: function(data)
{
alert('Something went wrong on our side...')
}
});
});
//DataTable Main renderer
var table = $('#groups').DataTable({
"ajax": {

View File

@ -5,6 +5,24 @@ $(document).on('shown.bs.modal', '#modalAddDesktop', function () {
$(document).ready(function() {
$('.btn-global-resync').on('click', function () {
$.ajax({
type: "GET",
url:"/isard-sso-admin/resync",
success: function(data)
{
table.ajax.reload();
// $("#modalImport").modal('hide');
// users_table.ajax.reload();
// groups_table.ajax.reload();
},
error: function(data)
{
alert('Something went wrong on our side...')
}
});
});
$('.btn-new').on('click', function () {
$("#modalAdd")[0].reset();
$('#modalAddDesktop').modal({

View File

@ -0,0 +1,19 @@
// SocketIO
socket = io.connect(location.protocol+'//' + document.domain + ':' + location.port+'/isard-sso-admin/sio');
socket.on('connect', function() {
connection_done();
console.log('Listening status socket');
});
socket.on('connect_error', function(data) {
connection_lost();
});
socket.on('update', function(data) {
var data = JSON.parse(data);
console.log('Status update')
console.log(data)
// var data = JSON.parse(data);
// drawUserQuota(data);
});

View File

@ -5,6 +5,25 @@ $(document).on('shown.bs.modal', '#modalAddDesktop', function () {
$(document).ready(function() {
$('.btn-global-resync').on('click', function () {
$.ajax({
type: "GET",
url:"/isard-sso-admin/resync",
success: function(data)
{
console.log('Reloaded')
table.ajax.reload();
// $("#modalImport").modal('hide');
// users_table.ajax.reload();
// groups_table.ajax.reload();
},
error: function(data)
{
alert('Something went wrong on our side...')
}
});
});
$('.btn-new').on('click', function () {
$("#modalAdd")[0].reset();
$('#modalAddDesktop').modal({

View File

@ -19,8 +19,6 @@
<link href="/isard-sso-admin/vendors/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Font Awesome -->
<link href="/isard-sso-admin/vendors/font-awesome/css/font-awesome.min.css" rel="stylesheet">
<!-- Font Linux -->
<link href="/isard-sso-admin/font-linux/font-linux.css" rel="stylesheet">
<!-- ion.rangeSlider -->
<link href="/isard-sso-admin/vendors/ion.rangeSlider/css/ion.rangeSlider.css" rel="stylesheet">
<link href="/isard-sso-admin/vendors/ion.rangeSlider/css/ion.rangeSlider.skinFlat.css" rel="stylesheet">
@ -116,8 +114,6 @@
<!-- isard initializers -->
<script src="/isard-sso-admin/static/dd.js"></script>
<!-- isard quota sse -->
<script src="/isard-sso-admin/static/js/quota.js"></script>
<!-- Requirements for fancy tree -->
<script src="/isard-sso-admin/static/vendor/fancytree/src/jquery-ui-dependencies/jquery-ui.min.js"></script>
<script src="/isard-sso-admin/static/vendor/fancytree/dist/jquery.fancytree.min.js"></script>

View File

@ -1,5 +1,5 @@
<div class="top_nav" >
<!-- <div class="nav_menu">
<div class="nav_menu">
<nav class="" role="navigation" >
<div class="nav toggle">
<a id="menu_toggle"><i class="fa fa-bars"></i></a>
@ -16,47 +16,37 @@
</ul>
</li>
<li role="presentation" class="quota-play">
<li role="presentation" class="sync-status">
<a href="javascript:" class="dropdown-toggle info-number" data-toggle="dropdown" aria-expanded="false">
<i class="fa fa-play"></i>
<i class="fa fa-spinner"></i>
<span class="badge"></span>
</a>
<ul id="menu1" class="dropdown-menu list-unstyled msg_list" role="menu">
<li>
<a>
<span class="image"><i class="fa fa-play"></i></span>
<span class="image"><i class="fa fa-user"></i></span>
<span>
<span>Desktops running</span>
<span>Users</span>
<span class="time"><span class="perc"></span>%</span>
</span>
<span class="message">
You have <span class="have"></span> running desktops of <span class="of"></span> in your quota.
Status <span class="have"></span> <span class="of"></span>
</span>
</a>
<a>
<span class="image"><i class="fa fa-users"></i></span>
<span>
<span>Groups</span>
<span class="time"><span class="perc"></span>%</span>
</span>
<span class="message">
Status <span class="have"></span> <span class="of"></span>
</span>
</a>
</li>
</ul>
</li>
<li role="presentation" class="quota-desktops">
<a href="javascript:" class="dropdown-toggle info-number" data-toggle="dropdown" aria-expanded="false">
<i class="fa fa-desktop"></i>
<span class="badge"></span>
</a>
<ul id="menu1" class="dropdown-menu list-unstyled msg_list" role="menu">
<li>
<a>
<span class="image"><i class="fa fa-desktop"></i></span>
<span>
<span>Desktops</span>
<span class="time"><span class="perc"></span>%</span>
</span>
<span class="message">
You have <span class="have"></span> desktops of <span class="of"></span> in your quota.
</span>
</a>
</li>
</ul>
</li>
</ul>
</nav>
</div> -->
</div>
</div>

View File

@ -53,5 +53,5 @@
{% block pagescript %}
<script src="/isard-sso-admin/static/js/restful.js"></script>
<script src="/isard-sso-admin/static/js/quota_socket.js"></script>
<script src="/isard-sso-admin/static/js/status_socket.js"></script>
{% endblock %}

View File

@ -16,6 +16,7 @@
<ul class="nav navbar-right panel_toolbox">
<li>
<a class="btn-new"><span style="color: #5499c7; "><i class="fa fa-plus"></i> Add new</span></a>
<a class="btn-delete_keycloak"><span style="color: #c75454; "><i class="fa fa-cross"></i> Delete all keycloak</span></a>
</li>
</ul>
<div class="clearfix"></div>

View File

@ -12,7 +12,7 @@
<h3>Administration</h3>
<div class="clearfix"></div>
<ul class="nav side-menu">
<!-- <li><a href="/"><i class="fa fa-home"></i> Home</a></li> -->
<li><a class="btn-global-resync"><span style="color: #c75454; "><i class="fa fa-refresh"></i> Resync</span></a></li>
<li><a href="/isard-sso-admin/users"><i class="fa fa-user"></i> Users</a></li>
<li><a href="/isard-sso-admin/groups"><i class="fa fa-users"></i> Groups</a></li>
<li><a href="/isard-sso-admin/roles"><i class="fa fa-user-secret"></i> Roles</a></li>

View File

@ -0,0 +1,32 @@
# This file is for unifying the coding style for different editors and IDEs
# editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.{json,html,css}]
indent_style = space
indent_size = 2
[*.js]
# indent_style = space
# indent_size = 2
indent_style = tab
indent_size = 4
[*.coffee]
indent_style = space
indent_size = 2
[*.md]
indent_style = space
[*.py]
indent_style = space

View File

@ -0,0 +1,10 @@
bin
doc
lib
node_modules
test/**
!test/unit/**/*.js
*.min.js
build/**
dist/**
!dist/jquery.js

View File

@ -0,0 +1,113 @@
extends:
- "eslint:recommended"
- "jquery"
- "plugin:prettier/recommended"
# Accept `window`, etc.
env:
browser: true
# Known globals (`false`: read-only)
globals:
define: false
require: false
module: false
jQuery: false
# Custom rules (see https://eslint.org/docs/rules/ )
# 0:off, 1:warn, 2:error
rules:
# --- Best Practices ---------------------------------------------------------
block-scoped-var: warn
# complexity: [warn, 20]
# consistent-return: warn
no-alert: error
no-caller: error
guard-for-in: warn
linebreak-style: warn
no-else-return: warn
# no-empty-function: warn
no-extend-native: error
no-eval: error
no-floating-decimal: error
no-implied-eval: error
# no-invalid-this: warn
no-labels: warn
no-lone-blocks: warn
no-loop-func: warn
no-new: error
no-new-func: warn
no-new-wrappers: warn
no-octal-escape: warn
no-return-assign: warn
no-script-url: warn
no-self-compare: warn
no-sequences: warn
no-throw-literal: error
no-unmodified-loop-condition: warn
no-unused-expressions: error
# Not enabled because we want to allow `self._superApply(self, args)`:
# no-useless-call: warn
no-useless-catch: warn
no-useless-return: warn
no-with: warn
prefer-promise-reject-errors: warn
radix: error
# vars-on-top: warn
wrap-iife:
- error
- any
yoda: warn
# --- Strict Mode ------------------------------------------------------------
# strict: error
# --- Variables --------------------------------------------------------------
# init-declarations: ["warn", "always"]
no-label-var: error
# no-shadow: warn
no-shadow-restricted-names: error
no-undef: error
no-undef-init: warn
# no-undefined: warn
no-use-before-define: error
# - error
# - functions: false
# --- Stylistic Issues -------------------------------------------------------
camelcase: error
# Not enabled because sometimes we set `node = this`:
# consistent-this: [warn, self] # use `self = this`
func-name-matching: warn
new-cap:
- error
- { "capIsNewExceptionPattern": "^\\$\\.." } # Allow `d = $.Deferred()`
no-bitwise: error
# no-multi-assign: warn
no-negated-condition: warn
no-unneeded-ternary: warn
no-new-object: error
one-var: # see also no-use-before-define
- warn
- consecutive
# one-var-declaration-per-line: warn
# --- Possible Errors --------------------------------------------------------
curly: error
eqeqeq: ["error", "always", {"null": "ignore"}]
no-cond-assign:
- error
- except-parens
no-constant-condition:
- error
- { "checkLoops": false }
no-empty:
- error
- {allowEmptyCatch: true}
# no-extra-parens: [warn, all, {conditionalAssign: false }]
no-nested-ternary: warn
no-unused-vars:
- error
# Allow unused vars in catch() and if start with '_'
- {args: none, caughtErrors: none, varsIgnorePattern: "^_" }

View File

@ -0,0 +1,27 @@
# Style guide rationale:
# Width 80 is default (and explicitly recommended) by prettier
# - 2 space indentation and trailing semicolons seem to be most popular
# https://hackernoon.com/what-javascript-code-style-is-the-most-popular-5a3f5bec1f6f
# It is also the prettier's default
# - Double quotes are default in prettier and mandatory in Black
# - Trailing comma produces smaller diffs
# BUT:
# As a first step, we keep the current whitespace setting:
# - use tabs
# - tabWitdh 4
printWidth: 80
useTabs: true
tabWidth: 4
# useTabs: false
# tabWidth: 2
semi: true
singleQuote: false
trailingComma: "es5"
bracketSpacing: true # because it's prettier's default
#requirePragma: true
#overrides:
# - files: "*.test.js"
# options:
# semi: true

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>fancytree</name>
<comment></comment>
<projects>
<project>fancytree_wiki</project>
<project>fancytree.wiki</project>
</projects>
<buildSpec>
</buildSpec>
<natures>
</natures>
<filteredResources>
<filter>
<id>1373147473034</id>
<name></name>
<type>10</type>
<matcher>
<id>org.eclipse.ui.ide.multiFilter</id>
<arguments>1.0-name-matches-false-false-node_modules</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>

View File

@ -0,0 +1,31 @@
# Configuration for `pyftpsync run ...` command line tool.
# See https://pyftpsync.readthedocs.io/ for details.
# This task is used by `pyftpsync run` if no task is passed as argument:
default_task: deploy
# Default settings shared by all tasks:
common_config:
exclude: archive,build,node_modules,.*,_*
progress: true
remote: ftp://wwwendt.de/tech/fancytree
# Make --root default (can be overridden by --here):
root: true
# verbose: 4
# List of task definitions:
tasks:
# sync_all:
# command: sync
# remote: ftp://wwwendt.de/tech/fancytree
deploy:
command: upload
delete_unmatched: true
deploy_force:
command: upload
delete_unmatched: true
delete: true
resolve: local
force: true

View File

@ -0,0 +1,26 @@
language: node_js
sudo: false
node_js:
- "10"
before_script:
- npm install -g grunt-cli
addons:
hosts:
- travis.dev
- localhost
matrix:
include:
- env: GRUNT_TASK=travis
# - env: GRUNT_TASK=travis-optional
# allow_failures:
# - env: GRUNT_TASK=travis-optional
script: grunt $GRUNT_TASK --verbose
env:
global:
- secure: VmlzKmxE+V+QZpvDuj5W41u2HTu2uTvW0aUi2p+2yhCHd7J5TFdOoECwIhTa/4VDEpnZwjLJXPd2q9kEn3+G0HpEqRMtKVTP/sM8y0JKUkprSCWV/y+pVX+0B9jQBAhEcjtkLDEGI3xVI8n+WV0Fig4kWecSCcSSUN5Mlbq5glQ=
- secure: ITp8qeoTyowtRqqFKPSjKq1tenmjt5ezNG/8ybEJQzxAMVGJ8bnyRPV1Aep0HB0ULP+GcYzDzGj5UeKM3hfWAJEfx+z1/HiHIMpJjEuGBz1JPfHx0lKcB7QfbhsRY3r8DVYptxdK9SyMisdIfCKApNMDW90RGDuALUdkLNPPXhI=

View File

@ -0,0 +1,128 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Fancytree - 3rd Party Example: Context menu</title>
<script src="../../../lib/jquery.js"></script>
<script src="../../../lib/jquery-ui.custom.js"></script>
<link href="../../../src/skin-win8/ui.fancytree.css" rel="stylesheet">
<script src="../../../src/jquery.fancytree.js"></script>
<!-- jquery-contextmenu (https://github.com/swisnl/jQuery-contextMenu) -->
<link rel="stylesheet"
href="//cdn.jsdelivr.net/npm/jquery-contextmenu@2.9.2/dist/jquery.contextMenu.min.css" />
<script src="//cdn.jsdelivr.net/npm/jquery-contextmenu@2.9.2/dist/jquery.contextMenu.min.js">
</script>
<script src="js/jquery.fancytree.contextMenu.js"></script>
<!-- Start_Exclude: This block is not part of the sample code -->
<link href="../../../lib/prettify.css" rel="stylesheet">
<script src="../../../lib/prettify.js"></script>
<link href="../../../demo/sample.css" rel="stylesheet">
<script src="../../../demo/sample.js"></script>
<!-- End_Exclude -->
<!-- Add code to initialize the tree when the document is loaded: -->
<script type="text/javascript">
$(function() {
$("#tree").fancytree({
extensions: ["contextMenu"],
source: {
url: "../../../demo/ajax-tree-local.json"
},
contextMenu: {
menu: {
"edit": { "name": "Edit", "icon": "edit" },
"cut": { "name": "Cut", "icon": "cut" },
"copy": { "name": "Copy", "icon": "copy" },
"paste": { "name": "Paste", "icon": "paste" },
"delete": { "name": "Delete", "icon": "delete", "disabled": true },
"sep1": "---------",
"quit": { "name": "Quit", "icon": "quit" },
"sep2": "---------",
"fold1": {
"name": "Sub group",
"items": {
"fold1-key1": { "name": "Foo bar" },
"fold2": {
"name": "Sub group 2",
"items": {
"fold2-key1": { "name": "alpha" },
"fold2-key2": { "name": "bravo" },
"fold2-key3": { "name": "charlie" }
}
},
"fold1-key3": { "name": "delta" }
}
},
"fold1a": {
"name": "Other group",
"items": {
"fold1a-key1": { "name": "echo" },
"fold1a-key2": { "name": "foxtrot" },
"fold1a-key3": { "name": "golf" }
}
}
},
actions: function(node, action, options) {
$("#selected-action")
.text("Selected action '" + action + "' on node " + node + ".");
}
},
lazyLoad: function(event, data) {
data.result = { url: "../../ajax-sub2.json" }
}
});
});
</script>
</head>
<body class="example">
<h1>Example: 'contextMenu' extension</h1>
<div class="description">
<p>
Integrate the external
<a href="https://github.com/swisnl/jQuery-contextMenu/" target="_blank" class="external">jQuery contextMenu plugin</a>
as Fancytree extension.
(<a href="https://github.com/mar10/fancytree/pull/3">Contributed by Tomas Norkūnas</a>.)
</p>
<p>
This is only one of more options. See the
<a href="../../../demo/index.html#sample-ext-menu.html">menu overview</a> for details.
</p>
<p>
Please click right mouse button on a node.
</p>
</div>
<!--
<div>
<label for="skinswitcher">Skin:</label> <select id="skinswitcher"></select>
</div>
-->
<!-- Tree wrapper -->
<div id="tree"></div>
<hr />
<div id="selected-action">Click right mouse button on a node.</div>
<!-- Start_Exclude: This block is not part of the sample code -->
<hr>
<p class="sample-links no_code">
<a class="hideInsideFS" href="https://github.com/mar10/fancytree">jquery.fancytree.js project home</a>
<a class="hideOutsideFS" href="#">Link to this page</a>
<a class="hideInsideFS" href="index.html">Example Browser</a>
<a href="#" id="codeExample">View source code</a>
</p>
<pre id="sourceCode" class="prettyprint" style="display:none"></pre>
<!-- End_Exclude -->
</body>
</html>

View File

@ -0,0 +1,85 @@
/**!
* jquery.fancytree.contextmenu.js
*
* Integrate the 'jQuery contextMenu' plugin as Fancytree extension:
* https://github.com/swisnl/jQuery-contextMenu
*
* Copyright (c) 2008-2018, Martin Wendt (https://wwWendt.de)
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*/
(function($, document) {
"use strict";
var initContextMenu = function(tree, selector, menu, actions) {
tree.$container.on("mousedown.contextMenu", function(event) {
var node = $.ui.fancytree.getNode(event);
if (node) {
$.contextMenu("destroy", "." + selector);
// node.setFocus(true);
node.setActive(true);
$.contextMenu({
selector: "." + selector,
events: {
show: function(options) {
options.prevKeyboard = tree.options.keyboard;
tree.options.keyboard = false;
},
hide: function(options) {
tree.options.keyboard = options.prevKeyboard;
node.setFocus(true);
},
},
build: function($trigger, e) {
node = $.ui.fancytree.getNode($trigger);
var menuItems = {};
if ($.isFunction(menu)) {
menuItems = menu(node);
} else if ($.isPlainObject(menu)) {
menuItems = menu;
}
return {
callback: function(action, options) {
if ($.isFunction(actions)) {
actions(node, action, options);
} else if ($.isPlainObject(actions)) {
if (
actions.hasOwnProperty(action) &&
$.isFunction(actions[action])
) {
actions[action](node, options);
}
}
},
items: menuItems,
};
},
});
}
});
};
$.ui.fancytree.registerExtension({
name: "contextMenu",
version: "@VERSION",
contextMenu: {
selector: "fancytree-title",
menu: {},
actions: {},
},
treeInit: function(ctx) {
this._superApply(arguments);
initContextMenu(
ctx.tree,
ctx.options.contextMenu.selector || "fancytree-title",
ctx.options.contextMenu.menu,
ctx.options.contextMenu.actions
);
},
});
})(jQuery, document);

View File

@ -0,0 +1,104 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>Fancytree - 3rd Party Example: Hotkeys</title>
<script src="../../../lib/jquery.js"></script>
<script src="../../../lib/jquery-ui.custom.js"></script>
<link href="../../../src/skin-win8/ui.fancytree.css" rel="stylesheet">
<script src="../../../src/jquery.fancytree.js"></script>
<script src="js/jquery.hotkeys.js"></script>
<script src="js/jquery.fancytree.hotkeys.js"></script>
<!-- Start_Exclude: This block is not part of the sample code -->
<link href="../../../lib/prettify.css" rel="stylesheet">
<script src="../../../lib/prettify.js"></script>
<link href="../../../demo/sample.css" rel="stylesheet">
<script src="../../../demo/sample.js"></script>
<!-- End_Exclude -->
<!-- Add code to initialize the tree when the document is loaded: -->
<script type="text/javascript">
$(function() {
$("#tree").fancytree({
extensions: ["hotkeys"],
source: {
url: "../../../demo/ajax-tree-local.json"
},
hotkeys: {
keyup: {
"shift+a": function(node) {
$("#selected-action").append(document.createTextNode("Key up 'Shift + a' on node " + node)).append("<br />");
}
},
keydown: {
"shift+a": function(node) {
$("#selected-action").append(document.createTextNode("Key down 'Shift + a' on node " + node)).append("<br />");
},
'ctrl+d': function(node, evt) {
$('#selected-action').append(document.createTextNode('Key down "Ctrl + d" on node ' + node)).append('<br />');
var new_node = $.extend(node.toDict(), {key: new Date().getTime().toString()}); // timestamp for dummy key
node.appendSibling(new_node);
evt.stopPropagation();
return false;
}
},
keypress: {
"shift+a": function(node) {
$("#selected-action").append(document.createTextNode("Key press 'Shift + a' on node " + node)).append("<br />");
}
}
},
lazyLoad: function(event, data) {
data.result = { url: "../../ajax-sub2.json" }
}
});
});
</script>
</head>
<body class="example">
<h1>Example: 'hotkeys' extension</h1>
<div class="description">
<p>
Integrate John Resig's
<a href="https://github.com/jeresig/jquery.hotkeys" target="_blank" class="external">'jQuery.Hotkeys' plugin</a>
as Fancytree extension.
</p>
<p>
Please activate one node and click "Shift + a".
</p>
</div>
<div>
<label for="skinswitcher">Skin:</label> <select id="skinswitcher"></select>
</div>
<!-- Tree wrapper -->
<div id="tree"></div>
<hr />
<div id="selected-action">Activate one node and click "Shift + a" or "Ctrl + d":<br /></div>
<!-- Start_Exclude: This block is not part of the sample code -->
<hr>
<p class="sample-links no_code">
<a class="hideInsideFS" href="https://github.com/mar10/fancytree">jquery.fancytree.js project home</a>
<a class="hideOutsideFS" href="#">Link to this page</a>
<a class="hideInsideFS" href="index.html">Example Browser</a>
<a href="#" id="codeExample">View source code</a>
</p>
<pre id="sourceCode" class="prettyprint" style="display:none"></pre>
<!-- End_Exclude -->
</body>
</html>

View File

@ -0,0 +1,35 @@
/**!
* jquery.fancytree.hotkeys.js
*
* Integrate the 'jQuery.Hotkeys' plugin as Fancytree extension:
* https://github.com/jeresig/jquery.hotkeys/
*
* Copyright (c) 2008-2018, Martin Wendt (https://wwWendt.de)
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*/
(function($, document) {
"use strict";
var initHotkeys = function(tree, data) {
$.each(data, function(event, keys) {
$.each(keys, function(key, handler) {
$(tree.$container).on(event, null, key, function(evt) {
var node = tree.getActiveNode();
return handler(node, evt);
// return false from the handler will stop default handling.
});
});
});
};
$.ui.fancytree.registerExtension({
name: "hotkeys",
version: "@VERSION",
hotkeys: {},
treeInit: function(ctx) {
this._superApply(arguments);
initHotkeys(this, ctx.options.hotkeys);
},
});
})(jQuery, document);

View File

@ -0,0 +1,196 @@
/*jslint browser: true*/
/*jslint jquery: true*/
/*
* jQuery Hotkeys Plugin
* Copyright 2010, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Based upon the plugin by Tzury Bar Yochay:
* http://github.com/tzuryby/hotkeys
*
* Original idea by:
* Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/
*/
/*
* One small change is: now keys are passed by object { keys: '...' }
* Might be useful, when you want to pass some other data to your handler
*/
(function(jQuery) {
jQuery.hotkeys = {
version: "0.8",
specialKeys: {
8: "backspace",
9: "tab",
10: "return",
13: "return",
16: "shift",
17: "ctrl",
18: "alt",
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: "'"
},
shiftNums: {
"`": "~",
"1": "!",
"2": "@",
"3": "#",
"4": "$",
"5": "%",
"6": "^",
"7": "&",
"8": "*",
"9": "(",
"0": ")",
"-": "_",
"=": "+",
";": ": ",
"'": "\"",
",": "<",
".": ">",
"/": "?",
"\\": "|"
},
// excludes: button, checkbox, file, hidden, image, password, radio, reset, search, submit, url
textAcceptingInputTypes: [
"text", "password", "number", "email", "url", "range", "date", "month", "week", "time", "datetime",
"datetime-local", "search", "color", "tel"],
options: {
filterTextInputs: true
}
};
function keyHandler(handleObj) {
if (typeof handleObj.data === "string") {
handleObj.data = {
keys: handleObj.data
};
}
// Only care when a possible input has been specified
if (!handleObj.data || !handleObj.data.keys || typeof handleObj.data.keys !== "string") {
return;
}
var origHandler = handleObj.handler,
keys = handleObj.data.keys.toLowerCase().split(" ");
handleObj.handler = function(event) {
// Don't fire in text-accepting inputs that we didn't directly bind to
if (this !== event.target && (/textarea|select/i.test(event.target.nodeName) ||
(jQuery.hotkeys.options.filterTextInputs &&
jQuery.inArray(event.target.type, jQuery.hotkeys.textAcceptingInputTypes) > -1))) {
return;
}
var special = event.type !== "keypress" && jQuery.hotkeys.specialKeys[event.which],
character = String.fromCharCode(event.which).toLowerCase(),
modif = "",
possible = {};
jQuery.each(["alt", "ctrl", "shift"], function(index, specialKey) {
if (event[specialKey + 'Key'] && special !== specialKey) {
modif += specialKey + '+';
}
});
// metaKey is triggered off ctrlKey erronously
if (event.metaKey && !event.ctrlKey && special !== "meta") {
modif += "meta+";
}
if (event.metaKey && special !== "meta" && modif.indexOf("alt+ctrl+shift+") > -1) {
modif = modif.replace("alt+ctrl+shift+", "hyper+");
}
if (special) {
possible[modif + special] = true;
}
else {
possible[modif + character] = true;
possible[modif + jQuery.hotkeys.shiftNums[character]] = true;
// "$" can be triggered as "Shift+4" or "Shift+$" or just "$"
if (modif === "shift+") {
possible[jQuery.hotkeys.shiftNums[character]] = true;
}
}
for (var i = 0, l = keys.length; i < l; i++) {
if (possible[keys[i]]) {
return origHandler.apply(this, arguments);
}
}
};
}
jQuery.each(["keydown", "keyup", "keypress"], function() {
jQuery.event.special[this] = {
add: keyHandler
};
});
})(jQuery || this.jQuery || window.jQuery);

View File

@ -0,0 +1,686 @@
# 2.36.1 / Unreleased
# 2.36.0 / 2020-07-15
* [Changed] #1005 Cast key to string in getNodeByKey()
* [Changed] #1013 ext-dnd5: log warning when jQuery is too old
* [Added] #1012 `dnd5.dropMarkerParent` allows usage in Webcomponents (i.e. shadow DOM)
* [Added] #1017 `copyFunctionsToData` allows also copying functions to the data property of the node
* [Fixed] #921 ext-edit / focus handling: Internet Explorer scrolls briefly
to the top/left after editing if the tree container is partially outside the viewport
* [Fixed] #1001 Invalid urls in skin-xp CSS
* [Fixed] ext-dnd5: dropEffectCallback=none was not reset in some cases
* [Fixed] #1018 ContextMenu extension always focuses the first node in the tree
# 2.35.0 / 2020-03-27
* [Changed] The `enableAspx` option will default to 'false' in the future.
For now, a warning is emitted, to explicitly set it or use the `postProcess`
event instead.
* [Added] #988 New option `dnd5.preventLazyParents` prevents dropping items on
unloaded lazy nodes (defaults to true)
* [Fixed] #983 lazyLoad with promise not calling postProcess
* [Fixed] #984 ext-edit: Exception when cancelling addSibling() or addChildren()
* [Fixed] #987 Lazy load puts "Load error" for content outside tree div
if parent folder is removed before loads ends
* [Fixed] #989 `node.toDict()` keeps empty `children` array
* [Fixed] #998 dnd5 triggering multiple loads of lazy nodes on hover
# 2.34.0 / 2019-12-26
* [DEPRECATED] jQuery UI widget methods:
Use `tree.METHOD()` instead of `$().fancytree("METHOD")`.
* [Added] `tree.debugTime()`, `tree.debugTimeEnd()` for debugging.
* [Added] `tree.destroy()` as alternative for `tree.widget.destroy()`.
* [Fixed] `$.ui.fancytree.getTree()` for Element arg.
* [Fixed] #973 when use ext-grid in one tree, other tree not use ext-grid has error on click.
* [Fixed] #974 ext-grid: too much output in production mode.
* [Fixed] #975 ext-grid: fix `tree.visitRows()` for empty tree.
* [Fixed] #978 ext-grid: addChildren() throws error when grid is hidden.
# 2.33.0 / 2019-10-29
* [Added] event `preInit` (fired before nodes are loaded).
* [Changed] jQuery is now a peerDependency (>=1.9), so users can install or re-use their own version.
* [Changed] ext-grid: `updateViewport` event is now also triggered for 'renumber' (i.e. expand, collapse)
* [Fixed] #963: tree.setExpanded() fails when autoScroll is enabled
* [Fixed] #964: handle case when `source` is not passed and no `<ul>` is embedded.
* [Fixed] #966: ext-dnd5: bug in function onDropEvent (case 'dragover')
* [Fixed] ext-filter: sub-match counter is one too high.
# 2.32.0 / 2019-09-10
* [Added] `node.hasClass()`
* [Added] `tree.applyCommand()` and `node.applyCommand()` (experimental!)
* [Added] `tree.isLoading()`
* [Added] `tree.toDict(includeRoot, callback)` and `node.toDict(recursive, callback)`:
callback can now return `false` or `"skip"` to skip nodes.
* [Fixed] #951 Hover issue in unselectable radio
* ext-dnd5: allow autoExpand even if dropping is prevented
* [Fixed] ext-filter: tree.rootNode.subMatchCount is now set correctly
* [Fixed] #955 node.navigate($.ui.keyCode.DOWN, false) does not return promise
* Stop testing with jQuery UI 1.10 and 1.11 (only jQuery UI 1.12 remains)
# 2.31.0 / 2019-05-30
* New extension **ext-grid** (experimental)<br>
This is a variant of `ext-table` that introduces viewport support, which
allows to maintain *huge* data models while only rendering as many DOM elements as necessary.<br>
Main changes:
- A viewport is defined by the number of visible rows (`tree.viewport.count`) and the index of the first visible row (`.start`)
- When scrolling, rows are not hidden, but removed and replaced. (This implies that the contents of embedded input fields should be written into the model immediately.)
* Refactored **ext-dnd5**<br>
Some **breaking changes** were made, mainly to improve handling of the dropEffect
(note that ext-dnd5 was and still is experimental and in progress).
- Remove `dnd5.dropEffect` callback option (set `data.dropEffect` instead)
- Remove `dnd5.dragImage` callback option (call `data.dataTransfer.setDragImage()`
- and set `data.useDefaultImage = false` instead)
- Rename `dnd5.preventRecursiveMoves` to `dnd5.preventRecursion`
- `dnd5.preventVoidMoves` now only aplies to 'move' operations, so we can *copy* before self
- [Added] `dnd5.preventSameParent` option
* [Added] hook `treeStructureChanged`
* [Added] methods `tree.findRelatedNode()`, `node.findRelatedNode()`
* [Added] method `node.getPath()`
* [Added] methods `$.ui.fancytree.getDragNode()`, `$.ui.fancytree.getDragNodeList()`
* [Added] event `updateViewport`
* [Added] tree option `.checkboxAutoHide` to hide checkboxes unless selected or hovered.
* [Added] tree option `.treeId` to prevent generation of a new sequence if the tree is re-initialized on a page.
* [Changed] `.getTree()` now also accepts the tree id string
* [Changed] #939: Keep a `partsel` flag that was explicitly set on a lazy node
* [Changed] ext-clones: make default key generation more robust against collisions
* [DEPRECATED] loaderror and lazyload options now throw an error instead of falling back to the correct loadError and lazyLoad
* [DEPRECATED] `tree.applyFilter` was removed
* [Fixed] #918 SVG font awesome 5 glyphs remove badge counter when parent node is collapsed
* [Fixed] #921 ext-edit respectively focus handling: Internet Explorer scrolls briefly
to the top/left of the tree container element after editing a node title if the
tree container is partially outside the viewport
* [Fixed] #931 Selecting grandparent selects all nodes of radiogroup in selectMode=3
* [Fixed] #946 dnd5 - Counter badge shows up, although the drag was cancelled from dragStart callback
* [Fixed] #947 dnd5 - dragEnd is fired only when re-ordering nodes within the same parent
* [Fixed] missing tree.error() and broken node.error()
* [Fixed] a bug in ext-logger
* Optimized performance of `expandAll()` and `ext-filter`
* Replace jshint/jscs with eslint
* Now testing on Puppeteer/Chromium instead of PhantonJS
* Use LF on Windows when checking out from git (added .gitattributes)
* Update to jQuery 3.4
# 2.30.2 / 2019-01-13
* Stop testing on IE 8 (no longer available on Saucelabs)
* [Fixed] #910 ext-dnd5 throws error for draggable column headers
* [Fixed] overrideMethod()'s calling context
* [Fixed] #912 ext-dnd5 + ext-glyph awesome5 does not show the icons when dragging an item
* [Fixed] #919 ext-multi: JavaScript error (event is not defined) in nodeKeydown
* [Fixed] #922 scrollIntoView for plain trees that don't have a scrollbar
* [Fixed] #924 ext-edit: Fix caret position for mouse-click in input
* [Fixed] #928 ext-dnd5: Fix `preventNonNodes` option
* [Fixed] #929 Fix `.getTree()` for jQuery 3
* [Fixed] #930 ext-dnd5: If drag does not start, no drag data should be stored
# 2.30.1 / 2018-11-13
* [Changed] Apply and enforce 'prettier' codestyle
* [Changed] #897 Set font for table extension
* [Fixed] #883: Font Awesome 4 animation spinner stays visible
* [Fixed] #894: Fancytree assertion failed: scrollParent should be a simple element or `window`, not document or body.
* [Fixed] #896 _requireExtension: order managment
* [Fixed] #899 Creating duplicate icon when removing node using extension columnview
* [Fixed] #900 ColumnView Extension - Toggle between parent and children not working
* [Fixed] #909 With quicksearch enabled, does not search for non-Latin character
# 2.30.0 / 2018-09-02
* [Changed] ext-edit trigger 'clickActive' now only triggers if no modifier keys
(shift, meta, control, ...) are pressed.<br>
Trigger 'shift+click' now only triggers if no other modifier key (control, ...)
is pressed.
* [Changed] #879 Rename ext-debug to ext-logger
(jquery.fancytree.debug.js => jquery.fancytree.logger.js)
* [Added] ext-multi is now deployed with jquery.fancytree-all.js (still experimental)
* [Added] tree.activateKey(key, opts) now has an `opts` argument
* [Added] `nodata` option (bool, string, or callback)
* [Added] ext-table `mergeStatusColumns` option
* [Added] new method `tree.enable(flag)`
* [Added] new method `tree.expandAll(flag, opts)`
* [Added] new methods `tree.setOption(name, value)` and `tree.getOption(name)`
* [Fixed] ES6 import dependency on jquery for jquery.fancytree.ui-deps.js
* [Fixed] #863 setActive() sometimes does not scroll node into view
* [Fixed] #877 postProcess may now also return the object form `{..., children: []}`
* [Fixed] #884 ReferenceError: jQuery is not defined at _simpleDeepMerge
* [Fixed] autoScroll, node.scrollIntoView(), and .makeVisible() now work for tables as well.
# 2.29.1 / 2018-06-27
* [Fixed] #848 Drag End Error with dnd5 extension (again):
fancytree-drag-remove class not removed on drop/dragend
* [Fixed] #875 ext-dnd5: Unwanted expanding of folder node when a node is dragged
before/after it
* [Fixed] #876 `triggerStart: []` does not override the default settings.<br>
**NOTE:** Options of type `Array` will now override the default option.
Before, arrays were merged with the default.
* [Fixed] ext-ariagrid default actions
# 2.29.0 / 2018-06-16
* [Changed]
`toggleEffect` now also accepts "toggle" or "slideToggle" to use jQuery effects instead of jQueryUI.<br>
`toggleEffect: { effect: "slideToggle", duration: 200 }` is now the default.<br>
'effects' component was removed from the bundled jquery.fancytree.ui-deps.js
* [Fixed] #746 Animation bug when expanding/collapsing nodes
* [Fixed] #848 Drag End Error with dnd5 extension
* [Fixed] #850 ext-childcounter doesn't work with custom icons
* [Fixed] #859 Fix log level configuration problem
* [Fixed] #865 toggleEffect animation (effect: blind) sometimes got stuck.
* Stop testing jQuery UI 1.9
* Update to jQuery 3.3.1
# 2.28.1 / 2018-03-19
* [Fixed] #844 Fix RTL for ext-table
* [Fixed] #845 Fix RTL for ext-dnd/ext-dnd5
* [Fixed] #764 Fix clicks on embedded <a> tags when filter is on
# 2.28.0 / 2018-03-02
* [Added] New extension ext-multi (experimental).
* [Added] ext-dnd5 support for dragging multiple selected nodes.
* [Added] #830 support for Font Awesome 5 (ext-glyph preset).
* [Added] ext-glyph supports SVG icons.
* [Added] `icon` option supports `{html: "..."}` content (also available for glyph-ext mapping).
* [Added] New method tree.visitRows()
* [Added] New method tree.selectAll()
* [Added] New method node.isBelowOf()
* [Added] New extension ext-fixed (experimental).
* [Changed] Re-rename clearData() to clearPersistData()
* [Changed] #828 Re-scale debugLevel from 0:quiet to 4:verbose, allowing to suppress warnings
and even errors.
* [Added] CSS helper classes:<br>
`.fancytree-helper-disabled`<br>
`.fancytree-helper-hidden` (replaces `ui-helper-hidden`)<br>
`.fancytree-helper-indeterminate-cb`<br>
`fancytree-helper-spin` for icon animations (replaces `glyphicon-spin`)
* [Fixed] #819: ext-filter: Handle nodes without title.
* [Fixed] #835: ext-dnd5: Accept drop externals after drag.
# 2.27.0 / 2017-12-16
* **BREAKING CHANGES:**
- `node.type` is now a first-class property of FancytreeNode.
Node data `{..., type: "foo"}` is now available as `node.type` (before: `node.data.type`).
- The properties `tree.types` and `tree.columns` have been added to Fancytree.
If passed with source data, they are now available directly instead of
`tree.data.types` or `tree.data.columns`.
* **Support patterns for node types:**
- The properties `node.type` and `tree.types` are recommended to implement node-type
specific configuration ([details](https://github.com/mar10/fancytree/wiki/TutorialNodeTypes)).
- Event `data` argument contains `typeInfo == tree.types[node.type]`.
* **Improved ext-glyph:**
- [Added] support for ligature icons (e.g. [material icons](https://material.io/icons/)).
- [Added] `icon` option can now return a dict to create a ligature icon.
* **Improved tree.loadKeyPath():**
- [Added] support for a custom path segment matcher.
This allows to have key paths with segments other than `node.key`.
- [Improved] the returned deferred promise now triggers `progress()` events which can
be used instead of the callback.
* The property `tree.columns` was added to Fancytree. Currently only reserved as
recommended pattern to pass global meta-data for ext-table.
* [Added] ext-edit: new trigger mode `clickActive` for option `triggerStart: [...]`.
* [Added] #798 Tooltip support for icons (dynamic option `iconTooltip`).
* [Added] #808 Pass custom storage providers to ext-persist.
* [Improved] ext-table no longer needs empty tbody/tr if thead is present.
* [Fixed] #796 UMD requirements for node/CommonJS
* [Fixed] #803 jquery.fancytree.ui-deps.js does not override existing widgets.
* [Fixed] #815 `<mark>` element missing in filtered nodes (minified bundle, IE 11).
* [Fixed] #816 findNextNode() doesn't set default for 'startNode' argument.
* [Added] Material Design demo
* [Added] Demo for Fancytree inside a jquery-confirm popup
* [Changed] String representation is now `"FancytreeNode@_4[title='My name']"`
* [DEPRECATED] `tree.clearCookies()`. Use <del>`tree.clearData()`</del> `tree.clearPersistData()` instead.
# 2.26.0 / 2017-11-04
* **BREAKING CHANGES:**
- [Fixed] #792 postProcess is now also called for non-Ajax sources.
* [Improved] LESS now compiles with webpack
* [Added] #791 ext-glyph support for radio buttons
* [Added] Color definitions for skin-awesome (taken from skin-lion)
* [Fixed] `$.ui.fancytree.getNode()` for ES6 environments
* [Fixed] #789 Wrong node is activated in IE, when clicking in unfocused container
# 2.25.0 / 2017-10-31
* **BREAKING CHANGES:**
- The `dist/src/` folder was renamed to `dist/modules`.
- Some directories like `demo/` are no longer part of the npm install.
* **Improved Module Support and Distribution**<br>
- The `dist/` folder now includes a `modules/` directory with fancytree core
and all extensions.
- All modules have UMD wrappers with defined dependencies.
- Internal jQuery UI dependencies are deployed as module and implicitly loaded.
- `jquery.fancytree/dist/modules/jquery.fancytree` is defined as
package main module, so Fancytree can be included using a simple<br>
`fancytree = require('jquery.fancytree')`.<br>
See [the docs](https://github.com/mar10/fancytree/wiki/TutorialIntegration)
for details.
- All modules now return the
[$.ui.fancytree object](https://wwWendt.de/tech/fancytree/doc/jsdoc/Fancytree_Static.html).
- [Added] new static method `$.ui.fancytree.createTree(elem, opts)`
* [Added] Source map files for `jquery.fancytree-all-deps.min.js`
* [Added] New extension ext-fixed (work-in-progress, experimental)
* [Fixed] #767: Input inside table head not working
* [Fixed] #768: Can't use keyboard to select nodes when `checkbox` option is false
* [Fixed] #782: wide extension - padding is off when checkbox option is changed
* [Fixed] #787: Fix getEventTarget() for custom icons
# 2.24.0 / 2017-08-26
* [Added] ext-glyph option `preset` (making the `map` option optional)
* [Fixed] Drop marker for ext-glyph + ext-dnd5
* [Fixed] #695: List AMD dependency on jQuery UI
* [Fixed] #735: Trying to set root node selected throws an error
* [Fixed] #740: Filtering must not consider escaped html entities
* [Fixed] #741: Passing an empty string ("") as filter calls clearFilter()
* [Fixed] #748: Drag start should not activate a node
* [Fixed] #761: ext-dnd5 throws exception when tree is empty
* [Fixed] #764: ext-filter breaks links
* Updated jsdoc to 3.5
# 2.23.0 / 2017-05-27
* **The external dependency on jQuery UI was removed**.<br>
A new library `jquery.fancytree-all-deps.min.js` is now added to the
distribution. It includes all dependencies on jQuery UI, so the only
remaining external dependency is jQuery.<br>
Continue to use `jquery.fancytree-all.min.js` if jQuery UI is already
included anyway.
* **Refactored the select behavior**<br>
[details](https://github.com/mar10/fancytree/wiki/SpecSelect):
<!-- [details](https://github.com/mar10/fancytree/wiki#selection-and-checkboxes) -->
* [Added] Allow control of selection status propagation with new options:
`unselectable`, `unselectableIgnore`, `unselectableStatus`.
* [Added] node option `radiogroup` to enable single-select for child nodes
* [Added] option `opts.noEvents` to `setSelected(flag, opts)`
* [Improved] Option 'checkbox' can have the string value "radio" (only has
the visual effect of replacing the icon)
* **BREAKING CHANGES:**
* The `hideCheckbox` option was removed. Use `checkbox: false` instead.<br>
Note that the `<li class='hideCheckbox'>` is still parsed from input
HTML and converted accordingly.
* The optional modifier class `<div class='fancytree-radio'>` was removed.
This class was used on the *container* to turn all checkbox items into
radio buttons.<br>
Instead, this class is now added to `<span class="fancytree-checkbox fancytree-radio">`.
Use the `tree.checkox: "radio"` option to activate this for the whole tree.
* The callback signature for the `tree.tooltip` option has changed to
`tooltip(event, data)`
* [Improved] `aria` option is now on by default
* Use the new dynamic options pattern for
`checkbox`, `icon`, `tooltip`, `unselectable`, `unselectableIgnore`,
`unselectableStatus`.<br>
See also <a href="https://github.com/mar10/fancytree/wiki#dynamic-options">dynamic options</a>.
* [Added] New method `node.visitSiblings()`
* [Added] #730 ext-persist option `expandOpts` is passed to setExpanded()
Allows to suppress animation or event generation.
# 2.22.5 / 2017-05-11
* [Improved] #709 experimental ext-ariagrid
# 2.22.4 / 2017-05-06
* [Improved] #709 experimental ext-ariagrid
# 2.22.3 / 2017-05-05
* [Improved] #709 experimental ext-ariagrid
# 2.22.2 / 2017-04-29
* [Fixed] #729 Fix regression with addChild performance improvements (#708)
# 2.22.1 / 2017-04-21
* [Fixed] #722 Fix regression with addChild performance improvements (#708)
# 2.22.0 / 2017-04-11
* [Added] ext-dnd5 now part of standard distribution
* [Added] #693 ext-dnd/dnd5: configurable drop marker offset
* [Added] #616 ext-wide: configurable left padding
* [Added] New method $.ui.fancytree.evalOption()
* [Improved] #601 ext-filter: improve performance (don't render hidden nodes)
* [Improved] ext-contextMenu: disable keyboard while popup is open and restore focus
* [Improved] #701 ext-hotkeys: Prevent default behavior on hot key combination
* [Improved] #708 speedup improvement for addChildren
* [Fixed] #680 ext-dnd5: top level nodes not draggable
* [Fixed] #681 ext-table: exception when a lazy node has `children: []`
* [Fixed] #699 ext-dnd5: Icon remains after dnd is cancelled
* [Fixed] #702 $.ui.fancytree.getNode(jQuery)' for jQuery v3.x
* [Fixed] #706 Fix DND where fancytree-title span is not a direct child due to custom layouts
* [Fixed] #712 When clicking in a scrolled tree for the first time, focus is not set properly
* [Fixed] #716 ext-wide: animation 'jumps' (jQuery UI 1.12)
* [Fixed] #717, #719 expand/collapse shows displaced child nodes when scrolled (jQuery UI 1.12)
* Update demos to jQuery 3.2.1 / jQuery UI 1.12.1
# 2.21.0 / 2017-01-15
* [Added] New extension 'ext-dnd5' (beta) for native HTML5 drag'n'drop support
* [Added] `rtl` option for right-to-left script support
* [Added] Add $.ui.fancytree.overrideMethod()
* [Added] hook `treeSetOption` allows extensions to update on option changes
* [Changed] standard CSS no longer defines `overflow: auto` for the container.
If the tree container has a fixed height, `overflow: auto` or `overflow: scroll`
should be added to make it scrollable.
(Otherwise this always would be the scroll parent for ext-dnd5.)
* [Improved] better support for initializing from embedded JSON using the
`data-type="json"` attribute
* [Fixed] corner case of #658 when ext-edit is loaded, but inactive
* [Fixed] #396 Don't load 'loading.gif' for glyph skins
* [Fixed] #675 ext-table: node.render(false) puts first node at end
# 2.20.0 / 2016-11-13
* [Added] #419 `modifyChild` event. This event is also a good place to
implement auto sorting (#559)
* [Added] #419 node.triggerModifyChild() and node.triggerModify()
* [Added] #595 add custom node filter to `generateFormElements()`
* [Added] #610 `tree.tooltip` option allows automatic or custom tooltips
* [Added] #620 improved tooltip escaping to allow newlines
* [DEPRECATED] `removeNode` event. Listen for `modifyChild` with operation
'remove' instead (which is fired on the parent)
* [Improved] ThemeRoller theme
* [Improved] ext-filter
- #297 add filter option 'hideExpanders' to remove expanders if all child
nodes are hidden by filter
- Filter options and the `opts` argument of `filterNodes()` / `filterBranches()`
have been unified
- [Fixed] #230 themeroller theme compatible with ext-filter
- [Fixed] #528 autoCollapse option blocks filter's autoExpand option
- [Fixed] #529 Filter: Mark matching nodes even if parent was matched in branch mode
- [Fixed] #643 Exceptions in ext-filter if expression contains special chars
- [Fixed] #658 ext-filter does not work with ext-edit `editCreateNode()`
* [Improved] #656 WAI-ARIA support
- Set focus to first node on first tab-in
- Support [home] and [end] keys
- Set aria-activedescendant on container to active ID
- Set aria-multiselectable on container if selectMode != 1
- Set aria-treeitem, -selected, -expanded, on title span instead `<li>`
* [Fixed] #576 `loadKeyPath()` sometimes gets the root wrong
* [Fixed] #615 Drag & drop helper icons lose indentation with table extension
* [Fixed] #632 Tabbing is not working if there is an anchor tag in treeview
* [Fixed] #644 New nodes created with ext-edit, are hidden in filtered trees
* [Fixed] #647 ext-table: tree.render(true) does not discard existing markup
* [Fixed] #659 handling of function keys, when quicksearch is on
* Use QUnit 2.0
# 2.19.0 / 2016-08-11
* [Added] #607 tree.enableUpdate() to temporarily disable rendering to improve
performance on bulk updates
* [Added] modifier class `.fancytree-connectors` to be set on container<br>
Note: Experimental! Not required for skin-xp and not compatible with ext-table
* [Added] #623 ext-edit: `data.originalEvent` is now passed to `beforeClose`
* [Fixed] #604 Set `source` option does not update tree
* [Fixed] #609 node.load(true); doesn't maintain expanded
* [Fixed] #621 Cannot focus embedded input controls
* [Improved] #611 Keyboard navigation honors autoScroll option
* Extensions inherit main version number
# 2.18.0 / 2016-05-02
* [Added] #586 node.discardMarkup() (useful in the `collapsed` event)
* [Added] #171 new option `.escapeTitles`
* [Added] new callback `.enhanceTitle()`
* [Fixed] #515 Html tags included in filter results
* [Fixed] #593 ext-dnd revert position fails for tables
# 2.17.0 / 2016-04-11
* [Added] `node.addClass()`, `.removeClass()`, and `.toggleClass()`
* [Added] ext-filter: matcher-callback for `tree.filterNodes()` may now return
`"branch"` and `"skip"`
* [Added] ext-filter: new option`nodata` allows to configure a status node for
empty results
* [Added] `digits` argument to `node.getIndexHier(separator, digits)`
* [Added] tree option `.tabindex`, default is "0". Pass "" to resolve #577
* [DEPRECATED] tree option `.tabbable`. Use `.tabindex` instead
* [Added] New option `mode='firstChild'` for `node.moveTo()`
* [Added] New option `digits=<int>` for `node.getIndexHier()`
* [Fixed] ext-filter: branch mode honors `autoExpand: true`
* [Fixed] #584: aria-labelledby ids not unique
* Update to jQuery UI 1.11.4
# 2.16.1 / 2016-03-18
* [Added] ext-glyph: new icon for 'nodata' status nodes
* [Fixed] #575 missing loading icon in non-bootstrap themes.<br>
Glyph themes now display status images in icon span (was expander span before)
# 2.16.0 / 2016-03-16
* [Added] ext-clones: new method node.setRefKey(refKey)
* [Added] modifier class `.fancytree-fade-expander` to be set on container
* [Added] ext-dnd: `.dragExpand()` callback to prevent auto-expand
* [Improved] load error reporting
* [Improved] bootstrap theme icons and style (samples use bootstrap 3.3)
* [Improved] status nodes don't have icons
* [Improved] pass data argument to `source` callback
* [Improved] Handle exceptions inside `postProcess`
* [Improved] #568 ext-dnd: Auto-expanding of collapsed nodes should also work
when dropping is not allowed
* [Improved] #567 ext-dnd: fix revert position
* [Improved] #565 ext-dnd: fix intermediate display of wrong icon (sending 'over' after 'enter')
* [Fixed] #569 node.navigate does not return a Promise object
* [Fixed] #563 `tree.reactivate(false)` sets fancytree-treefocus and `tree.reactivate(true)`
doesn't set keyboard focus
* [Fixed] #562 Node span tag leaks outside table cell
* [Fixed] #526 tree.setFocus() does not set keyboard focus
* Updated to jQuery 1.12.1
* Updated grunt devDependencies
* Add jQuery 3.0 beta to test suite
* Added LICENSE.txt to dist
# 2.15.0 / 2016-01-11
* [Changed] Renamed class `fancytree-statusnode-wait` to `fancytree-statusnode-loading`
* [Added] new event `renderStatusColumns`
* [DEPRECATED] ext-table option `customStatus`. Use `renderStatusColumns` instead
* [Added] new event `clickPaging`
* [Added] new mode `nodata` for use with node.setStatus()
* [Added] new method `node.addPagingNode()`
* [Added] new method `node.replaceWith()`
* [Added] new type 'paging' for `node.statusNodeType`
* [Added] #542 new method `node.getSelectedNodes()`
* [Added] Helper class `glyphicon-spin` to allow rotating loading icon with bootstrap3
* [Improved] #356: serialize load requests
* [Improved] #538: Be more robust if site css defines custom li:before
* [Improved] ext-table: Define table row templates in `<tbody>`
* [Improved] ext-table: `<thead>` is now optional if `<tbody>` contains `<td>`s
# 2.14.0 / 2015-12-19
* [CHANGED] #519 Refactored custom icon configuration:<br>
(see also the [theming tutorial](https://github.com/mar10/fancytree/wiki/TutorialTheming))
* [Added] `options.icon` option/callback.<br>
Valid values are true, false, a string containing a class name or image
url, or a callback returning that.
* [Changed] `node.icon` option. Valid values are true, false, or a string
containing a class name or image url.<br>
This option existed before, but was stored in the `node.data.icon` namespace,
and did not accept class names.
* [DEPRECATED] `options.iconClass` callback: use `options.icon` instead
* [DEPRECATED] `options.icons`: use `options.icon` instead
* [DEPRECATED] `node.data.iconclass` option: use `node.icon` instead
* [DEPRECATED] `node.data.icon` option: use `node.icon` instead
* [Added] `tree.clear()` method.
* [Added] #520 ext-persist: new event `beforeRestore`
* [Fixed] #533 table-ext: nodeSetExpanded triggers redundant events
# 2.13.0 / 2015-11-16
* [Changed] If a node is initalized as `lazy: true`, and `children: []`,
treat it as 'loaded leaf node'.<br>
This is consistent with a lazy node that has no children property at all (i.e.
`undefined`). This would issue a lazyLoad event and a resopnse of `[]` would
mark the node as leaf node.
* [Added] new function $.ui.fancytree.getTree()
* [Added] ext-filter methods node.isMatched() and tree.isFilterActive()
* [Added] CSS for ext-childcounter badges is now part of the standard themes
* [Added] ext-childcounter method node.updateCounter()`
* [Fixed] #507 data-hideCheckbox="true"
* [Fixed] #513 activeVisible option does not work on init
* [Fixed] #516 ExtPersist requires cookie.js even when not using cookies
# 2.12.0 / 2015-09-10
* [Changed] Documented `iconClass` callback and changed signature from
`iconClass(node)` to `iconClass(event, data)`
* [Added] ext-dnd events `initHelper` and `updateHelper`
* [Added] ext-dnd option `smartRevert`
* [Added] #146 sample for multi-node drag'n'drop
* [Added] Sample for modifier keys to control copy/move behavior while dragging
* [Added] `highlight` and `fuzzy` options to ext-filter
* [Added] `fireActivate` option to ext-persist (default: true)
* [Added] #496 new methods tree.findFirst() / .findAll()
* [Improved] clearFilter() performance #491
* [Improved] dnd registers global handlers to cancel on ESC and mousedown
* [Fixed] #475 Font color while editing node title with bootstrap skin
* [Fixed] #484 Glyph plugin: Missing margin-left for span.fancytree-custom-icon
* [Fixed] #486 node.render(true) moves the node to the end of the list
* [Fixed] #489 `focusOnClick` option is ignored for tables if 'dnd' is listed after 'table' extension
* [Fixed] #495 Double clicking on expander with lazy-load causes assertion error
# 2.11.0 / 2015-07-26
* [Changed] Adding `fancytree-plain` class to container (if not table), allowing for more efficient css
* [Changed] #434: Use data-uris to inline loading.gif image
* [Changed] #460: Use padding-left instead of margin-left for table indent
* [Changed] #465: Add `node` argument to the `toDict()` callback
* [Improved] Nicer bootstrap theme and added table to the example
* [Improved] #464: ext-dnd supports ext-glyph
* [Improved] #466: Add counter badges to ext-filter
* [Fixed] Win8 theme jumpy hover effects
* [Fixed] #411: ext-edit fails with ext-table, when edit was cancelled
* [Fixed] #463: ext-table: render(deep) does not work
* [Fixed] #470: Wide plugin not present in jquery.fancytree-all.min.js
# 2.10.2 / 2015-07-02
* [Fixed] Add `dist/skin-custom-1` sample (again)
* [Fixed] #459 Don't collapse root folder when last node is removed
# 2.10.1 / 2015-06-27
* [Changed] Undo #340: Revert dist folder layout to v2.9.0, but add
dist/skin-common.less
# 2.10.0 / 2015-06-26 [YANKED]
* [Changed] #340: New dist folder layout: moved skin-* folders into src/ folder
(**Note:** this change was reverted in v2.10.1)
* [Improved] Update to jQuery UI 1.11.4, jQuery 1.11.3
* [Improved] #340: add `dist/skin-common.less` to fix theme imports
* [Improved] #443 Support js-cookie (still compatible with jquery-cookie)
* [Fixed] #415 selected and unselectable shows unchecked checkbox
* [Fixed] #427 table + themeroller: apply color to TR
* [Fixed] #442 filterBranches shall use opts to allow autoExpand
* [Fixed] #445 enter key not handled correctly
* [Fixed] #449 After deleting last child, parent node remains expanded
* [Fixed] #452 destroy not removing nodes with ext-table
* [Fixed] #457 Autoscroll fails with lazyloading returning empty list
# 2.9.0 / 2015-04-19
* [Changed] ext-filter: `tree.filterNodes(filter, opts)` now accept an `opts`
object instead of `leavesOnly`
* [Improved] #417 only raise exception about data being a string if dataType is "json"
* [Added] #394 New option `autoExpand` for [ext-filter]
* [Fixed] #402, #405 rare exception in dnd events
* [Fixed] #420 nodeSetActive not returning promise
* [Fixed] #270 Keyboard focus not working when using dnd extension
# 2.8.1 / 2015-03-01
* [Improved] generateFormElements() new argument `opts`, default: `{stopOnParents: true}`
* [Fixed] #393 ext-table: checkboxColumnIdx not working
* [Fixed] #397 ext-edit: Creating sub category fails
* [Fixed] #403 generateFormElements() doesn't work with string args
# 2.8.0 / 2015-02-08
* [Changed] Deprecated ext-menu (was never officially supported, see http://localhost:8080/demo/index.html#sample-ext-menu.html)
* [Improved] Bluring the widget will now blur the focused node too.
* [Improved] Persistence will only set node focus if widget had focus (otherwise only activate the node).
* [Improved] Set default focus on first keypress to active node (first node otherwise)
* [Improved] #383 Accept [ECMAScript 6 Promise](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise) as source
* [Added] `_superApply()` for hook handlers.
* [Added] eventToString() supports mouse events
* [Fixed] persistence for focus (when using non-cookie storage)
* [Fixed] #391 Exception on autoscrolling filtered trees
# 2.7.0 / 2014-12-21
* [CHANGED] Dropped `fx` option. Use `toggleEffect` instead.
* [CHANGED] 'win8' and 'bootstrap' skins where modified to highlight the
title span instead of the node span, in order to be compatible with
[ext-wide]. The original skins are available as 'skin-win8-n' and
'skin-bootstrap-n' respectively.
* [Added] ext-wide extension (experimental)
* [Added] LESS files to distribution
* [Added] Publish on [cdnjs](https://cdnjs.com/libraries/jquery.fancytree)
* [Improved] tree.reactivate() returns a promise
* [Fixed] #246 Gaps when filtering in hide mode (patch by @lefunque)
* [Fixed] #287 wrong image on hovers
* [Fixed] #368 Standard browser behavior prevented (e.g. zoom with Ctrl+'+'/'-')
* [Fixed] #369 Suppress warning, when dropping top- on top-node
# 2.6.0 / 2014-11-29
* [Added] Option `focusOnSelect` to set focus when node is checked by a mouse
click (default: false)
* [Added] `restore` event, sent after ext-persist has restored the tree state
* [Improved] #359 Better navigation performance when skipping hidden nodes
* Publish on npm Registry
# 2.5.0 / 2014-11-23
* [CHANGED] [ext-persist] overrideSource option now defaults to true
* [Added] [ext-filter] Option `autoApply` re-applies filter on lazy loading
(on by default)
* [Added] quicksearch: navigate to next node by typing the first letters
* [Improved] [ext-dnd] Make draggable helper and parent configurable
* [Improved] #153 Add class `fancytree-unselectable` to respective nodes and
dim unselectable checkboxes
* [Improved] Update to jQuery 1.1.11, jQuery UI 1.11.2
* [Improved] New mode 'firstChild' for node.addNode()
* [Fixed] #324 Fix problem where minExpandLevel was not expanding root node
* [Fixed] #300 dnd.focusOnClick for jQuery UI 1.11
* [Fixed] #354 [ext-persist] with selectMode 3
# 2.4.1 / 2014-09-23
* [Fixed] Regression #323
# 2.4.0 / 2014-09-21
* [CHANGED] Renamed dist/jquery.fancytree-custom.min.js to jquery.fancytree-all.min.js
* [CHANGED] ext-edit callbacks no longer pass `data.value` (use `data.input.val()` instead).
* [Added] CDN support (http://www.jsdelivr.com/#!jquery.fancytree)
* [Added] New method `node.visitAndLoad()`
* [Added] New method `node.editCreateNode()` (ext-edit)
* [Added] New method `node.isRootNode()`
* [Added] New method `node.isTopLevel()`
* [Added] New option `id` to override default tree id
* [Added] New argument `stopOnParents` for tree.generateFormElements()
* [Improved] #294 node.load() should resolve 'ok', if node is already loaded
* [Improved] #293 minExpandLevel does not auto-expand
* [Improved] #313 Allow HTML in tooltips
* [Fixed] crash in scrollIntoView() when parent is `window`
* [Fixed] #305 Checkbox doesn't show with Glyph + Table
* [Fixed] #316 Fix hasChildren() when children = []
* [Fixed] #237 Ajax LoadError not updated in StatusNode with Table ext
* [Fixed] #295 loadKeyPath with multiple paths
* [DEPRECATED] node.isRoot(). Use node.isRootNode() instead
# 2.3.0 / 2014-08-17
* [CHANGED] renamed (undocumented) event 'loaderror' to 'loadError'
* [Added] postProcess now allows to signal error conditions (so it becomes easy to handle custom Ajax response formats)
* [Added] node.setStatus()
* [Added] ext-clones to the standard distribution.
* [Improved] loadError allows to return `false` to prevent default handling
* [Fixed] #258 Fix moveTo when moving a node to same parent
* [Fixed] #257 Glyph expander sometimes disappears
# 2.2.0 / 2014-06-28
* [Added] Option dnd.focusOnClick sets focus to tree widget, even when dragging
is enabled
* [Added] node.info()
* [Improved] #245 tree.generateInput() now returns data using PHPs array
convention, i.e. by appending brackets to the name: 'ft_1[]'.
* [Fixed] #250: Children lazy empty nodes remain checked when parent is
unchecked with hierarchical multi-selection
* [Fixed] #272 Navigation in filtered trees
# 2.1.0 / 2014-05-29
* [Added] #210: [ext-persist] optionally store information in sessionStorage or localStorage
* [Added] #64 [ext-filter] filterBranches() will restrict display to sub-trees
* [Added] New options 'scrollParent' and 'scrollOfs' are evaluated by node.scrollIntoView()
(which is also called on expand). This allows autoScroll to work with
[ext-table]: set scrollParent to `window` or a wrapper DIV with overflow: auto
* [Added] [ext-wide] use 100% wide selection bar (experimental)
* [Added] $.ui.fancytree.debounce()
* [Improved] [ext-columnview] css
* [Improved] skin-win8 now includes the loading.gif as inline CSS for faster response
* [Improved] Add 'fancytree-icon' class to icon IMG
* [Improved] css v-align for checkboxes and icons
* [Fixed] #217: persistence when node keys are numeric
* [Fixed] #228: html in node title prevents click
* [Fixed] #235: D'n'd helper is displaced, when window is scrolled
* [Fixed] #241: fromDict() does not update node title
* [Fixed] relative custom imagePath option
* [DEPRECATED] [ext-filter] Use filterNodes() instead of applyFilter()
* [DEPRECATED] [ext-filter] 'leavesOnly' option removed (see filterNodes())
# 2.0.0 / 2014-05-01
* Released 2.0.0
# 1.x
* See [Dynatree](https://code.google.com/p/dynatree/)

View File

@ -0,0 +1,629 @@
###
Build scripts for Fancytree
###
"use strict"
module.exports = (grunt) ->
grunt.initConfig
pkg:
grunt.file.readJSON("package.json")
# Project metadata, used by the <banner> directive.
meta:
banner: "/*! <%= pkg.title || pkg.name %> - @VERSION - @DATE\n" +
# "<%= grunt.template.today('yyyy-mm-dd HH:mm') %>\n" +
"<%= pkg.homepage ? ' * ' + pkg.homepage + '\\n' : '' %>" +
" * Copyright (c) <%= grunt.template.today('yyyy') %> <%= pkg.author.name %>;" +
" Licensed <%= _.map(pkg.licenses, 'type').join(', ') %>\n" +
" */\n"
# separator: "\n/*! --- Fancytree Plugin --- */\n"
clean:
build:
src: [ "build" ]
dist:
src: [ "dist" ]
post_build: # Remove unwanted files from build folder
src: [
"build/jquery.fancytree.*.min.js"
"build/jquery.fancytree.js"
"build/jquery-ui-dependencies/"
]
concat:
core_to_build:
options:
stripBanners: true
src: ["<banner:meta.banner>"
"src/jquery.fancytree.js"
]
dest: "build/jquery.fancytree.js"
bundle_to_build:
options:
stripBanners: true
src: [
"<%= meta.banner %>"
"src/jquery.fancytree.js"
# "src/jquery.fancytree.ariagrid.js"
"src/jquery.fancytree.childcounter.js"
"src/jquery.fancytree.clones.js"
# "src/jquery.fancytree.columnview.js"
"src/jquery.fancytree.dnd.js"
"src/jquery.fancytree.dnd5.js"
"src/jquery.fancytree.edit.js"
"src/jquery.fancytree.filter.js"
# "src/jquery.fancytree.fixed.js"
"src/jquery.fancytree.glyph.js"
# "src/jquery.fancytree.grid.js"
"src/jquery.fancytree.gridnav.js"
"src/jquery.fancytree.multi.js"
"src/jquery.fancytree.persist.js"
"src/jquery.fancytree.table.js"
"src/jquery.fancytree.themeroller.js"
"src/jquery.fancytree.wide.js"
]
dest: "build/jquery.fancytree-all.js"
amd_bundle_min:
options:
banner: "<%= meta.banner %>"
stripBanners: true
process: (src, fspec) ->
# Remove all comments, including /*! ... */
src = src.replace(/\/\*(.|\n)*\*\//g, "")
if /fancytree..+.min.js/.test(fspec)
# If it is an extension:
# Prepend a one-liner instead
fspec = fspec.substr(6) # strip 'build/'
src = "\n/*! Extension '" + fspec + "' */" + src
return src
src: [
"lib/amd-intro-require-native-ui.js"
"build/jquery.fancytree.min.js"
# "build/jquery.fancytree.ariagrid.min.js"
"build/jquery.fancytree.childcounter.min.js"
"build/jquery.fancytree.clones.min.js"
# "build/jquery.fancytree.columnview.min.js"
"build/jquery.fancytree.dnd.min.js"
"build/jquery.fancytree.dnd5.min.js"
"build/jquery.fancytree.edit.min.js"
"build/jquery.fancytree.filter.min.js"
# "build/jquery.fancytree.fixed.min.js"
"build/jquery.fancytree.glyph.min.js"
# "build/jquery.fancytree.grid.min.js"
"build/jquery.fancytree.gridnav.min.js"
"build/jquery.fancytree.multi.min.js"
"build/jquery.fancytree.persist.min.js"
"build/jquery.fancytree.table.min.js"
"build/jquery.fancytree.themeroller.min.js"
"build/jquery.fancytree.wide.min.js"
"lib/amd-outro.js"
]
dest: "build/jquery.fancytree-all.min.js"
all_deps: # un-minified, so we can generate a map file
options:
banner: "<%= meta.banner %>"
stripBanners: true
process: (src, fspec) ->
# Remove all comments, including /*! ... */
# (but keep disclaimer for jQuery-UI)
# if not /jquery-ui..+.js/.test(fspec)
# # if not /jquery-ui..+.min.js/.test(fspec)
# src = src.replace(/\/\*(.|\n)*\*\//g, "")
# # strip out AMD related code from jQuery-UI and make it an IIFE
# if /jquery-ui..+.min.js/.test(fspec)
# src = src.replace(/\(function.+jQuery\)}\)\((.+\)}\)})\);/, "!$1(jQuery);")
if /jquery.fancytree.js/.test(fspec)
src = "\n/*! Fancytree Core */" + src
if /fancytree..+.js/.test(fspec)
# If it is an extension:
# Prepend a one-liner instead
fspec = fspec.substr(4) # strip 'src/'
src = "\n/*! Extension '" + fspec + "' */" + src
return src
src: [
"<%= meta.banner %>"
# Inline jQuery UI custom (AMD header removed: IIFE only)
"src/jquery-ui-dependencies/jquery-ui-iife.js"
# Fancytree core and extensions, wrapped in UMD pattern
"lib/amd-intro-require-jquery.js"
"src/jquery.fancytree.js"
# "src/jquery.fancytree.ariagrid.js"
"src/jquery.fancytree.childcounter.js"
"src/jquery.fancytree.clones.js"
# "src/jquery.fancytree.columnview.js"
# "src/jquery.fancytree.dnd.js" # Draggable widget is not part of our custom jQuery UI dependencies
"src/jquery.fancytree.dnd5.js"
"src/jquery.fancytree.edit.js"
"src/jquery.fancytree.filter.js"
# "src/jquery.fancytree.fixed.js"
"src/jquery.fancytree.glyph.js"
# "src/jquery.fancytree.grid.js"
"src/jquery.fancytree.gridnav.js"
"src/jquery.fancytree.multi.js"
"src/jquery.fancytree.persist.js"
"src/jquery.fancytree.table.js"
"src/jquery.fancytree.themeroller.js"
"src/jquery.fancytree.wide.js"
"lib/amd-outro.js"
]
dest: "build/jquery.fancytree-all-deps.js"
connect:
forever:
options:
port: 8080
base: "./"
keepalive: true
dev: # pass on, so subsequent tasks (like watch) can start
options:
port: 8080
base: "./"
keepalive: false
# middleware: (connect) ->
# return [
# (req, res, next) ->
# res.setHeader('Access-Control-Allow-Origin', '*')
# res.setHeader('Access-Control-Allow-Methods', '*')
# next()
# ]
sauce: # Used by sauce tasks, see https://wiki.saucelabs.com/display/DOCS/Grunt-Saucelabs+Set+Up%2C+Configuration%2C+and+Usage
options:
# hostname: "localhost"
# hostname: "127.0.0.1"
# port: 8080
port: 9999
base: ""
keepalive: false
localhost_9999: # Start web server for Sauce live testing w/ manuallly run bin/sc.exe
options:
# hostname: "localhost"
port: 9999
base: ""
keepalive: true
copy:
build: # Copy development files to build folder
files: [{ # src/ => build/
expand: true # required for cwd
cwd: "src/"
src: [
"skin-**/*.{css,gif,md,png,less}"
"skin-common.less"
"*.txt"
]
dest: "build/"
}, { # src/ => build/modules/
expand: true
cwd: "src/"
src: [ "jquery.*.js" ]
dest: "build/modules/"
}, { # Top-level => build/
src: ["LICENSE.txt"]
dest: "build/"
}]
ui_deps: #
files: [{
src: "src/jquery-ui-dependencies/jquery.fancytree.ui-deps.js"
dest: "build/modules/jquery.fancytree.ui-deps.js"
}]
dist: # Copy build folder to dist/ (recursive)
files: [
{expand: true, cwd: "build/", src: ["**"], dest: "dist/"}
]
cssmin:
options:
report: "min"
build:
expand: true
cwd: "build/"
src: ["**/*.fancytree.css", "!*.min.css"]
dest: "build/"
ext: ".fancytree.min.css"
devUpdate:
main:
options:
reportUpdated: true
updateType: 'prompt' # 'report'
docco:
docs:
src: ["src/jquery.fancytree.childcounter.js"]
options:
output: "doc/annotated-src"
eslint:
options:
maxWarnings: 100
# format: "stylish"
# options:
# # See https://github.com/sindresorhus/grunt-eslint/issues/119
# quiet: true
# We have to explicitly declare "src" property otherwise "newer"
# task wouldn't work properly :/
build:
options:
ignore: false
src: [
"build/jquery.fancytree.js"
"build/jquery.fancytree-all.js"
"build/modules/*.js"
]
dev:
src: [
"src/*.js"
"3rd-party/**/jquery.fancytree.*.js"
# "test/**/test-*.js"
"demo/**/*.js"
]
fix:
options:
fix: true
src: [
"src/*.js"
"3rd-party/**/jquery.fancytree.*.js"
# "test/**/test-*.js"
"demo/**/*.js"
]
exec:
upload:
# FTP upload the demo files (requires https://github.com/mar10/pyftpsync)
stdin: true # Allow interactive console
cmd: "pyftpsync upload . ftp://www.wwwendt.de/tech/fancytree --progress --exclude build,node_modules,.*,_* --delete-unmatched"
upload_force:
# FTP upload the demo files (requires https://github.com/mar10/pyftpsync)
cmd: "pyftpsync upload . ftp://www.wwwendt.de/tech/fancytree --progress --exclude build,node_modules,.*,_* --delete-unmatched --resolve=local --force"
jsdoc:
build:
src: ["src/*.js", "doc/README.md"]
options:
destination: "doc/jsdoc"
template: "bin/jsdoc3-moogle",
configure: "doc/jsdoc.conf.json"
verbose: true
less:
development:
options:
# paths: ["src/"]
# report: "min"
compress: false
yuicompress: false
# optimization: 10
# webpack uses /dist/skin-common.less as root path
# grunt-less uses /dist/skin-Xxx/ui.fancyree.less as root path
# So we define our theme LESS files for webpack compatibility
# and fix it for grunt-less here:
rootpath: ".."
files: [
{expand: true, cwd: "src/", src: "**/ui.fancytree.less", dest: "src/", ext: ".fancytree.css"}
]
qunit:
options:
httpBase: "http://localhost:8080"
# httpBase: "http://127.0.0.1:8080"
build: [
"test/unit/test-core-build.html"
]
develop: [
"test/unit/test-core.html"
"test/unit/test-ext-filter.html"
"test/unit/test-ext-table.html"
"test/unit/test-ext-misc.html"
]
dist: [
"test/unit/test-core-dist.html"
]
replace: # grunt-text-replace
production:
src: ["build/**/*.{js,less,css}"]
overwrite : true
replacements: [ {
from : /@DATE/g
# https://github.com/felixge/node-dateformat
to : "<%= grunt.template.today('isoUtcDateTime') %>"
},{
from : /buildType:\s*\"[a-zA-Z]+\"/g
to : "buildType: \"production\""
},{
from : /debugLevel:\s*[0-9]/g
to : "debugLevel: 3"
} ]
release:
src: ["dist/**/*.{js,less,css}"]
overwrite : true
replacements: [ {
from : /@VERSION/g
to : "<%= pkg.version %>"
} ]
"saucelabs-qunit":
options:
build: process.env.TRAVIS_JOB_ID
throttled: 5
framework: "qunit"
# Map of extra parameters to be passed to sauce labs. example:
# {'video-upload-on-pass': false, 'idle-timeout': 60}
sauceConfig:
"video-upload-on-pass": false
recordVideo: true
# Needed for Edge/Windows (as of 2019-06-02) and Firefox(?)
iedriverVersion: "3.141.59"
seleniumVersion: "3.141.59"
# Array of optional arguments to be passed to the Sauce Connect tunnel.
# See https://saucelabs.com/docs/additional-config
tunnelArgs: [
'-v',
'--logfile', 'saucelabs-tunnel.log',
'--tunnel-domains', 'localhost,travis.dev'
# '--direct-domains', 'google.com'
]
triage:
options:
testname: "Triage"
build: "triage"
# urls: ["http://wwwendt.de/tech/fancytree/test/unit/test-core.html"]
# urls: ["http://127.0.0.1:9999/test/unit/test-jQuery19-ui19.html"]
# urls: ["http://127.0.0.1:9999/test/unit/test-jQuery1x-mig-ui1x.html"]
urls: ["http://localhost:9999/test/unit/test-core.html"]
# urls: ["http://127.0.0.1:9999/test/unit/test-core.html"]
# tunneled: false # Use bin/sc manually
browsers: [
# Issue #825
# { browserName: "chrome", version: "dev", platform: "Windows 10" }
# { browserName: "internet explorer", version: "9", platform: "Windows 7" }
# { browserName: "internet explorer", version: "8", platform: "Windows 7" }
# { browserName: "chrome", version: "latest", platform: "Windows 10" }
# { browserName: "microsoftedge", version: "latest", platform: "Windows 10" }
# { browserName: "safari", version: "12", platform: "macOS 10.14" }
{ browserName: "firefox", version: "latest", platform: "Windows 10" }
]
ui_112:
options:
testname: "Fancytree qunit tests (jQuery 3, jQuery UI 1.12)"
# urls: ["http://wwwendt.de/tech/fancytree/test/unit/test-core.html"]
urls: ["http://localhost:9999/test/unit/test-core.html"]
# urls: ["http://127.0.0.1:9999/test/unit/test-core.html"]
# jQuery 3 supports IE 9+ and latest Chrome/Edge/Firefox/Safari (-1)
# jQuery UI 1.12 supports IE 11 and latest Chrome/Edge/Firefox/Safari (-1)
browsers: [
{ browserName: "chrome", version: "latest", platform: "Windows 10" }
{ browserName: "chrome", version: "latest-1", platform: "Windows 10" }
{ browserName: "firefox", version: "latest", platform: "Windows 10" }
{ browserName: "firefox", version: "latest-1", platform: "Windows 10" }
{ browserName: "firefox", version: "latest", platform: "Linux" }
{ browserName: "microsoftedge", version: "latest", platform: "Windows 10" }
{ browserName: "microsoftedge", version: "latest-1", platform: "Windows 10" }
{ browserName: "internet explorer", version: "11", platform: "Windows 8.1" }
{ browserName: "internet explorer", version: "10", platform: "Windows 8" }
{ browserName: "internet explorer", version: "9", platform: "Windows 7" }
# Test Saucelabs:
# { browserName: "chrome", version: "latest", platform: "macOS 10.14" }
# { browserName: "firefox", version: "latest", platform: "macOS 10.14" }
]
# ui_111:
# options:
# testname: "Fancytree qunit tests (jQuery 1.11, jQuery UI 1.11)"
# # urls: ["http://wwwendt.de/tech/fancytree/test/unit/test-jQuery111-ui111.html"]
# urls: ["http://127.0.0.1:9999/test/unit/test-jQuery111-ui111.html"]
# # jQuery 1.11 supports IE + and latest Chrome/Edge/Firefox/Safari (-1)
# # jQuery UI 1.11 supports IE 7+ and ?
# browsers: [
# { browserName: "internet explorer", version: "10", platform: "Windows 8" }
# # Issue #842:
# # { browserName: "safari", version: "7", platform: "OS X 10.9" }
# { browserName: "safari", version: "8", platform: "OS X 10.10" }
# ]
# ui_110:
# options:
# testname: "Fancytree qunit tests (jQuery 1.10, jQuery UI 1.10)"
# # urls: ["http://wwwendt.de/tech/fancytree/test/unit/test-jQuery110-ui110.html"]
# urls: ["http://127.0.0.1:9999/test/unit/test-jQuery110-ui110.html"]
# # jQuery 1.10 dropped support for IE 6
# # jQuery UI 1.10 supports IE 7+ and ?
# browsers: [
# # { browserName: "internet explorer", version: "8", platform: "Windows 7" }
# { browserName: "internet explorer", version: "9", platform: "Windows 7" }
# ]
beta: # This tests are allowed to fail in the travis matrix
options:
testname: "Fancytree qunit tests ('dev' browser versions)"
# urls: ["http://wwwendt.de/tech/fancytree/test/unit/test-core.html"]
urls: ["http://localhost:9999/test/unit/test-core.html"]
# urls: ["http://127.0.0.1:9999/test/unit/test-core.html"]
browsers: [
# Issue #825
{ browserName: "chrome", version: "dev", platform: "Windows 10" } #, chromedriverVersion: "2.46.0" }
# FF.dev is problematic: https://support.saucelabs.com/hc/en-us/articles/225253808-Firefox-Dev-Beta-Browser-Won-t-Start
{ browserName: "firefox", version: "dev", platform: "Windows 10" }
# 2019-06-02: known problem with Saucelabs using localhost on macOS:
{ browserName: "safari", version: "12", platform: "macOS 10.14" }
{ browserName: "safari", version: "11", platform: "macOS 10.13" }
{ browserName: "safari", version: "10", platform: "macOS 10.12" }
{ browserName: "safari", version: "9", platform: "OS X 10.11" }
# { browserName: "safari", version: "8", platform: "OS X 10.10" }
]
uglify:
src_to_build:
options: # see https://github.com/gruntjs/grunt-contrib-uglify/issues/366
report: "min"
# preserveComments: "some"
preserveComments: /(?:^!|@(?:license|preserve|cc_on))/
output:
ascii_only: true # #815
files: [
{
src: ["**/jquery.fancytree*.js", "!*.min.js"]
cwd: "src/"
dest: "build/"
expand: true
rename: (dest, src) ->
folder = src.substring(0, src.lastIndexOf("/"))
filename = src.substring(src.lastIndexOf("/"), src.length)
filename = filename.substring(0, filename.lastIndexOf("."))
return dest + folder + filename + ".min.js"
}
]
all_deps:
options: # see https://github.com/gruntjs/grunt-contrib-uglify/issues/366
report: "min"
sourceMap: true
# preserveComments: "some"
preserveComments: /(?:^!|@(?:license|preserve|cc_on))/
output:
ascii_only: true # #815
files: [
{
src: ["jquery.fancytree-all-deps.js"]
cwd: "build/"
dest: "build/"
expand: true
rename: (dest, src) ->
folder = src.substring(0, src.lastIndexOf("/"))
filename = src.substring(src.lastIndexOf("/"), src.length)
filename = filename.substring(0, filename.lastIndexOf("."))
return dest + folder + filename + ".min.js"
}
]
watch:
less:
files: "src/**/*.less"
tasks: ["less:development"]
eslint:
options:
atBegin: true
files: ["src/*.js", "test/unit/*.js", "demo/**/*.js"]
tasks: ["eslint:dev"]
yabs:
release:
common: # defaults for all tools
manifests: ['package.json', 'bower.json']
# The following tools are run in order:
run_test: { tasks: ['test'] }
check: { branch: ['master'], canPush: true, clean: true, cmpVersion: 'gte' }
bump: {} # 'bump' also uses the increment mode `yabs:release:MODE`
run_build: { tasks: ['make_dist'] }
commit: { add: '.' }
tag: {}
push: { tags: true, useFollowTags: true },
githubRelease:
repo: 'mar10/fancytree'
draft: false
npmPublish: {}
bump_develop: { inc: 'prepatch' }
commit_develop: { message: 'Bump prerelease ({%= version %}) [ci skip]' }
push_develop: {}
# ----------------------------------------------------------------------------
# Load "grunt*" dependencies
for key of grunt.file.readJSON("package.json").devDependencies
grunt.loadNpmTasks key if key isnt "grunt" and key.indexOf("grunt") is 0
# Register tasks
grunt.registerTask "server", ["connect:forever"]
grunt.registerTask "dev", ["connect:dev", "watch"]
# grunt.registerTask "prettier", ["eslint:fix"]
grunt.registerTask "format", ["eslint:fix"]
grunt.registerTask "test", [
"eslint:dev",
# "csslint",
# "htmllint",
"connect:dev" # start server
"qunit:develop"
]
grunt.registerTask "sauce", [
"connect:sauce",
"saucelabs-qunit:ui_112",
# "saucelabs-qunit:ui_111",
# "saucelabs-qunit:ui_110",
]
grunt.registerTask "sauce-optional", [
"connect:sauce",
"saucelabs-qunit:beta",
]
grunt.registerTask "sauce-triage", ["connect:sauce", "saucelabs-qunit:triage"]
# 2020-01-26 Saucelabs tests don't work.
# Disable them in travis for now:
grunt.registerTask "travis", ["test"]
grunt.registerTask "travis-optional", []
# if parseInt(process.env.TRAVIS_PULL_REQUEST, 10) > 0
# # saucelab keys do not work on forks
# # http://support.saucelabs.com/entries/25614798
# grunt.registerTask "travis", ["test"]
# grunt.registerTask "travis-optional", []
# else
# grunt.registerTask "travis", ["test", "sauce"]
# grunt.registerTask "travis-optional", ["sauce-optional"]
grunt.registerTask "default", ["test"]
grunt.registerTask "ci", ["test"] # Called by 'npm test'
# Update package.json to latest versions (interactive)
grunt.registerTask "dev-update", ["devUpdate"]
grunt.registerTask "build", [
"less:development"
"format"
# `test` also starts the connect:dev server
"test"
"jsdoc:build"
"docco:docs"
"clean:build"
"copy:build"
"cssmin:build"
"concat:core_to_build"
"concat:bundle_to_build"
"uglify:src_to_build"
"concat:amd_bundle_min"
"concat:all_deps"
"uglify:all_deps"
"clean:post_build"
"replace:production"
"eslint:build"
"copy:ui_deps"
"qunit:build"
]
grunt.registerTask "make_dist", [
# `build` also starts the connect:dev server
"build"
"clean:dist"
"copy:dist"
"clean:build"
"replace:release"
# "eslint:dist" # should rather use grunt-jsvalidate for minified output
"qunit:dist"
]
grunt.registerTask "upload", [
"build"
"exec:upload"
]
grunt.registerTask "upload_force", [
"build"
"exec:upload_force"
]

View File

@ -0,0 +1,21 @@
Copyright 2008-2020 Martin Wendt,
https://wwWendt.de/
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,71 @@
# ![logo](doc/logo.png?raw=true) Fancytree
[![GitHub version](https://badge.fury.io/gh/mar10%2Ffancytree.svg)](https://github.com/mar10/fancytree/releases/latest)
[![Build Status](https://travis-ci.org/mar10/fancytree.svg?branch=master)](https://travis-ci.org/mar10/fancytree)
[![npm](https://img.shields.io/npm/dm/jquery.fancytree.svg)](https://www.npmjs.com/package/jquery.fancytree)
[![jsDelivr](https://data.jsdelivr.com/v1/package/npm/jquery.fancytree/badge)](https://www.jsdelivr.com/package/npm/jquery.fancytree)
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
[![StackOverflow: fancytree](https://img.shields.io/badge/StackOverflow-fancytree-blue.svg)](https://stackoverflow.com/questions/tagged/fancytree)
<!--
[![Selenium Test Status](https://saucelabs.com/buildstatus/sauce-fancytree)](https://saucelabs.com/u/sauce-fancytree)
-->
Fancytree (sequel of [DynaTree 1.x](https://code.google.com/p/dynatree/)) is a
JavaScript tree view / tree grid plugin with support for keyboard, inline editing,
filtering, checkboxes, drag'n'drop, and lazy loading.
[ ![sample](doc/teaser2.png?raw=true) ](https://wwWendt.de/tech/fancytree/demo "Live demo")
### Status
[![GitHub version](https://badge.fury.io/gh/mar10%2Ffancytree.svg)](https://github.com/mar10/fancytree/releases/latest)
See the [change log](https://github.com/mar10/fancytree/blob/master/CHANGELOG.md)
for details.
### Get Started
* [Try the live demo](https://wwWendt.de/tech/fancytree/demo).
* [Read the documentation](https://github.com/mar10/fancytree/wiki).
* [Check the Q&A forum](https://groups.google.com/forum/#!forum/fancytree) or
[Stackoverflow](http://stackoverflow.com/questions/tagged/fancytree) if you have questions.
* Play with [jsFiddle](http://jsfiddle.net/mar10/KcxRd/),
[CodePen](https://codepen.io/mar10/pen/WMWrbq),
or [Plunker](http://plnkr.co/edit/8sdy3r?p=preview).
* [Contribute](https://github.com/mar10/fancytree/wiki/HowtoContribute)
### ES6 Quickstart
```js
import $ from "jquery";
import 'jquery.fancytree/dist/skin-lion/ui.fancytree.less'; // CSS or LESS
import {createTree} from 'jquery.fancytree';
import 'jquery.fancytree/dist/modules/jquery.fancytree.edit';
import 'jquery.fancytree/dist/modules/jquery.fancytree.filter';
const tree = createTree('#tree', {
extensions: ['edit', 'filter'],
source: {...},
...
});
// Note: Loading and initialization may be asynchronous, so the nodes may not be accessible yet.
```
See [module loader support](https://github.com/mar10/fancytree/wiki#use-a-module-loader) and
[API docs](https://wwWendt.de/tech/fancytree/doc/jsdoc/Fancytree_Static.html#createTree).
### Credits
Thanks to all [contributors](https://github.com/mar10/fancytree/contributors).
<!--
### Browser Status Matrix
[![Selenium Test Status](https://saucelabs.com/browser-matrix/sauce-fancytree.svg)](https://saucelabs.com/u/sauce-fancytree)
-->

View File

@ -0,0 +1,22 @@
The default template for JSDoc 3 uses: [the Taffy Database library](http://taffydb.com/) and the [Underscore Template library](http://underscorejs.org/).
## Customized
Modified by Martin Wendt in 2017-08.
Changes are marked with `<!-- Start MOOGLE Changes -->` or `// --- Start MOOGLE Changes`
* Add a 'Methods:' section for class views, between 'Properties:' and 'Methods details'
* Add google analytics hooks
* Add a 'Fork me on Github'
## Generating Typeface Fonts
The default template uses the [OpenSans](https://www.google.com/fonts/specimen/Open+Sans) typeface. The font files can be regenerated as follows:
1. Open the [OpenSans page at Font Squirrel](<http://www.fontsquirrel.com/fonts/open-sans>).
2. Click on the 'Webfont Kit' tab.
3. Either leave the subset drop-down as 'Western Latin (Default)', or, if we decide we need more glyphs, than change it to 'No Subsetting'.
4. Click the 'DOWNLOAD @FONT-FACE KIT' button.
5. For each typeface variant we plan to use, copy the 'eot', 'svg' and 'woff' files into the 'templates/default/static/fonts' directory.

View File

@ -0,0 +1,701 @@
'use strict';
var doop = require('jsdoc/util/doop');
var env = require('jsdoc/env');
var fs = require('jsdoc/fs');
var helper = require('jsdoc/util/templateHelper');
var logger = require('jsdoc/util/logger');
var path = require('jsdoc/path');
var taffy = require('taffydb').taffy;
var template = require('jsdoc/template');
var util = require('util');
var htmlsafe = helper.htmlsafe;
var linkto = helper.linkto;
var resolveAuthorLinks = helper.resolveAuthorLinks;
var hasOwnProp = Object.prototype.hasOwnProperty;
var data;
var view;
var outdir = path.normalize(env.opts.destination);
function find(spec) {
return helper.find(data, spec);
}
function tutoriallink(tutorial) {
return helper.toTutorial(tutorial, null, {
tag: 'em',
classname: 'disabled',
prefix: 'Tutorial: '
});
}
function getAncestorLinks(doclet) {
return helper.getAncestorLinks(data, doclet);
}
function hashToLink(doclet, hash) {
var url;
if ( !/^(#.+)/.test(hash) ) {
return hash;
}
url = helper.createLink(doclet);
url = url.replace(/(#.+|$)/, hash);
return '<a href="' + url + '">' + hash + '</a>';
}
function needsSignature(doclet) {
var needsSig = false;
// function and class definitions always get a signature
if (doclet.kind === 'function' || doclet.kind === 'class') {
needsSig = true;
}
// typedefs that contain functions get a signature, too
else if (doclet.kind === 'typedef' && doclet.type && doclet.type.names &&
doclet.type.names.length) {
for (var i = 0, l = doclet.type.names.length; i < l; i++) {
if (doclet.type.names[i].toLowerCase() === 'function') {
needsSig = true;
break;
}
}
}
// and namespaces that are functions get a signature (but finding them is a
// bit messy)
else if (doclet.kind === 'namespace' && doclet.meta && doclet.meta.code &&
doclet.meta.code.type && doclet.meta.code.type.match(/[Ff]unction/)) {
needsSig = true;
}
return needsSig;
}
function getSignatureAttributes(item) {
var attributes = [];
if (item.optional) {
attributes.push('opt');
}
if (item.nullable === true) {
attributes.push('nullable');
}
else if (item.nullable === false) {
attributes.push('non-null');
}
return attributes;
}
function updateItemName(item) {
var attributes = getSignatureAttributes(item);
var itemName = item.name || '';
if (item.variable) {
itemName = '&hellip;' + itemName;
}
if (attributes && attributes.length) {
itemName = util.format( '%s<span class="signature-attributes">%s</span>', itemName,
attributes.join(', ') );
}
return itemName;
}
function addParamAttributes(params) {
return params.filter(function(param) {
return param.name && param.name.indexOf('.') === -1;
}).map(updateItemName);
}
function buildItemTypeStrings(item) {
var types = [];
if (item && item.type && item.type.names) {
item.type.names.forEach(function(name) {
types.push( linkto(name, htmlsafe(name)) );
});
}
return types;
}
function buildAttribsString(attribs) {
var attribsString = '';
if (attribs && attribs.length) {
attribsString = htmlsafe( util.format('(%s) ', attribs.join(', ')) );
}
return attribsString;
}
function addNonParamAttributes(items) {
var types = [];
items.forEach(function(item) {
types = types.concat( buildItemTypeStrings(item) );
});
return types;
}
function addSignatureParams(f) {
var params = f.params ? addParamAttributes(f.params) : [];
f.signature = util.format( '%s(%s)', (f.signature || ''), params.join(', ') );
}
function addSignatureReturns(f) {
var attribs = [];
var attribsString = '';
var returnTypes = [];
var returnTypesString = '';
var source = f.yields || f.returns;
// jam all the return-type attributes into an array. this could create odd results (for example,
// if there are both nullable and non-nullable return types), but let's assume that most people
// who use multiple @return tags aren't using Closure Compiler type annotations, and vice-versa.
if (source) {
source.forEach(function(item) {
helper.getAttribs(item).forEach(function(attrib) {
if (attribs.indexOf(attrib) === -1) {
attribs.push(attrib);
}
});
});
attribsString = buildAttribsString(attribs);
}
if (source) {
returnTypes = addNonParamAttributes(source);
}
if (returnTypes.length) {
returnTypesString = util.format( ' &rarr; %s{%s}', attribsString, returnTypes.join('|') );
}
f.signature = '<span class="signature">' + (f.signature || '') + '</span>' +
'<span class="type-signature">' + returnTypesString + '</span>';
}
function addSignatureTypes(f) {
var types = f.type ? buildItemTypeStrings(f) : [];
f.signature = (f.signature || '') + '<span class="type-signature">' +
(types.length ? ' :' + types.join('|') : '') + '</span>';
}
function addAttribs(f) {
var attribs = helper.getAttribs(f);
var attribsString = buildAttribsString(attribs);
f.attribs = util.format('<span class="type-signature">%s</span>', attribsString);
}
function shortenPaths(files, commonPrefix) {
Object.keys(files).forEach(function(file) {
files[file].shortened = files[file].resolved.replace(commonPrefix, '')
// always use forward slashes
.replace(/\\/g, '/');
});
return files;
}
function getPathFromDoclet(doclet) {
if (!doclet.meta) {
return null;
}
return doclet.meta.path && doclet.meta.path !== 'null' ?
path.join(doclet.meta.path, doclet.meta.filename) :
doclet.meta.filename;
}
function generate(title, docs, filename, resolveLinks) {
var docData;
var html;
var outpath;
resolveLinks = resolveLinks !== false;
docData = {
env: env,
title: title,
docs: docs
};
outpath = path.join(outdir, filename);
html = view.render('container.tmpl', docData);
if (resolveLinks) {
html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>
}
fs.writeFileSync(outpath, html, 'utf8');
}
function generateSourceFiles(sourceFiles, encoding) {
encoding = encoding || 'utf8';
Object.keys(sourceFiles).forEach(function(file) {
var source;
// links are keyed to the shortened path in each doclet's `meta.shortpath` property
var sourceOutfile = helper.getUniqueFilename(sourceFiles[file].shortened);
helper.registerLink(sourceFiles[file].shortened, sourceOutfile);
try {
source = {
kind: 'source',
code: helper.htmlsafe( fs.readFileSync(sourceFiles[file].resolved, encoding) )
};
}
catch (e) {
logger.error('Error while generating source file %s: %s', file, e.message);
}
generate('Source: ' + sourceFiles[file].shortened, [source], sourceOutfile,
false);
});
}
/**
* Look for classes or functions with the same name as modules (which indicates that the module
* exports only that class or function), then attach the classes or functions to the `module`
* property of the appropriate module doclets. The name of each class or function is also updated
* for display purposes. This function mutates the original arrays.
*
* @private
* @param {Array.<module:jsdoc/doclet.Doclet>} doclets - The array of classes and functions to
* check.
* @param {Array.<module:jsdoc/doclet.Doclet>} modules - The array of module doclets to search.
*/
function attachModuleSymbols(doclets, modules) {
var symbols = {};
// build a lookup table
doclets.forEach(function(symbol) {
symbols[symbol.longname] = symbols[symbol.longname] || [];
symbols[symbol.longname].push(symbol);
});
modules.forEach(function(module) {
if (symbols[module.longname]) {
module.modules = symbols[module.longname]
// Only show symbols that have a description. Make an exception for classes, because
// we want to show the constructor-signature heading no matter what.
.filter(function(symbol) {
return symbol.description || symbol.kind === 'class';
})
.map(function(symbol) {
symbol = doop(symbol);
if (symbol.kind === 'class' || symbol.kind === 'function') {
symbol.name = symbol.name.replace('module:', '(require("') + '"))';
}
return symbol;
});
}
});
}
function buildMemberNav(items, itemHeading, itemsSeen, linktoFn) {
var nav = '';
if (items.length) {
var itemsNav = '';
items.forEach(function(item) {
var displayName;
if ( !hasOwnProp.call(item, 'longname') ) {
itemsNav += '<li>' + linktoFn('', item.name) + '</li>';
}
else if ( !hasOwnProp.call(itemsSeen, item.longname) ) {
if (env.conf.templates.default.useLongnameInNav) {
displayName = item.longname;
} else {
displayName = item.name;
}
itemsNav += '<li>' + linktoFn(item.longname, displayName.replace(/\b(module|event):/g, '')) + '</li>';
itemsSeen[item.longname] = true;
}
});
if (itemsNav !== '') {
nav += '<h3>' + itemHeading + '</h3><ul>' + itemsNav + '</ul>';
}
}
return nav;
}
function linktoTutorial(longName, name) {
return tutoriallink(name);
}
function linktoExternal(longName, name) {
return linkto(longName, name.replace(/(^"|"$)/g, ''));
}
/**
* Create the navigation sidebar.
* @param {object} members The members that will be used to create the sidebar.
* @param {array<object>} members.classes
* @param {array<object>} members.externals
* @param {array<object>} members.globals
* @param {array<object>} members.mixins
* @param {array<object>} members.modules
* @param {array<object>} members.namespaces
* @param {array<object>} members.tutorials
* @param {array<object>} members.events
* @param {array<object>} members.interfaces
* @return {string} The HTML for the navigation sidebar.
*/
function buildNav(members) {
var globalNav;
var nav = '<h2><a href="index.html">Home</a></h2>';
var seen = {};
var seenTutorials = {};
nav += buildMemberNav(members.modules, 'Modules', {}, linkto);
nav += buildMemberNav(members.externals, 'Externals', seen, linktoExternal);
nav += buildMemberNav(members.classes, 'Classes', seen, linkto);
nav += buildMemberNav(members.events, 'Events', seen, linkto);
nav += buildMemberNav(members.namespaces, 'Namespaces', seen, linkto);
nav += buildMemberNav(members.mixins, 'Mixins', seen, linkto);
nav += buildMemberNav(members.tutorials, 'Tutorials', seenTutorials, linktoTutorial);
nav += buildMemberNav(members.interfaces, 'Interfaces', seen, linkto);
if (members.globals.length) {
globalNav = '';
members.globals.forEach(function(g) {
if ( g.kind !== 'typedef' && !hasOwnProp.call(seen, g.longname) ) {
globalNav += '<li>' + linkto(g.longname, g.name) + '</li>';
}
seen[g.longname] = true;
});
if (!globalNav) {
// turn the heading into a link so you can actually get to the global page
nav += '<h3>' + linkto('global', 'Global') + '</h3>';
}
else {
nav += '<h3>Global</h3><ul>' + globalNav + '</ul>';
}
}
return nav;
}
/**
@param {TAFFY} taffyData See <http://taffydb.com/>.
@param {object} opts
@param {Tutorial} tutorials
*/
exports.publish = function(taffyData, opts, tutorials) {
var classes;
var conf;
var externals;
var files;
var fromDir;
var globalUrl;
var indexUrl;
var interfaces;
var members;
var mixins;
var modules;
var namespaces;
var outputSourceFiles;
var packageInfo;
var packages;
var sourceFilePaths = [];
var sourceFiles = {};
var staticFileFilter;
var staticFilePaths;
var staticFiles;
var staticFileScanner;
var templatePath;
data = taffyData;
conf = env.conf.templates || {};
conf.default = conf.default || {};
templatePath = path.normalize(opts.template);
view = new template.Template( path.join(templatePath, 'tmpl') );
// claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness
// doesn't try to hand them out later
indexUrl = helper.getUniqueFilename('index');
// don't call registerLink() on this one! 'index' is also a valid longname
globalUrl = helper.getUniqueFilename('global');
helper.registerLink('global', globalUrl);
// set up templating
view.layout = conf.default.layoutFile ?
path.getResourcePath(path.dirname(conf.default.layoutFile),
path.basename(conf.default.layoutFile) ) :
'layout.tmpl';
// set up tutorials for helper
helper.setTutorials(tutorials);
data = helper.prune(data);
data.sort('longname, version, since');
helper.addEventListeners(data);
data().each(function(doclet) {
var sourcePath;
doclet.attribs = '';
if (doclet.examples) {
doclet.examples = doclet.examples.map(function(example) {
var caption;
var code;
if (example.match(/^\s*<caption>([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) {
caption = RegExp.$1;
code = RegExp.$3;
}
return {
caption: caption || '',
code: code || example
};
});
}
if (doclet.see) {
doclet.see.forEach(function(seeItem, i) {
doclet.see[i] = hashToLink(doclet, seeItem);
});
}
// build a list of source files
if (doclet.meta) {
sourcePath = getPathFromDoclet(doclet);
sourceFiles[sourcePath] = {
resolved: sourcePath,
shortened: null
};
if (sourceFilePaths.indexOf(sourcePath) === -1) {
sourceFilePaths.push(sourcePath);
}
}
});
// update outdir if necessary, then create outdir
packageInfo = ( find({kind: 'package'}) || [] )[0];
if (packageInfo && packageInfo.name) {
outdir = path.join( outdir, packageInfo.name, (packageInfo.version || '') );
}
fs.mkPath(outdir);
// copy the template's static files to outdir
fromDir = path.join(templatePath, 'static');
staticFiles = fs.ls(fromDir, 3);
staticFiles.forEach(function(fileName) {
var toDir = fs.toDir( fileName.replace(fromDir, outdir) );
fs.mkPath(toDir);
fs.copyFileSync(fileName, toDir);
});
// copy user-specified static files to outdir
if (conf.default.staticFiles) {
// The canonical property name is `include`. We accept `paths` for backwards compatibility
// with a bug in JSDoc 3.2.x.
staticFilePaths = conf.default.staticFiles.include ||
conf.default.staticFiles.paths ||
[];
staticFileFilter = new (require('jsdoc/src/filter')).Filter(conf.default.staticFiles);
staticFileScanner = new (require('jsdoc/src/scanner')).Scanner();
staticFilePaths.forEach(function(filePath) {
var extraStaticFiles;
filePath = path.resolve(env.pwd, filePath);
extraStaticFiles = staticFileScanner.scan([filePath], 10, staticFileFilter);
extraStaticFiles.forEach(function(fileName) {
var sourcePath = fs.toDir(filePath);
var toDir = fs.toDir( fileName.replace(sourcePath, outdir) );
fs.mkPath(toDir);
fs.copyFileSync(fileName, toDir);
});
});
}
if (sourceFilePaths.length) {
sourceFiles = shortenPaths( sourceFiles, path.commonPrefix(sourceFilePaths) );
}
data().each(function(doclet) {
var docletPath;
var url = helper.createLink(doclet);
helper.registerLink(doclet.longname, url);
// add a shortened version of the full path
if (doclet.meta) {
docletPath = getPathFromDoclet(doclet);
docletPath = sourceFiles[docletPath].shortened;
if (docletPath) {
doclet.meta.shortpath = docletPath;
}
}
});
data().each(function(doclet) {
var url = helper.longnameToUrl[doclet.longname];
if (url.indexOf('#') > -1) {
doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop();
}
else {
doclet.id = doclet.name;
}
if ( needsSignature(doclet) ) {
addSignatureParams(doclet);
addSignatureReturns(doclet);
addAttribs(doclet);
}
});
// do this after the urls have all been generated
data().each(function(doclet) {
doclet.ancestors = getAncestorLinks(doclet);
if (doclet.kind === 'member') {
addSignatureTypes(doclet);
addAttribs(doclet);
}
if (doclet.kind === 'constant') {
addSignatureTypes(doclet);
addAttribs(doclet);
doclet.kind = 'member';
}
});
members = helper.getMembers(data);
members.tutorials = tutorials.children;
// output pretty-printed source files by default
outputSourceFiles = conf.default && conf.default.outputSourceFiles !== false;
// add template helpers
view.find = find;
view.linkto = linkto;
view.resolveAuthorLinks = resolveAuthorLinks;
view.tutoriallink = tutoriallink;
view.htmlsafe = htmlsafe;
view.outputSourceFiles = outputSourceFiles;
// once for all
view.nav = buildNav(members);
attachModuleSymbols( find({ longname: {left: 'module:'} }), members.modules );
// generate the pretty-printed source files first so other pages can link to them
if (outputSourceFiles) {
generateSourceFiles(sourceFiles, opts.encoding);
}
if (members.globals.length) { generate('Global', [{kind: 'globalobj'}], globalUrl); }
// index page displays information from package.json and lists files
files = find({kind: 'file'});
packages = find({kind: 'package'});
generate('Home',
packages.concat(
[{
kind: 'mainpage',
readme: opts.readme,
longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'
}]
).concat(files), indexUrl);
// set up the lists that we'll use to generate pages
classes = taffy(members.classes);
modules = taffy(members.modules);
namespaces = taffy(members.namespaces);
mixins = taffy(members.mixins);
externals = taffy(members.externals);
interfaces = taffy(members.interfaces);
Object.keys(helper.longnameToUrl).forEach(function(longname) {
var myClasses = helper.find(classes, {longname: longname});
var myExternals = helper.find(externals, {longname: longname});
var myInterfaces = helper.find(interfaces, {longname: longname});
var myMixins = helper.find(mixins, {longname: longname});
var myModules = helper.find(modules, {longname: longname});
var myNamespaces = helper.find(namespaces, {longname: longname});
if (myModules.length) {
generate('Module: ' + myModules[0].name, myModules, helper.longnameToUrl[longname]);
}
if (myClasses.length) {
generate('Class: ' + myClasses[0].name, myClasses, helper.longnameToUrl[longname]);
}
if (myNamespaces.length) {
generate('Namespace: ' + myNamespaces[0].name, myNamespaces, helper.longnameToUrl[longname]);
}
if (myMixins.length) {
generate('Mixin: ' + myMixins[0].name, myMixins, helper.longnameToUrl[longname]);
}
if (myExternals.length) {
generate('External: ' + myExternals[0].name, myExternals, helper.longnameToUrl[longname]);
}
if (myInterfaces.length) {
generate('Interface: ' + myInterfaces[0].name, myInterfaces, helper.longnameToUrl[longname]);
}
});
// TODO: move the tutorial functions to templateHelper.js
function generateTutorial(title, tutorial, filename) {
var tutorialData = {
title: title,
header: tutorial.title,
content: tutorial.parse(),
children: tutorial.children
};
var tutorialPath = path.join(outdir, filename);
var html = view.render('tutorial.tmpl', tutorialData);
// yes, you can use {@link} in tutorials too!
html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>
fs.writeFileSync(tutorialPath, html, 'utf8');
}
// tutorials can have only one parent so there is no risk for loops
function saveChildren(node) {
node.children.forEach(function(child) {
generateTutorial('Tutorial: ' + child.title, child, helper.tutorialToUrl(child.name));
saveChildren(child);
});
}
saveChildren(tutorials);
};

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 116 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 118 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 120 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 114 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 120 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 117 KiB

View File

@ -0,0 +1,25 @@
/*global document */
(function() {
var source = document.getElementsByClassName('prettyprint source linenums');
var i = 0;
var lineNumber = 0;
var lineId;
var lines;
var totalLines;
var anchorHash;
if (source && source[0]) {
anchorHash = document.location.hash.substring(1);
lines = source[0].getElementsByTagName('li');
totalLines = lines.length;
for (; i < totalLines; i++) {
lineNumber++;
lineId = 'line' + lineNumber;
lines[i].id = lineId;
if (lineId === anchorHash) {
lines[i].className += ' selected';
}
}
}
})();

View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,2 @@
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com",
/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]);

View File

@ -0,0 +1,28 @@
var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a=
[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a);for(c=0;c<
f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\\"===j.charAt(0)&&
(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l=!1;break}}for(var r=
{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+=g.length,
t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b===
"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m),
l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/,
q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g,
"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a),
a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e}
for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute("value",
m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}function E(a){var m=
a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.nodeValue=
j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"],
H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+
I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),
["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",
/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),
["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes",
hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g),f,b;if(b=
!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m,
250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",
PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})();

View File

@ -0,0 +1,393 @@
@font-face {
font-family: 'Open Sans';
font-weight: normal;
font-style: normal;
src: url('../fonts/OpenSans-Regular-webfont.eot');
src:
local('Open Sans'),
local('OpenSans'),
url('../fonts/OpenSans-Regular-webfont.eot?#iefix') format('embedded-opentype'),
url('../fonts/OpenSans-Regular-webfont.woff') format('woff'),
url('../fonts/OpenSans-Regular-webfont.svg#open_sansregular') format('svg');
}
@font-face {
font-family: 'Open Sans Light';
font-weight: normal;
font-style: normal;
src: url('../fonts/OpenSans-Light-webfont.eot');
src:
local('Open Sans Light'),
local('OpenSans Light'),
url('../fonts/OpenSans-Light-webfont.eot?#iefix') format('embedded-opentype'),
url('../fonts/OpenSans-Light-webfont.woff') format('woff'),
url('../fonts/OpenSans-Light-webfont.svg#open_sanslight') format('svg');
}
html
{
overflow: auto;
background-color: #fff;
font-size: 14px;
}
body
{
font-family: 'Open Sans', sans-serif;
line-height: 1.5;
color: #4d4e53;
background-color: white;
}
a, a:visited, a:active {
color: #0095dd;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
header
{
display: block;
padding: 0px 4px;
}
tt, code, kbd, samp {
font-family: Consolas, Monaco, 'Andale Mono', monospace;
}
.class-description {
font-size: 130%;
line-height: 140%;
margin-bottom: 1em;
margin-top: 1em;
}
.class-description:empty {
margin: 0;
}
#main {
float: left;
width: 70%;
}
article dl {
margin-bottom: 40px;
}
article img {
max-width: 100%;
}
section
{
display: block;
background-color: #fff;
padding: 12px 24px;
border-bottom: 1px solid #ccc;
margin-right: 30px;
}
.variation {
display: none;
}
.signature-attributes {
font-size: 60%;
color: #aaa;
font-style: italic;
font-weight: lighter;
}
nav
{
display: block;
float: right;
margin-top: 28px;
width: 30%;
box-sizing: border-box;
border-left: 1px solid #ccc;
padding-left: 16px;
/* Start MOOGLE Changes */
position: sticky;
position: -webkit-sticky;
top: 10px;
}
nav ul {
font-family: 'Lucida Grande', 'Lucida Sans Unicode', arial, sans-serif;
font-size: 100%;
line-height: 17px;
padding: 0;
margin: 0;
list-style-type: none;
}
nav ul a, nav ul a:visited, nav ul a:active {
font-family: Consolas, Monaco, 'Andale Mono', monospace;
line-height: 18px;
color: #4D4E53;
}
nav h3 {
margin-top: 12px;
}
nav li {
margin-top: 6px;
}
footer {
display: block;
padding: 6px;
margin-top: 12px;
font-style: italic;
font-size: 90%;
}
h1, h2, h3, h4 {
font-weight: 200;
margin: 0;
}
h1
{
font-family: 'Open Sans Light', sans-serif;
font-size: 48px;
letter-spacing: -2px;
margin: 12px 24px 20px;
}
h2, h3.subsection-title
{
font-size: 30px;
font-weight: 700;
letter-spacing: -1px;
margin-bottom: 12px;
}
h3
{
font-size: 24px;
letter-spacing: -0.5px;
margin-bottom: 12px;
}
h4
{
font-size: 18px;
letter-spacing: -0.33px;
margin-bottom: 12px;
color: #4d4e53;
}
h5, .container-overview .subsection-title
{
font-size: 120%;
font-weight: bold;
letter-spacing: -0.01em;
margin: 8px 0 3px 0;
}
h6
{
font-size: 100%;
letter-spacing: -0.01em;
margin: 6px 0 3px 0;
font-style: italic;
}
table
{
border-spacing: 0;
border: 0;
border-collapse: collapse;
}
td, th
{
border: 1px solid #ddd;
margin: 0px;
text-align: left;
vertical-align: top;
padding: 4px 6px;
display: table-cell;
}
thead tr
{
background-color: #ddd;
font-weight: bold;
}
th { border-right: 1px solid #aaa; }
tr > th:last-child { border-right: 1px solid #ddd; }
.ancestors, .attribs { color: #999; }
.ancestors a, .attribs a
{
color: #999 !important;
text-decoration: none;
}
.clear
{
clear: both;
}
.important
{
font-weight: bold;
color: #950B02;
}
.yes-def {
text-indent: -1000px;
}
.type-signature {
color: #aaa;
}
.name, .signature {
font-family: Consolas, Monaco, 'Andale Mono', monospace;
}
.details { margin-top: 14px; border-left: 2px solid #DDD; }
.details dt { width: 120px; float: left; padding-left: 10px; padding-top: 6px; }
.details dd { margin-left: 70px; }
.details ul { margin: 0; }
.details ul { list-style-type: none; }
.details li { margin-left: 30px; padding-top: 6px; }
.details pre.prettyprint { margin: 0 }
.details .object-value { padding-top: 0; }
.description {
margin-bottom: 1em;
margin-top: 1em;
}
.code-caption
{
font-style: italic;
font-size: 107%;
margin: 0;
}
.prettyprint
{
border: 1px solid #ddd;
width: 80%;
overflow: auto;
}
.prettyprint.source {
width: inherit;
}
.prettyprint code
{
font-size: 100%;
line-height: 18px;
display: block;
padding: 4px 12px;
margin: 0;
background-color: #fff;
color: #4D4E53;
}
.prettyprint code span.line
{
display: inline-block;
}
.prettyprint.linenums
{
padding-left: 70px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.prettyprint.linenums ol
{
padding-left: 0;
}
.prettyprint.linenums li
{
border-left: 3px #ddd solid;
}
.prettyprint.linenums li.selected,
.prettyprint.linenums li.selected *
{
background-color: lightyellow;
}
.prettyprint.linenums li *
{
-webkit-user-select: text;
-moz-user-select: text;
-ms-user-select: text;
user-select: text;
}
.params .name, .props .name, .name code {
color: #4D4E53;
font-family: Consolas, Monaco, 'Andale Mono', monospace;
font-size: 100%;
}
.params td.description > p:first-child,
.props td.description > p:first-child
{
margin-top: 0;
padding-top: 0;
}
.params td.description > p:last-child,
.props td.description > p:last-child
{
margin-bottom: 0;
padding-bottom: 0;
}
.disabled {
color: #454545;
}
/* Start MOOGLE Changes */
.showHover
{
display: none;
}
tr:hover .showHover,
h4:hover .showHover
{
display: inline-block;
}
.params th, .props th, .methods th { border-right: 1px solid #aaa; }
.params thead .last, .props thead .last, .methods thead .last { border-right: 1px solid #ddd; }
.disabled {
color: #454545;
}
table.methods tbody tr {
cursor: pointer;
}
table.methods tbody tr:hover {
background-color: #e2edff;
}
nav {
margin-left: -250px; /* prevent GitHub logo to overlap TOC links */
}
/* End MOOGLE Changes */

View File

@ -0,0 +1,111 @@
/* JSDoc prettify.js theme */
/* plain text */
.pln {
color: #000000;
font-weight: normal;
font-style: normal;
}
/* string content */
.str {
color: #006400;
font-weight: normal;
font-style: normal;
}
/* a keyword */
.kwd {
color: #000000;
font-weight: bold;
font-style: normal;
}
/* a comment */
.com {
font-weight: normal;
font-style: italic;
}
/* a type name */
.typ {
color: #000000;
font-weight: normal;
font-style: normal;
}
/* a literal value */
.lit {
color: #006400;
font-weight: normal;
font-style: normal;
}
/* punctuation */
.pun {
color: #000000;
font-weight: bold;
font-style: normal;
}
/* lisp open bracket */
.opn {
color: #000000;
font-weight: bold;
font-style: normal;
}
/* lisp close bracket */
.clo {
color: #000000;
font-weight: bold;
font-style: normal;
}
/* a markup tag name */
.tag {
color: #006400;
font-weight: normal;
font-style: normal;
}
/* a markup attribute name */
.atn {
color: #006400;
font-weight: normal;
font-style: normal;
}
/* a markup attribute value */
.atv {
color: #006400;
font-weight: normal;
font-style: normal;
}
/* a declaration */
.dec {
color: #000000;
font-weight: bold;
font-style: normal;
}
/* a variable name */
.var {
color: #000000;
font-weight: normal;
font-style: normal;
}
/* a function name */
.fun {
color: #000000;
font-weight: bold;
font-style: normal;
}
/* Specify class=linenums on a pre to get line numbering */
ol.linenums {
margin-top: 0;
margin-bottom: 0;
}

View File

@ -0,0 +1,132 @@
/* Tomorrow Theme */
/* Original theme - https://github.com/chriskempson/tomorrow-theme */
/* Pretty printing styles. Used with prettify.js. */
/* SPAN elements with the classes below are added by prettyprint. */
/* plain text */
.pln {
color: #4d4d4c; }
@media screen {
/* string content */
.str {
color: #718c00; }
/* a keyword */
.kwd {
color: #8959a8; }
/* a comment */
.com {
color: #8e908c; }
/* a type name */
.typ {
color: #4271ae; }
/* a literal value */
.lit {
color: #f5871f; }
/* punctuation */
.pun {
color: #4d4d4c; }
/* lisp open bracket */
.opn {
color: #4d4d4c; }
/* lisp close bracket */
.clo {
color: #4d4d4c; }
/* a markup tag name */
.tag {
color: #c82829; }
/* a markup attribute name */
.atn {
color: #f5871f; }
/* a markup attribute value */
.atv {
color: #3e999f; }
/* a declaration */
.dec {
color: #f5871f; }
/* a variable name */
.var {
color: #c82829; }
/* a function name */
.fun {
color: #4271ae; } }
/* Use higher contrast and text-weight for printable form. */
@media print, projection {
.str {
color: #060; }
.kwd {
color: #006;
font-weight: bold; }
.com {
color: #600;
font-style: italic; }
.typ {
color: #404;
font-weight: bold; }
.lit {
color: #044; }
.pun, .opn, .clo {
color: #440; }
.tag {
color: #006;
font-weight: bold; }
.atn {
color: #404; }
.atv {
color: #060; } }
/* Style */
/*
pre.prettyprint {
background: white;
font-family: Consolas, Monaco, 'Andale Mono', monospace;
font-size: 12px;
line-height: 1.5;
border: 1px solid #ccc;
padding: 10px; }
*/
/* Specify class=linenums on a pre to get line numbering */
ol.linenums {
margin-top: 0;
margin-bottom: 0; }
/* IE indents via margin-left */
li.L0,
li.L1,
li.L2,
li.L3,
li.L4,
li.L5,
li.L6,
li.L7,
li.L8,
li.L9 {
/* */ }
/* Alternate shading for lines */
li.L1,
li.L3,
li.L5,
li.L7,
li.L9 {
/* */ }

View File

@ -0,0 +1,10 @@
<?js
var data = obj;
var self = this;
?>
<?js if (data.augments && data.augments.length) { ?>
<ul><?js data.augments.forEach(function(a) { ?>
<li><?js= self.linkto(a, a) ?></li>
<?js }) ?></ul>
<?js } ?>

View File

@ -0,0 +1,207 @@
<?js
var self = this;
var isGlobalPage;
docs.forEach(function(doc, i) {
?>
<?js
// we only need to check this once
if (typeof isGlobalPage === 'undefined') {
isGlobalPage = (doc.kind === 'globalobj');
}
?>
<?js if (doc.kind === 'mainpage' || (doc.kind === 'package')) { ?>
<?js= self.partial('mainpage.tmpl', doc) ?>
<?js } else if (doc.kind === 'source') { ?>
<?js= self.partial('source.tmpl', doc) ?>
<?js } else { ?>
<section>
<header>
<?js if (!doc.longname || doc.kind !== 'module') { ?>
<h2><?js if (doc.attribs) { ?><span class="attribs"><?js= doc.attribs ?></span><?js }
if (doc.ancestors && doc.ancestors.length) { ?>
<span class="ancestors"><?js= doc.ancestors.join('') ?></span><?js
}
?><?js= doc.name ?><?js
if (doc.variation) { ?>
<sup class="variation"><?js= doc.variation ?></sup><?js }
if (doc.signature && !doc.hideconstructor) { ?><?js= doc.signature ?><?js } ?></h2>
<?js if (doc.classdesc) { ?>
<div class="class-description"><?js= doc.classdesc ?></div>
<?js } ?>
<?js } else if (doc.kind === 'module' && doc.modules) { ?>
<?js doc.modules.forEach(function(module) { ?>
<?js if (module.classdesc) { ?>
<div class="class-description"><?js= module.classdesc ?></div>
<?js } ?>
<?js }) ?>
<?js } ?>
</header>
<article>
<div class="container-overview">
<?js if (doc.kind === 'module' && doc.modules) { ?>
<?js if (doc.description) { ?>
<div class="description"><?js= doc.description ?></div>
<?js } ?>
<?js doc.modules.forEach(function(module) { ?>
<?js= self.partial('method.tmpl', module) ?>
<?js }) ?>
<?js } else if (doc.kind === 'class' || (doc.kind === 'namespace' && doc.signature)) { ?>
<?js= self.partial('method.tmpl', doc) ?>
<?js } else { ?>
<?js if (doc.description) { ?>
<div class="description"><?js= doc.description ?></div>
<?js } ?>
<?js= self.partial('details.tmpl', doc) ?>
<?js if (doc.examples && doc.examples.length) { ?>
<h3>Example<?js= doc.examples.length > 1? 's':'' ?></h3>
<?js= self.partial('examples.tmpl', doc.examples) ?>
<?js } ?>
<?js } ?>
</div>
<?js if (doc.augments && doc.augments.length) { ?>
<h3 class="subsection-title">Extends</h3>
<?js= self.partial('augments.tmpl', doc) ?>
<?js } ?>
<?js if (doc.requires && doc.requires.length) { ?>
<h3 class="subsection-title">Requires</h3>
<ul><?js doc.requires.forEach(function(r) { ?>
<li><?js= self.linkto(r, r) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js
var classes = self.find({kind: 'class', memberof: doc.longname});
if (!isGlobalPage && classes && classes.length) {
?>
<h3 class="subsection-title">Classes</h3>
<dl><?js classes.forEach(function(c) { ?>
<dt><?js= self.linkto(c.longname, c.name) ?></dt>
<dd><?js if (c.summary) { ?><?js= c.summary ?><?js } ?></dd>
<?js }); ?></dl>
<?js } ?>
<?js
var interfaces = self.find({kind: 'interface', memberof: doc.longname});
if (!isGlobalPage && interfaces && interfaces.length) {
?>
<h3 class="subsection-title">Interfaces</h3>
<dl><?js interfaces.forEach(function(i) { ?>
<dt><?js= self.linkto(i.longname, i.name) ?></dt>
<dd><?js if (i.summary) { ?><?js= i.summary ?><?js } ?></dd>
<?js }); ?></dl>
<?js } ?>
<?js
var mixins = self.find({kind: 'mixin', memberof: doc.longname});
if (!isGlobalPage && mixins && mixins.length) {
?>
<h3 class="subsection-title">Mixins</h3>
<dl><?js mixins.forEach(function(m) { ?>
<dt><?js= self.linkto(m.longname, m.name) ?></dt>
<dd><?js if (m.summary) { ?><?js= m.summary ?><?js } ?></dd>
<?js }); ?></dl>
<?js } ?>
<?js
var namespaces = self.find({kind: 'namespace', memberof: doc.longname});
if (!isGlobalPage && namespaces && namespaces.length) {
?>
<h3 class="subsection-title">Namespaces</h3>
<dl><?js namespaces.forEach(function(n) { ?>
<dt><?js= self.linkto(n.longname, n.name) ?></dt>
<dd><?js if (n.summary) { ?><?js= n.summary ?><?js } ?></dd>
<?js }); ?></dl>
<?js } ?>
<?js
var members = self.find({kind: 'member', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
// symbols that are assigned to module.exports are not globals, even though they're not a memberof anything
if (isGlobalPage && members && members.length && members.forEach) {
members = members.filter(function(m) {
return m.longname && m.longname.indexOf('module:') !== 0;
});
}
if (members && members.length && members.forEach) {
?>
<h3 class="subsection-title">Members</h3>
<?js members.forEach(function(p) { ?>
<?js= self.partial('members.tmpl', p) ?>
<?js }); ?>
<?js } ?>
<!-- Start MOOGLE Changes -->
<?js
var methods = self.find({kind: 'function', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
if (methods && methods.length && methods.forEach) {
?>
<h3 class="subsection-title">Method Summary</h3>
<?js= self.partial('methods_overview.tmpl', methods) ?>
<?js } ?>
<!-- End MOOGLE Changes -->
<?js
var methods = self.find({kind: 'function', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
if (methods && methods.length && methods.forEach) {
?>
<h3 class="subsection-title">Method Details</h3>
<?js methods.forEach(function(m) { ?>
<?js= self.partial('method.tmpl', m) ?>
<?js }); ?>
<?js } ?>
<?js
var typedefs = self.find({kind: 'typedef', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
if (typedefs && typedefs.length && typedefs.forEach) {
?>
<h3 class="subsection-title">Type Definitions</h3>
<?js typedefs.forEach(function(e) {
if (e.signature) {
?>
<?js= self.partial('method.tmpl', e) ?>
<?js
}
else {
?>
<?js= self.partial('members.tmpl', e) ?>
<?js
}
}); ?>
<?js } ?>
<?js
var events = self.find({kind: 'event', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
if (events && events.length && events.forEach) {
?>
<h3 class="subsection-title">Events</h3>
<?js events.forEach(function(e) { ?>
<?js= self.partial('method.tmpl', e) ?>
<?js }); ?>
<?js } ?>
</article>
</section>
<?js } ?>
<?js }); ?>

View File

@ -0,0 +1,143 @@
<?js
var data = obj;
var self = this;
var defaultObjectClass = '';
// Check if the default value is an object or array; if so, apply code highlighting
if (data.defaultvalue && (data.defaultvaluetype === 'object' || data.defaultvaluetype === 'array')) {
data.defaultvalue = "<pre class=\"prettyprint\"><code>" + data.defaultvalue + "</code></pre>";
defaultObjectClass = ' class="object-value"';
}
?>
<?js
var properties = data.properties;
if (properties && properties.length && properties.forEach && !data.hideconstructor) {
?>
<h5 class="subsection-title">Properties:</h5>
<?js= this.partial('properties.tmpl', data) ?>
<?js } ?>
<dl class="details">
<?js if (data.version) {?>
<dt class="tag-version">Version:</dt>
<dd class="tag-version"><ul class="dummy"><li><?js= version ?></li></ul></dd>
<?js } ?>
<?js if (data.since) {?>
<dt class="tag-since">Since:</dt>
<dd class="tag-since"><ul class="dummy"><li><?js= since ?></li></ul></dd>
<?js } ?>
<?js if (data.inherited && data.inherits && !data.overrides) { ?>
<dt class="inherited-from">Inherited From:</dt>
<dd class="inherited-from"><ul class="dummy"><li>
<?js= this.linkto(data.inherits, this.htmlsafe(data.inherits)) ?>
</li></ul></dd>
<?js } ?>
<?js if (data.overrides) { ?>
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<?js= this.linkto(data.overrides, this.htmlsafe(data.overrides)) ?>
</li></ul></dd>
<?js } ?>
<?js if (data.implementations && data.implementations.length) { ?>
<dt class="implementations">Implementations:</dt>
<dd class="implementations"><ul>
<?js data.implementations.forEach(function(impl) { ?>
<li><?js= self.linkto(impl, self.htmlsafe(impl)) ?></li>
<?js }); ?>
</ul></dd>
<?js } ?>
<?js if (data.implements && data.implements.length) { ?>
<dt class="implements">Implements:</dt>
<dd class="implements"><ul>
<?js data.implements.forEach(function(impl) { ?>
<li><?js= self.linkto(impl, self.htmlsafe(impl)) ?></li>
<?js }); ?>
</ul></dd>
<?js } ?>
<?js if (data.mixes && data.mixes.length) { ?>
<dt class="mixes">Mixes In:</dt>
<dd class="mixes"><ul>
<?js data.mixes.forEach(function(a) { ?>
<li><?js= self.linkto(a, a) ?></li>
<?js }); ?>
</ul></dd>
<?js } ?>
<?js if (data.deprecated) { ?>
<dt class="important tag-deprecated">Deprecated:</dt><?js
if (data.deprecated === true) { ?><dd class="yes-def tag-deprecated"><ul class="dummy"><li>Yes</li></ul></dd><?js }
else { ?><dd><ul class="dummy"><li><?js= data.deprecated ?></li></ul></dd><?js }
?>
<?js } ?>
<?js if (data.author && author.length) {?>
<dt class="tag-author">Author:</dt>
<dd class="tag-author">
<ul><?js author.forEach(function(a) { ?>
<li><?js= self.resolveAuthorLinks(a) ?></li>
<?js }); ?></ul>
</dd>
<?js } ?>
<?js if (data.copyright) {?>
<dt class="tag-copyright">Copyright:</dt>
<dd class="tag-copyright"><ul class="dummy"><li><?js= copyright ?></li></ul></dd>
<?js } ?>
<?js if (data.license) {?>
<dt class="tag-license">License:</dt>
<dd class="tag-license"><ul class="dummy"><li><?js= license ?></li></ul></dd>
<?js } ?>
<?js if (data.defaultvalue) {?>
<dt class="tag-default">Default Value:</dt>
<dd class="tag-default"><ul class="dummy">
<li<?js= defaultObjectClass ?>><?js= data.defaultvalue ?></li>
</ul></dd>
<?js } ?>
<?js if (data.meta && self.outputSourceFiles) {?>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<?js= self.linkto(meta.shortpath) ?>, <?js= self.linkto(meta.shortpath, 'line ' + meta.lineno, null, 'line' + meta.lineno) ?>
</li></ul></dd>
<?js } ?>
<?js if (data.tutorials && tutorials.length) {?>
<dt class="tag-tutorial">Tutorials:</dt>
<dd class="tag-tutorial">
<ul><?js tutorials.forEach(function(t) { ?>
<li><?js= self.tutoriallink(t) ?></li>
<?js }); ?></ul>
</dd>
<?js } ?>
<?js if (data.see && see.length) {?>
<dt class="tag-see">See:</dt>
<dd class="tag-see">
<ul><?js see.forEach(function(s) { ?>
<li><?js= self.linkto(s) ?></li>
<?js }); ?></ul>
</dd>
<?js } ?>
<?js if (data.todo && todo.length) {?>
<dt class="tag-todo">To Do:</dt>
<dd class="tag-todo">
<ul><?js todo.forEach(function(t) { ?>
<li><?js= t ?></li>
<?js }); ?></ul>
</dd>
<?js } ?>
</dl>

View File

@ -0,0 +1,2 @@
<?js var data = obj; ?>
<pre><code><?js= data ?></code></pre>

View File

@ -0,0 +1,13 @@
<?js
var data = obj;
var self = this;
data.forEach(function(example) {
if (example.caption) {
?>
<p class="code-caption"><?js= example.caption ?></p>
<?js } ?>
<pre class="prettyprint"><code><?js= self.htmlsafe(example.code) ?></code></pre>
<?js
});
?>

View File

@ -0,0 +1,32 @@
<?js
var data = obj;
?>
<?js if (data.description && data.type && data.type.names) { ?>
<dl>
<dt>
<div class="param-desc">
<?js= data.description ?>
</div>
</dt>
<dd></dd>
<dt>
<dl>
<dt>
Type
</dt>
<dd>
<?js= this.partial('type.tmpl', data.type.names) ?>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
<?js } else { ?>
<div class="param-desc">
<?js if (data.description) { ?>
<?js= data.description ?>
<?js } else if (data.type && data.type.names) { ?>
<?js= this.partial('type.tmpl', data.type.names) ?>
<?js } ?>
</div>
<?js } ?>

View File

@ -0,0 +1,85 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: <?js= title ?></title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div id="main">
<h1 class="page-title"><?js= title ?></h1>
<?js= content ?>
</div>
<nav>
<?js= this.nav ?>
</nav>
<br class="clear">
<footer>
<!-- Start MOOGLE Changes -->
<!-- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc <?js= env.version.number ?></a><?js if(env.conf.templates && env.conf.templates.default && env.conf.templates.default.includeDate !== false) { ?> on <?js= (new Date()) ?><?js } ?> -->
<?js if (env.conf.templates.moogle.footer){ ?>
<?js= env.conf.templates.moogle.footer ?>
<?js } ?>
<?js if (env.conf.templates.moogle.copyright){ ?>
<span class="copyright">
<?js= env.conf.templates.moogle.copyright ?>
</span>
<?js } ?>
<span class="jsdoc-message">
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc <?js= env.version.number ?></a>
<?js if (env.conf.templates.default.includeDate) { ?>
on <?js= (new Date()).toDateString() ?>
<?js } ?>
using a <a href="https://github.com/mar10/fancytree/tree/master/bin/jsdoc3-moogle "
target="_blank">fancytree custom template</a>.
</span>
<!-- End MOOGLE Changes -->
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
<!-- Start MOOGLE Changes -->
<!-- See https://codepo8.github.io/css-fork-on-github-ribbon/ -->
<?js if(env.conf.templates.moogle.ghForkMe) { ?>
<style>#forkongithub a{background:#000;color:#fff;text-decoration:none;font-family:arial,sans-serif;text-align:center;font-weight:bold;padding:5px 40px;font-size:1rem;line-height:2rem;position:relative;transition:0.5s;}#forkongithub a:hover{background:#c11;color:#fff;}#forkongithub a::before,#forkongithub a::after{content:"";width:100%;display:block;position:absolute;top:1px;left:0;height:1px;background:#fff;}#forkongithub a::after{bottom:1px;top:auto;}@media screen and (min-width:800px){#forkongithub{position:fixed;display:block;top:0;right:0;width:200px;overflow:hidden;height:200px;z-index:9999;}#forkongithub a{width:200px;position:absolute;top:60px;right:-60px;transform:rotate(45deg);-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);-moz-transform:rotate(45deg);-o-transform:rotate(45deg);box-shadow:4px 4px 10px rgba(0,0,0,0.8);}}
</style>
<span id="forkongithub"><a href="<?js= env.conf.templates.moogle.ghForkMe.url ?>">Fork me on GitHub</a></span>
<?js } ?>
<!-- Google Analytics -->
<?js if (env.conf.templates.moogle.analytics) { ?>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', '<?js= env.conf.templates.moogle.analytics.ua ?>', '<?js= env.conf.templates.moogle.analytics.domain ?>');
ga('send', 'pageview');
</script>
<?js } ?>
<!-- End MOOGLE Changes -->
</body>
</html>

View File

@ -0,0 +1,14 @@
<?js
var data = obj;
var self = this;
?>
<?js if (data.kind === 'package') { ?>
<h3><?js= data.name ?> <?js= data.version ?></h3>
<?js } ?>
<?js if (data.readme) { ?>
<section>
<article><?js= data.readme ?></article>
</section>
<?js } ?>

View File

@ -0,0 +1,38 @@
<?js
var data = obj;
var self = this;
?>
<h4 class="name" id="<?js= id ?>"><?js= data.attribs + name + (data.signature ? data.signature : '') ?></h4>
<?js if (data.summary) { ?>
<p class="summary"><?js= summary ?></p>
<?js } ?>
<?js if (data.description) { ?>
<div class="description">
<?js= data.description ?>
</div>
<?js } ?>
<?js if (data.type && data.type.names) {?>
<h5>Type:</h5>
<ul>
<li>
<?js= self.partial('type.tmpl', data.type.names) ?>
</li>
</ul>
<?js } ?>
<?js= this.partial('details.tmpl', data) ?>
<?js if (data.fires && fires.length) { ?>
<h5>Fires:</h5>
<ul><?js fires.forEach(function(f) { ?>
<li><?js= self.linkto(f) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.examples && examples.length) { ?>
<h5>Example<?js= examples.length > 1? 's':'' ?></h5>
<?js= this.partial('examples.tmpl', examples) ?>
<?js } ?>

View File

@ -0,0 +1,129 @@
<?js
var data = obj;
var self = this;
?>
<?js if (data.kind !== 'module' && !data.hideconstructor) { ?>
<?js if (data.kind === 'class' && data.classdesc) { ?>
<h2>Constructor</h2>
<?js } ?>
<?js if (data.kind !== 'namespace') { ?>
<h4 class="name" id="<?js= id ?>">
<!-- Start MOOGLE Changes -->
<?js= data.attribs + (kind === 'class' ? 'new ' : '') + name + (data.signature || '') ?>
<a class="showHover" href="#<?js= id ?>">
<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
<!-- End MOOGLE Changes -->
</h4>
<?js } ?>
<?js if (data.summary) { ?>
<p class="summary"><?js= summary ?></p>
<?js } ?>
<?js } ?>
<?js if (data.kind !== 'module' && data.description && !data.hideconstructor) { ?>
<div class="description">
<?js= data.description ?>
</div>
<?js } ?>
<?js if (data.augments && data.alias && data.alias.indexOf('module:') === 0) { ?>
<h5>Extends:</h5>
<?js= self.partial('augments.tmpl', data) ?>
<?js } ?>
<?js if (kind === 'event' && data.type && data.type.names) {?>
<h5>Type:</h5>
<ul>
<li>
<?js= self.partial('type.tmpl', data.type.names) ?>
</li>
</ul>
<?js } ?>
<?js if (data['this']) { ?>
<h5>This:</h5>
<ul><li><?js= this.linkto(data['this'], data['this']) ?></li></ul>
<?js } ?>
<?js if (data.params && params.length && !data.hideconstructor) { ?>
<h5>Parameters:</h5>
<?js= this.partial('params.tmpl', params) ?>
<?js } ?>
<?js= this.partial('details.tmpl', data) ?>
<?js if (data.kind !== 'module' && data.requires && data.requires.length) { ?>
<h5>Requires:</h5>
<ul><?js data.requires.forEach(function(r) { ?>
<li><?js= self.linkto(r) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.fires && fires.length) { ?>
<h5>Fires:</h5>
<ul><?js fires.forEach(function(f) { ?>
<li><?js= self.linkto(f) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.listens && listens.length) { ?>
<h5>Listens to Events:</h5>
<ul><?js listens.forEach(function(f) { ?>
<li><?js= self.linkto(f) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.listeners && listeners.length) { ?>
<h5>Listeners of This Event:</h5>
<ul><?js listeners.forEach(function(f) { ?>
<li><?js= self.linkto(f) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.exceptions && exceptions.length) { ?>
<h5>Throws:</h5>
<?js if (exceptions.length > 1) { ?><ul><?js
exceptions.forEach(function(r) { ?>
<li><?js= self.partial('exceptions.tmpl', r) ?></li>
<?js });
?></ul><?js } else {
exceptions.forEach(function(r) { ?>
<?js= self.partial('exceptions.tmpl', r) ?>
<?js });
} } ?>
<?js if (data.returns && returns.length) { ?>
<h5>Returns:</h5>
<?js if (returns.length > 1) { ?><ul><?js
returns.forEach(function(r) { ?>
<li><?js= self.partial('returns.tmpl', r) ?></li>
<?js });
?></ul><?js } else {
returns.forEach(function(r) { ?>
<?js= self.partial('returns.tmpl', r) ?>
<?js });
} } ?>
<?js if (data.yields && yields.length) { ?>
<h5>Yields:</h5>
<?js if (yields.length > 1) { ?><ul><?js
yields.forEach(function(r) { ?>
<li><?js= self.partial('returns.tmpl', r) ?></li>
<?js });
?></ul><?js } else {
yields.forEach(function(r) { ?>
<?js= self.partial('returns.tmpl', r) ?>
<?js });
} } ?>
<?js if (data.examples && examples.length) { ?>
<h5>Example<?js= examples.length > 1? 's':'' ?></h5>
<?js= this.partial('examples.tmpl', examples) ?>
<?js } ?>

View File

@ -0,0 +1,80 @@
<!-- Start MOOGLE Changes -->
<?js
var self = this;
var data = obj;
var methods = data;
?>
<table class="methods">
<thead>
<tr>
<th>Return Type</th>
<th>Name and Arguments</th>
<th class="last">Details</th>
</tr>
</thead>
<tbody>
<?js
var self = this;
methods.forEach(function(m) {
if (!m) { return; }
var params = m.params,
funcname = m.name,
returns = m.returns,
args = "()",
ret = (m.kind === "class" ? "new" : "void");
if(returns){
var returnTypes = [];
returns.forEach(function(r) {
if (r.type && r.type.names) {
if (! returnTypes.length) { returnTypes = r.type.names; }
}
});
ret = (returnTypes.length ? returnTypes.join(' | ') : '');
}
if(params){
args = [];
params.forEach(function(param) {
if (!param) { return; }
var name = param.name;
if (param.optional || param.nullable) {
name = "<span class='optional'>" + name + "</span>";
}
if (typeof param.defaultvalue !== 'undefined') {
name = name + "=<span class='default'>" + param.defaultvalue + "</span>";
}
args.push(name);
});
args = "(" + args.join(", ") + ")";
}
?>
<tr onclick="window.open('#<?js= m.id ?>', '_self')">
<td class="type">
<?js= ret ?>
</td>
<td class="description">
<span class="name"><code><?js= m.name + args ?></code></span>
<?js= (m.description ? ("<div class=''>" + m.description + "</div>") : "") ?>
</td>
<td class="last">
<a class="showHover" href="#<?js= m.id ?>">Details</a>
</td>
<!--
<td class="name">
<code><?js= m.name + args ?></code>
</td>
<td class="description last">
<?js= m.description ?>
</td>
-->
</tr>
<?js }); ?>
</tbody>
</table>
<!-- End MOOGLE Changes -->

View File

@ -0,0 +1,131 @@
<?js
var params = obj;
/* sort subparams under their parent params (like opts.classname) */
var parentParam = null;
params.forEach(function(param, i) {
var paramRegExp;
if (!param) {
return;
}
if (parentParam && parentParam.name && param.name) {
try {
paramRegExp = new RegExp('^(?:' + parentParam.name + '(?:\\[\\])*)\\.(.+)$');
}
catch (e) {
// there's probably a typo in the JSDoc comment that resulted in a weird
// parameter name
return;
}
if ( paramRegExp.test(param.name) ) {
param.name = RegExp.$1;
parentParam.subparams = parentParam.subparams || [];
parentParam.subparams.push(param);
params[i] = null;
}
else {
parentParam = param;
}
}
else {
parentParam = param;
}
});
/* determine if we need extra columns, "attributes" and "default" */
params.hasAttributes = false;
params.hasDefault = false;
params.hasName = false;
params.forEach(function(param) {
if (!param) { return; }
if (param.optional || param.nullable || param.variable) {
params.hasAttributes = true;
}
if (param.name) {
params.hasName = true;
}
if (typeof param.defaultvalue !== 'undefined') {
params.hasDefault = true;
}
});
?>
<table class="params">
<thead>
<tr>
<?js if (params.hasName) {?>
<th>Name</th>
<?js } ?>
<th>Type</th>
<?js if (params.hasAttributes) {?>
<th>Attributes</th>
<?js } ?>
<?js if (params.hasDefault) {?>
<th>Default</th>
<?js } ?>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<?js
var self = this;
params.forEach(function(param) {
if (!param) { return; }
?>
<tr>
<?js if (params.hasName) {?>
<td class="name"><code><?js= param.name ?></code></td>
<?js } ?>
<td class="type">
<?js if (param.type && param.type.names) {?>
<?js= self.partial('type.tmpl', param.type.names) ?>
<?js } ?>
</td>
<?js if (params.hasAttributes) {?>
<td class="attributes">
<?js if (param.optional) { ?>
&lt;optional><br>
<?js } ?>
<?js if (param.nullable) { ?>
&lt;nullable><br>
<?js } ?>
<?js if (param.variable) { ?>
&lt;repeatable><br>
<?js } ?>
</td>
<?js } ?>
<?js if (params.hasDefault) {?>
<td class="default">
<?js if (typeof param.defaultvalue !== 'undefined') { ?>
<?js= self.htmlsafe(param.defaultvalue) ?>
<?js } ?>
</td>
<?js } ?>
<td class="description last"><?js= param.description ?><?js if (param.subparams) { ?>
<h6>Properties</h6>
<?js= self.partial('params.tmpl', param.subparams) ?>
<?js } ?></td>
</tr>
<?js }); ?>
</tbody>
</table>

View File

@ -0,0 +1,108 @@
<?js
var data = obj;
var props = data.subprops || data.properties;
/* sort subprops under their parent props (like opts.classname) */
var parentProp = null;
props.forEach(function(prop, i) {
if (!prop) { return; }
if ( parentProp && prop.name && prop.name.indexOf(parentProp.name + '.') === 0 ) {
prop.name = prop.name.substr(parentProp.name.length+1);
parentProp.subprops = parentProp.subprops || [];
parentProp.subprops.push(prop);
props[i] = null;
}
else {
parentProp = prop;
}
});
/* determine if we need extra columns, "attributes" and "default" */
props.hasAttributes = false;
props.hasDefault = false;
props.hasName = false;
props.forEach(function(prop) {
if (!prop) { return; }
if (prop.optional || prop.nullable) {
props.hasAttributes = true;
}
if (prop.name) {
props.hasName = true;
}
if (typeof prop.defaultvalue !== 'undefined' && !data.isEnum) {
props.hasDefault = true;
}
});
?>
<table class="props">
<thead>
<tr>
<?js if (props.hasName) {?>
<th>Name</th>
<?js } ?>
<th>Type</th>
<?js if (props.hasAttributes) {?>
<th>Attributes</th>
<?js } ?>
<?js if (props.hasDefault) {?>
<th>Default</th>
<?js } ?>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<?js
var self = this;
props.forEach(function(prop) {
if (!prop) { return; }
?>
<tr>
<?js if (props.hasName) {?>
<td class="name"><code><?js= prop.name ?></code></td>
<?js } ?>
<td class="type">
<?js if (prop.type && prop.type.names) {?>
<?js= self.partial('type.tmpl', prop.type.names) ?>
<?js } ?>
</td>
<?js if (props.hasAttributes) {?>
<td class="attributes">
<?js if (prop.optional) { ?>
&lt;optional><br>
<?js } ?>
<?js if (prop.nullable) { ?>
&lt;nullable><br>
<?js } ?>
</td>
<?js } ?>
<?js if (props.hasDefault) {?>
<td class="default">
<?js if (typeof prop.defaultvalue !== 'undefined') { ?>
<?js= self.htmlsafe(prop.defaultvalue) ?>
<?js } ?>
</td>
<?js } ?>
<td class="description last"><?js= prop.description ?><?js if (prop.subprops) { ?>
<h6>Properties</h6><?js= self.partial('properties.tmpl', prop) ?>
<?js } ?></td>
</tr>
<?js }); ?>
</tbody>
</table>

View File

@ -0,0 +1,19 @@
<?js
var data = obj || {};
if (data.description) {
?>
<div class="param-desc">
<?js= description ?>
</div>
<?js } ?>
<?js if (data.type && data.type.names) {?>
<dl>
<dt>
Type
</dt>
<dd>
<?js= this.partial('type.tmpl', data.type.names) ?>
</dd>
</dl>
<?js } ?>

View File

@ -0,0 +1,8 @@
<?js
var data = obj;
?>
<section>
<article>
<pre class="prettyprint source linenums"><code><?js= data.code ?></code></pre>
</article>
</section>

View File

@ -0,0 +1,19 @@
<section>
<header>
<?js if (children.length > 0) { ?>
<ul><?js
var self = this;
children.forEach(function(t) { ?>
<li><?js= self.tutoriallink(t.name) ?></li>
<?js }); ?></ul>
<?js } ?>
<h2><?js= header ?></h2>
</header>
<article>
<?js= content ?>
</article>
</section>

View File

@ -0,0 +1,7 @@
<?js
var data = obj;
var self = this;
data.forEach(function(name, i) { ?>
<span class="param-type"><?js= self.linkto(name, self.htmlsafe(name)) ?></span>
<?js if (i < data.length-1) { ?>|<?js } ?>
<?js }); ?>

View File

@ -0,0 +1,50 @@
{
"name": "jquery.fancytree",
"description": "JavaScript tree view / tree grid plugin with support for keyboard, inline editing, filtering, checkboxes, drag'n'drop, and lazy loading",
"version": "2.36.1-0",
"main": [
"dist/jquery.fancytree-all-deps.min.js"
],
"moduleType": "globals",
"license": "MIT",
"ignore": [
"**/.*",
"/3rd-party",
"/archive",
"/bin",
"/build",
"/demo",
"/doc",
"/lib",
"/src",
"/test",
"CONTRIBUTING.md",
"fancytree.jquery.json",
"Gruntfile.coffee",
"index.html"
],
"keywords": [
"ajax",
"jquery-plugin",
"lazy",
"table",
"tabletree",
"tree",
"treegrid"
],
"authors": [
{
"name": "Martin Wendt",
"homepage": "https://wwWendt.de"
}
],
"repository": {
"type": "git",
"url": "git://github.com/mar10/fancytree.git"
},
"dependencies": {
"jquery": ">=1.7",
"jquery-ui": ">=1.8.6"
},
"devDependencies": {}
}

View File

@ -0,0 +1 @@
[]

View File

@ -0,0 +1,4 @@
[
{'title': "sub 1"},
{"title": "sub 2"}
]

View File

@ -0,0 +1,6 @@
{
"status": "fault",
"faultMsg": "uh-oh",
"faultCode": -1,
"faulDetails": "..."
}

View File

@ -0,0 +1,7 @@
{
"status": "ok",
"result": [
{"title": "sub 1"},
{"title": "sub 2"}
]
}

View File

@ -0,0 +1,8 @@
<children>
<node lazy="true">
<title> SubNode 1 (lazy)</title>
</node>
<node folder="true" lazy="true">
<title> SubNode 1 (lazy)</title>
</node>
</children>

View File

@ -0,0 +1 @@
[ {"title": "Sub item", "lazy": true }, {"title": "Sub folder", "folder": true, "lazy": true } ]

View File

@ -0,0 +1,29 @@
[
{"title": "ATX PC Computer Power Supply Troubleshooting", "expanded": true, "folder": true, "children": [
{"title": "Power comes on", "extraClasses": "yes", "children": [
{"title": "Live screen", "extraClasses": "yes", "children": [
{"title": "New build", "extraClasses": "yes", "children": [
{"title": "Check power requirement vs. rating.", "extraClasses": "answer"}
]},
{"title": "<strong>No</strong> new build", "extraClasses": "no", "children": [
{"title": "Need two tries to boot", "extraClasses": "yes", "children": [
{"title": "Premature power_good signal. Try different power supply.", "extraClasses": "answer"}
]},
{"title": "Does <strong>not</strong> need two tries to boot", "extraClasses": "no", "children": [
]}
]}
]},
{"title": "<strong>No</strong> live screen", "extraClasses": "no", "children": [
{"title": "Proceed to Video Failure Chart", "extraClasses": "link"}
]}
]},
{"title": "Power comes <strong>not</strong> on", "extraClasses": "no", "children": [
{"title": "AC power source tested?", "extraClasses": "yes", "children": [
]},
{"title": "AC poower source <strong>not</strong> tested", "extraClasses": "no", "children": [
{"title": "Connect to known good outlet.", "extraClasses": "answer"}
]}
]}
]}
]

View File

@ -0,0 +1,18 @@
[
{"title": "html", "expanded": true, "folder": true, "children": [
{"title": "head", "folder": true, "children": [
{"title": "meta"},
{"title": "title"}
]},
{"title": "body", "expanded": true, "folder": true, "children": [
{"title": "ul", "expanded": true, "children": [
{"title": "li"},
{"title": "li"}
]},
{"title": "h1"},
{"title": "h2", "expanded": true, "children": [
{"title": "a"}
]}
]}
]}
]

View File

@ -0,0 +1,27 @@
[
{"title": "/", "expanded": true, "folder": true, "children": [
{"title": "dev", "folder": true},
{"title": "etc", "folder": true, "children": [
{"title": "cups"},
{"title": "httpd"},
{"title": "init.d"}
]},
{"title": "sbin", "folder": true},
{"title": "tmp", "folder": true},
{"title": "Users", "expanded": true, "folder": true, "children": [
{"title": "jdoe", "folder": true},
{"title": "jmiller", "folder": true},
{"title": "mysql", "folder": true}
]},
{"title": "usr", "expanded": true, "folder": true, "children": [
{"title": "bin", "folder": true},
{"title": "lib", "folder": true},
{"title": "local", "folder": true}
]},
{"title": "var", "expanded": true, "folder": true, "children": [
{"title": "log", "folder": true},
{"title": "spool", "folder": true},
{"title": "yp", "folder": true}
]}
]}
]

View File

@ -0,0 +1,10 @@
http://jameskennedymonash.files.wordpress.com/2012/05/musical-instruments.jpg
http://yamltojson.com/
"Musical Instruments":
- "Aerophones":
- "Free aerophones":
- "aa"
- "bb"
- "Pipe aerophones"

View File

@ -0,0 +1,28 @@
[
{"title": "simple node (no explicit id, so a default key is generated)" },
{"key": "2", "title": "item1 with key and tooltip", "tooltip": "Look, a tool tip!" },
{"key": "3", "title": "<span>item2 with <b>html</b> inside a span tag</span>" },
{"key": "4", "title": "node 4" },
{"key": "5", "title": "using href", "href": "https://wwWendt.de/" },
{"key": "6", "title": "node with some extra classes (will be added to the generated markup)", "extraClasses": "my-extra-class" },
{"key": "10", "title": "Folder 1", "folder": true, "children": [
{"key": "10_1", "title": "Sub-item 1.1", "children": [
{"key": "10_1_1", "title": "Sub-item 1.1.1"},
{"key": "10_1_2", "title": "Sub-item 1.1.2 r"}
]},
{"key": "10_2", "title": "Sub-item 1.2", "children": [
{"key": "10_2_1", "title": "Sub-item 1.2.1"},
{"key": "10_2_2", "title": "Sub-item 1.2.2"}
]}
]},
{"key": "20", "title": "Simple node with active children (expand)", "expanded": true, "children": [
{"key": "20_1", "title": "Sub-item 2.1", "children": [
{"key": "20_1_1", "title": "Sub-item 2.1.1"},
{"key": "20_1_2", "title": "Sub-item 2.1.2"}
]},
{"key": "20_2", "title": "Sub-item 2.2", "children": [
{"key": "20_2_1", "title": "Sub-item 2.2.1"},
{"key": "20_2_2", "title": "Sub-item 2.2.2"}
]}
]}
]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,33 @@
[
{"title": "simple node (no explicit id, so a default key is generated)" },
{"key": "2", "title": "item1 with key and tooltip", "tooltip": "Look, a tool tip!" },
{"key": "3", "title": "<span>item2 with <b>html</b> inside a span tag</span>" },
{"key": "4", "title": "node 4" },
{"key": "5", "title": "using href", "href": "https://wwWendt.de/" },
{"key": "6", "title": "node with some extra classes (will be added to the generated markup)", "extraClasses": "my-extra-class" },
{"key": "10", "title": "Folder 1", "folder": true, "children": [
{"key": "10_1", "title": "Sub-item 1.1", "children": [
{"key": "10_1_1", "title": "Sub-item 1.1.1"},
{"key": "10_1_2", "title": "Sub-item 1.1.2"}
]},
{"key": "10_2", "title": "Sub-item 1.2", "children": [
{"key": "10_2_1", "title": "Sub-item 1.2.1"},
{"key": "10_2_2", "title": "Sub-item 1.2.2"}
]}
]},
{"key": "20", "title": "Simple node with active children (expand)", "expanded": true, "children": [
{"key": "20_1", "title": "Sub-item 2.1", "children": [
{"key": "20_1_1", "title": "Sub-item 2.1.1", "children": [
{"key": "20_1_1_1", "title": "Sub-item 2.1.1.1"}
]},
{"key": "20_1_2", "title": "Sub-item 2.1.2"}
]},
{"key": "20_2", "title": "Sub-item 2.2", "children": [
{"key": "20_2_1", "title": "Sub-item 2.2.1"},
{"key": "20_2_2", "title": "Sub-item 2.2.2"}
]}
]},
{"key": "30", "title": "Lazy folder", "folder": true, "lazy": true },
{"key": "31", "title": "Lazy folder 2", "folder": true, "lazy": true },
{"key": "32", "title": "Lazy folder 3", "folder": true, "lazy": true }
]

View File

@ -0,0 +1,36 @@
[
{"title": "Books", "expanded": true, "folder": true, "children": [
{"title": "Art of War", "type": "book", "author": "Sun Tzu", "year": -500, "qty": 21, "price": 5.95},
{"title": "The Hobbit", "type": "book", "author": "J.R.R. Tolkien", "year": 1937, "qty": 32, "price": 8.97},
{"title": "The Little Prince", "type": "book", "author": "Antoine de Saint-Exupery", "year": 1943, "qty": 2946, "price": 6.82},
{"title": "Don Quixote", "type": "book", "author": "Miguel de Cervantes", "year": 1615, "qty": 932, "price": 15.99}
]},
{"title": "Music", "folder": true, "children": [
{"title": "Nevermind", "type": "music", "author": "Nirvana", "year": 1991, "qty": 916, "price": 15.95},
{"title": "Autobahn", "type": "music", "author": "Kraftwerk", "year": 1974, "qty": 2261, "price": 23.98},
{"title": "Kind of Blue", "type": "music", "author": "Miles Davis", "year": 1959, "qty": 9735, "price": 21.90},
{"title": "Back in Black", "type": "music", "author": "AC/DC", "year": 1980, "qty": 3895, "price": 17.99},
{"title": "The Dark Side of the Moon", "type": "music", "author": "Pink Floyd", "year": 1973, "qty": 263, "price": 17.99},
{"title": "Sgt. Pepper's Lonely Hearts Club Band", "type": "music", "author": "The Beatles", "year": 1967, "qty": 521, "price": 13.98}
]},
{"title": "Electronics & Computers", "expanded": true, "folder": true, "children": [
{"title": "Cell Phones", "folder": true, "children": [
{"title": "Moto G", "type": "phone", "author": "Motorola", "year": 2014, "qty": 332, "price": 224.99},
{"title": "Galaxy S8", "type": "phone", "author": "Samsung", "year": 2016, "qty": 952, "price": 509.99},
{"title": "iPhone SE", "type": "phone", "author": "Apple", "year": 2016, "qty": 444, "price": 282.75},
{"title": "G6", "type": "phone", "author": "LG", "year": 2017, "qty": 951, "price": 309.99},
{"title": "Lumia", "type": "phone", "author": "Microsoft", "year": 2014, "qty": 32, "price": 205.95},
{"title": "Xperia", "type": "phone", "author": "Sony", "year": 2014, "qty": 77, "price": 195.95},
{"title": "3210", "type": "phone", "author": "Nokia", "year": 1999, "qty": 3, "price": 85.99}
]},
{"title": "Computers", "folder": true, "children": [
{"title": "ThinkPad", "type": "computer", "author": "IBM", "year": 1992, "qty": 16, "price": 749.90},
{"title": "C64", "type": "computer", "author": "Commodore", "year": 1982, "qty": 83, "price": 595.00},
{"title": "MacBook Pro", "type": "computer", "author": "Apple", "year": 2006, "qty": 482, "price": 1949.95},
{"title": "Sinclair ZX Spectrum", "type": "computer", "author": "Sinclair Research", "year": 1982, "qty": 1, "price": 529},
{"title": "Apple II", "type": "computer", "author": "Apple", "year": 1977, "qty": 17, "price": 1298},
{"title": "PC AT", "type": "computer", "author": "IBM", "year": 1984, "qty": 3, "price": 1235.00}
]}
]},
{"title": "More...", "folder": true, "lazy": true}
]

View File

@ -0,0 +1,36 @@
[
{"title": "Books & Audible", "expanded": true, "folder": true, "children": [
{"title": "Books", "expanded": true, "folder": true, "children": [
{"title": "General Books"},
{"title": "Kindle Books"},
{"title": "Books For Study"},
{"title": "Audiobooks"}
]},
{"title": "Movies, TV, Music, Games", "folder": true, "children": [
{"title": "Music"},
{"title": "MP3 Downloads"},
{"title": "Musical Instruments & DJ"},
{"title": "Film & TV"},
{"title": "Blue-ray"},
{"title": "PC & Video Games"}
]},
{"title": "Electronics & Computers", "expanded": true, "folder": true, "children": [
{"title": "Electronics", "folder": true, "children": [
{"title": "Camera & Photo"},
{"title": "TV & Home Cinema"},
{"title": "Audio & HiFi"},
{"title": "Sat Nav & Car Electronics"},
{"title": "Phones"},
{"title": "Electronic Accessories"}
]},
{"title": "Computers", "folder": true, "children": [
{"title": "Laptops"},
{"title": "Tablets"},
{"title": "Computer & Accessories"},
{"title": "Computer Components"},
{"title": "Software"},
{"title": "Printers & Ink"}
]}
]}
]}
]

View File

@ -0,0 +1,22 @@
[
{"title": "Animalia", "expanded": true, "folder": true, "children": [
{"title": "Chordate", "folder": true, "children": [
{"title": "Mammal", "children": [
{"title": "Primate", "children": [
{"title": "Primate", "children": [
]},
{"title": "Carnivora", "children": [
]}
]},
{"title": "Carnivora", "children": [
{"title": "Felidae", "lazy": true}
]}
]}
]},
{"title": "Arthropoda", "expanded": true, "folder": true, "children": [
{"title": "Insect", "children": [
{"title": "Diptera", "lazy": true}
]}
]}
]}
]

View File

@ -0,0 +1,31 @@
[
{"title": "simple node (no explicit id, so a default key is generated)" },
{"key": "2", "title": "item1 with key and tooltip", "tooltip": "Look, a tool tip!" },
{"key": "3", "title": "<span>item2 with <b>html</b> inside a span tag</span>" },
{"key": "4", "title": "this nodes uses 'nolink', so no &lt;a> tag is generated", "nolink": true},
{"key": "5", "title": "using href", "href": "https://wwWendt.de/" },
{"key": "6", "title": "node with some extra classes (will be added to the generated markup)", "extraClasses": "my-extra-class" },
{"key": "10", "title": "Folder 1", "folder": true, "children": [
{"key": "10_1", "title": "Sub-item 1.1", "children": [
{"key": "10_1_1", "title": "Sub-item 1.1.1"},
{"key": "10_1_2", "title": "Sub-item 1.1.2"}
]},
{"key": "10_2", "title": "Sub-item 1.2", "children": [
{"key": "10_2_1", "title": "Sub-item 1.2.1"},
{"key": "10_2_2", "title": "Sub-item 1.2.2"}
]}
]},
{"key": "20", "title": "Simple node with active children (expand)", "expanded": true, "children": [
{"key": "20_1", "title": "Sub-item 2.1", "children": [
{"key": "20_1_1", "title": "Sub-item 2.1.1"},
{"key": "20_1_2", "title": "Sub-item 2.1.2"}
]},
{"key": "20_2", "title": "Sub-item 2.2", "children": [
{"key": "20_2_1", "title": "Sub-item 2.2.1"},
{"key": "20_2_2", "title": "Sub-item 2.2.2"}
]}
]},
{"key": "30", "title": "Lazy folder", "folder": true, "lazy": true },
{"key": "31", "title": "Lazy folder (preload)", "folder": true, "lazy": true, "preload": true },
{"key": "32", "title": "Lazy folder (expand on load)", "folder": true, "lazy": true, "expanded": true }
]

View File

@ -0,0 +1,30 @@
<children>
<node>
<title> Node 1</title>
</node>
<node folder="true" expanded="true" key="42">
<title> Node 2 (expanded folder)</title>
<children>
<node>
<title> Node 2.1</title>
</node>
<node>
<title> Node 2.2</title>
</node>
</children>
</node>
<node folder="true">
<title> Node 3 (collapsed folder)</title>
<children>
<node>
<title> Node 3.1</title>
</node>
<node>
<title> Node 3.2</title>
</node>
</children>
</node>
<node folder="true" lazy="true">
<title> Node 4 (lazy)</title>
</node>
</children>

View File

@ -0,0 +1,113 @@
/*
* TODO: implement a simple nose-based server that
*
* - serves the demo folder, so we don't need to use restricted local file
* file://... access
* - act as an ajax server that send lazy subnodes
* - See https://gist.github.com/701407
*/
/* eslint-env node */
/* eslint-disable one-var, no-console */
// TODO enable strict mode again
//"use strict";
var assert = require("assert"),
http = require("http"),
url = require("url");
/*
* Helpers
*/
var NODE_ATTRS = ["title", "key"];
function copyNode(node, deep) {
var i,
l,
name,
node2 = {};
for (i = 0, l = NODE_ATTRS.length; i < l; i++) {
name = NODE_ATTRS[i];
node2[name] = node[name];
}
return node2;
}
/*
* Class TreeModel
* Simple tree data structure
*/
var TreeModel = function() {
this.children = [];
this.keyMap = {};
};
TreeModel.prototype.find = function(key) {
return this.keyMap[key];
};
TreeModel.prototype.append = function(node, obj) {
// Calling append(obj) -> append(root, obj)
if (obj === undefined) {
obj = node;
node = this;
}
assert.ok(obj.key && this.keyMap[obj.key] === undefined);
if (node.children) {
node.children.push(obj);
} else {
node.children = [obj];
}
this.keyMap[obj.key] = obj;
obj.parent = node;
return obj;
};
TreeModel.prototype.remove = function(key) {
var node = this.keyMap[key],
parent = node.parent,
idx = parent.children.indexOf(node);
parent.children.splice(idx, 1);
delete this.keyMap[key];
};
/*
* Init a new tree with some sample data
*/
var _tree = new TreeModel();
var n = _tree.append({ title: "node 1", key: "1", folder: true });
_tree.append(n, { title: "node 1.1", key: "1.1" });
_tree.append(n, { title: "node 1.2", key: "1.2" });
n = _tree.append({ title: "node 2", key: "2" });
_tree.append(n, { title: "node 2.1", key: "2.1" });
/**
* Ajax server
*/
http.createServer(function(request, response) {
var i,
args = url.parse(request.url, true),
query = args.query,
parts = args.pathname.substring(1).split("/"),
cmd = parts[0],
node = _tree.find(query.key),
res = { error: "invalid command" };
console.log("args", args, parts);
switch (cmd) {
case "get":
res = copyNode(node);
break;
case "children":
res = [];
if (node.children) {
for (i = 0; i < node.children.length; i++) {
res.push(copyNode(node.children[i]));
}
}
break;
}
console.log("children", node.children);
console.log("json", copyNode(node));
response.writeHead(200, { "Content-Type": "application/json" });
response.end(JSON.stringify(res));
}).listen(8124);
console.log("Server running at http://127.0.0.1:8124/");

View File

@ -0,0 +1,25 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<meta name="robots" content="noindex,follow">
<script src="../lib/jquery.js"></script>
<script src="sample.js"></script>
<title>Fancytree - Example Browser</title>
</head>
<frameset rows="50,1*" frameborder="no" framespacing="0">
<frame src="top.html" name="top" scrolling="NO" noresize
marginwidth="0" marginheight="0">
<frameset cols="200,1*" >
<frame src="nav.html" name="nav" scrolling="NO"
marginwidth="0" marginheight="0" style="border-right: 1px solid gray">
<frame src="welcome.html" name="content">
</frameset>
</frameset>
<noframes>
<body>
<p>This page requires frames.</p>
</body>
</noframes>
</html>

View File

@ -0,0 +1,276 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<meta name="robots" content="noindex,follow">
<script src="../lib/jquery.js"></script>
<script src="../src/jquery-ui-dependencies/jquery.fancytree.ui-deps.js"></script>
<link href="../src/skin-win8/ui.fancytree.css" rel="stylesheet">
<script src="../src/jquery.fancytree.js"></script>
<script src="sample.js"></script>
<title>Fancytree - Example Browser Nav</title>
<style type="text/css">
body {
background-color: #f7f7f7;
/* background-color: #39414A;
color: white; */
font-family: Helvetica, Arial, sans-serif;
font-size: smaller;
/* background-image: url("nav_bg.png"); */
/* background-repeat: repeat-x; */
}
div#tree {
position: absolute;
height: 95%;
width: 95%;
padding: 5px;
margin-right: 16px;
}
ul.fancytree-container {
height: 100%;
width: 100%;
overflow: auto;
background-color: transparent;
}
span.fancytree-node span.fancytree-title {
/* color: white; */
text-decoration: none;
}
/* span.fancytree-focused span.fancytree-title {
outline-color: white;
} */
span.fancytree-node:hover span.fancytree-title,
span.fancytree-active span.fancytree-title,
span.fancytree-active.fancytree-focused span.fancytree-title,
.fancytree-treefocus span.fancytree-title:hover,
.fancytree-treefocus span.fancytree-active span.fancytree-title {
color: #39414A;
}
span.external span.fancytree-title:after {
content: "";
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAFVBMVEVmmcwzmcyZzP8AZswAZv////////9E6giVAAAAB3RSTlP///////8AGksDRgAAADhJREFUGFcly0ESAEAEA0Ei6/9P3sEcVB8kmrwFyni0bOeyyDpy9JTLEaOhQq7Ongf5FeMhHS/4AVnsAZubxDVmAAAAAElFTkSuQmCC") 100% 50% no-repeat;
padding-right: 13px;
}
/* Remove system outline for focused container */
.ui-fancytree.fancytree-container:focus {
outline: none;
}
.ui-fancytree.fancytree-container {
border: none;
}
</style>
<script type="text/javascript">
$(function(){
// --- Initialize sample trees
$("#tree").fancytree({
treeId: "nav",
autoActivate: false, // we use scheduleAction()
autoCollapse: true,
// autoFocus: true,
autoScroll: true,
clickFolderMode: 3, // expand with single click
minExpandLevel: 2,
tabindex: "-1", // we don't want the focus frame
// toggleEffect: { effect: "blind", options: {direction: "vertical", scale: "box"}, duration: 2000 },
// scrollParent: null, // use $container
tooltip: function(event, data) {
return data.node.title;
},
focus: function(event, data) {
var node = data.node;
// Auto-activate focused node after 1 second
if(node.data.href){
node.scheduleAction("activate", 1000);
}
},
blur: function(event, data) {
data.node.scheduleAction("cancel");
},
beforeActivate: function(event, data){
var node = data.node;
if( node.data.href && node.data.target === "_blank") {
window.open(node.data.href, "_blank");
return false; // don't activate
}
},
activate: function(event, data){
var node = data.node,
orgEvent = data.originalEvent || {};
// Open href (force new window if Ctrl is pressed)
if(node.data.href){
window.open(node.data.href, (orgEvent.ctrlKey || orgEvent.metaKey) ? "_blank" : node.data.target);
}
// When an external link was clicked, we don't want the node to become
// active. Also the URL fragment should not be changed
if( node.data.target === "_blank") {
return false;
}
// Append #HREF to URL without actually loading content
// (We check for this value on page load re-activate the node.)
if( window.parent && parent.history && parent.history.pushState ) {
parent.history.pushState({title: node.title}, "", "#" + (node.data.href || ""));
}
},
click: function(event, data){
// We implement this in the `click` event, because `activate` is not
// triggered if the node already was active.
// We want to allow re-loads by clicking again.
var node = data.node,
orgEvent = data.originalEvent;
// Open href (force new window if Ctrl is pressed)
if(node.isActive() && node.data.href){
window.open(node.data.href, (orgEvent.ctrlKey || orgEvent.metaKey) ? "_blank" : node.data.target);
}
}
});
// On page load, activate node if node.data.href matches the url#href
var tree = $.ui.fancytree.getTree(),
frameHash = window.parent && window.parent.location.hash;
if( frameHash ) {
frameHash = frameHash.replace("#", "");
tree.visit(function(n) {
if( n.data.href && n.data.href === frameHash ) {
n.setActive();
return false; // done: break traversal
}
});
}
});
</script>
</head>
<body>
<div id="tree">
<ul>
<li class="folder expanded">Documentation
<ul>
<li class="external">
<a target="_blank" href="https://github.com/mar10/fancytree/">Project home</a>
</li>
<li class="external">
<a target="_blank" href="https://github.com/mar10/fancytree/wiki/">Documentation</a>
</li>
<li class="external">
<a target="_blank" href="../doc/jsdoc/">API reference</a>
</li>
</ul>
<li class="folder expanded"> Examples
<ul>
<li><a target="content" href="welcome.html">Welcome</a></li>
<li><a target="content" href="sample-default.html">Default Options</a></li>
<li><a target="content" href="sample-playground.html">Playground</a></li>
<li><a target="content" href="sample-configurator.html">Option Configurator</a></li>
<li><a target="content" href="sample-multi-ext.html">Complex Demo</a></li>
<li><a target="content" href="sample-ext-grid.html">Grid/Viewport</a></li>
<li><a target="content" href="sample-source.html">Initialization</a></li>
<li><a target="content" href="sample-events.html">Event Handling</a></li>
<li><a target="content" href="sample-api.html">Programming API</a></li>
<li><a target="content" href="sample-select.html">Checkbox &amp; Select</a></li>
<li class="external">
<a target="_blank" href="sample-aria.html">WAI-ARIA</a>
</li>
<li class="folder">Glyph Themes
<ul>
<li><a target="content" href="sample-ext-glyph-awesome4.html">Font Awesome 4</a></li>
<li><a target="content" href="sample-ext-glyph-awesome5.html">Font Awesome 5</a></li>
<li><a target="content" href="sample-ext-glyph-bootstrap3.html">Bootstrap</a></li>
<li><a target="content" href="sample-ext-glyph-material.html">Material</a></li>
<li><a target="content" href="sample-ext-glyph-svg.html">SVG</a></li>
</ul>
</li>
<li><a target="content" href="sample-theming.html">Custom Theming</a></li>
<li><a target="content" href="sample-form.html">Embed in Forms</a></li>
<li class="external">
<a target="_blank" href="https://wwWendt.de/tech/fancytree/demo/taxonomy-browser/">
Taxonomy Browser</a>
</li>
<li class="folder">Extensions
<ul>
<li><a target="content" href="sample-ext-childcounter.html">Child Counter</a></li>
<li><a target="content" href="sample-ext-clones.html">Clones</a></li>
<li><a target="content" href="sample-ext-columnview.html">Column View</a></li>
<li><a target="content" href="sample-ext-menu.html">Context Menu</a></li>
<li><a target="content" href="sample-ext-dnd5.html">Drag'n'Drop</a></li>
<li><a target="content" href="sample-ext-dnd.html">Drag'n'Drop (jQuery UI)</a></li>
<li><a target="content" href="sample-ext-edit.html">Edit</a></li>
<li><a target="content" href="sample-ext-filter.html">Filter</a></li>
<li><a target="content" href="sample-ext-fixed.html">Fixed Headers</a></li>
<li><a target="content" href="sample-ext-glyph-bootstrap3.html">Glyph Fonts</a></li>
<li><a target="content" href="sample-ext-grid.html">Grid/Viewport</a></li>
<li><a target="content" href="sample-ext-logger.html">Logger</a></li>
<li><a target="content" href="sample-ext-multi.html">Multi-Select</a></li>
<li class="external"><a target="_blank" href="sample-ext-persist.html">Persist</a></li>
<li><a target="content" href="sample-ext-table.html">Table</a></li>
<li><a target="content" href="sample-ext-themeroller.html">ThemeRoller</a></li>
<li><a target="content" href="sample-ext-wide.html">Wide</a></li>
</ul>
</li>
<li class="folder">Tweaks
<ul>
<li><a target="content" href="sample-iframe.html">URL Navigation and &lt;iframe></a></li>
<li><a target="content" href="sample-accordion.html">Accordion</a></li>
<li><a target="content" href="sample-load-errors.html">Lazy Load Error Handling</a></li>
<li><a target="content" href="sample-rtl.html">RTL</a></li>
<li><a target="content" href="sample-types.html">Node Types</a></li>
<li><a target="content" href="sample-multiline.html">Large nodes</a></li>
<li><a target="content" href="sample-multi-dnd5.html">Multiple D'n'd</a></li>
<!-- <li><a target="content" href="sample-multi-dnd.html">Multiple D'n'd (jQuery UI)</a></li> -->
<li><a target="content" href="sample-scroll.html">Smart Scrolling</a></li>
<li><a target="content" href="sample-webservice.html">Webservice</a></li>
<li><a target="content" href="../test/test-ext-keyboard.html">Keyboard Nav.</a></li>
</ul>
</li>
<li class="folder">Test
<ul>
<li class="external"><a target="_blank" href="../test/unit/test-core.html">Core Unit Tests</a></li>
<li class="external"><a target="_blank" href="../test/unit/test-suite.html">Suite</a></li>
<li><a target="content" href="../test/test-ext-dnd.html">Drag'n'Drop</a></li>
<li class="external"><a target="_blank" href="../test/unit/test-bench.html">Benchmarks</a></li>
<!--
<li><a target="content" href="sample-pyserver.html">Local server</a>
<li class="folder">DTD
<ul>
<li><a target="content" href="../test/doctypes/doctype-none.html">No DTD</a></li>
<li><a target="content" href="../test/doctypes/doctype-html4-loose.html">HTML4 transitional</a></li>
<li><a target="content" href="../test/doctypes/doctype-html4-strict.html">HTML4 strict</a></li>
<li><a target="content" href="../test/doctypes/doctype-html5.html">HTML5</a></li>
<li><a target="content" href="../test/doctypes/doctype-xml-transitional.html">XHTML transitional</a></li>
<li><a target="content" href="../test/doctypes/doctype-xml-strict.html">XHTML strict</a></li>
</ul>
</li>
-->
</ul>
</li>
</ul>
<li class="folder expanded">3rd Party
<ul>
<li class="folder">Extensions
<ul>
<li><a target="content" href="../3rd-party/extensions/contextmenu/contextmenu.html">jQuery contextMenu Extension</a></li>
<li><a target="content" href="../3rd-party/extensions/hotkeys/hotkeys.html">hotkeys</a></li>
</ul>
</li>
<li class="folder">Samples
<ul>
<li><a target="content" href="sample-3rd-confirm.html">jquery-confirm</a></li>
<li><a target="content" href="sample-3rd-jQuery-contextMenu.html">jQuery contextMenu</a></li>
<li><a target="content" href="sample-3rd-ui-contextmenu.html">ui-contextmenu</a></li>
<li><a target="content" href="sample-3rd-contextmenu-abs.html">Context menu (ABS), Copy/paste</a></li>
<li><a target="content" href="sample-3rd-grid-scrollbar.html">Scrollbar for ext-grid</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 B

View File

@ -0,0 +1,97 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>Fancytree - 3rd Party Example: jquery.confirm</title>
<!-- <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" /> -->
<script src="//code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="//code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<link href="../src/skin-win8/ui.fancytree.css" rel="stylesheet">
<script src="../src/jquery.fancytree.js"></script>
<!-- jquery-contextmenu (http://craftpip.github.io/jquery-confirm/) -->
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.3.0/jquery-confirm.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.3.0/jquery-confirm.min.js"></script>
<!-- Start_Exclude: This block is not part of the sample code -->
<link href="../lib/prettify.css" rel="stylesheet">
<script src="../lib/prettify.js"></script>
<link href="sample.css" rel="stylesheet">
<script src="sample.js"></script>
<!-- End_Exclude -->
<style type="text/css">
div#tree {
width: 300px;
height: 200px;
overflow-y: scroll;
}
ul.fancytree-container {
border: 0;
outline: 0;
}
</style>
<!-- Add code to initialize the tree when the document is loaded: -->
<script type="text/javascript">
$(function() {
$("#btnOpenPopup").click(function() {
$.confirm({
// theme: "material",
title: "Select Products",
// title: "Fancytree & jquery-confirm",
content: "<div id='tree'></div>",
escape: true,
useBootstrap: false,
boxWidth: 320,
onContentReady: function(){
$("#tree").fancytree({
checkbox: true,
source: {url: "ajax-tree-products.json"}
});
},
onAction: function(btnName){
var tree = $.ui.fancytree.getTree("#tree"),
selNodes = tree.getSelectedNodes();
if( btnName === "ok" ) {
alert("Selected: " + selNodes.length + " nodes.");
}
}
});
});
});
</script>
</head>
<body class="example">
<h1>Example: use 'jquery.confirm'</h1>
<div class="description">
<p>
This example uses the
<a href="http://craftpip.github.io/jquery-confirm/" target="_blank" class="external">jquery-confirm plugin</a>,
which is maintained independantly from Fancytree.
</p>
</div>
Click here for a demo:
<button id="btnOpenPopup">Select products...</button>
<!-- Start_Exclude: This block is not part of the sample code -->
<hr>
<p class="sample-links no_code">
<a class="hideInsideFS" href="https://github.com/mar10/fancytree">jquery.fancytree.js project home</a>
<a class="hideOutsideFS" href="#">Link to this page</a>
<a class="hideInsideFS" href="index.html">Example Browser</a>
<a href="#" id="codeExample">View source code</a>
</p>
<pre id="sourceCode" class="prettyprint" style="display:none"></pre>
<!-- End_Exclude -->
</body>
</html>

View File

@ -0,0 +1,250 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>Fancytree - Example: Context Menu</title>
<script src="//code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="//code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<link href="../src/skin-win8/ui.fancytree.css" rel="stylesheet">
<script src="../src/jquery.fancytree.js"></script>
<script src="../src/jquery.fancytree.dnd.js"></script>
<!-- jquery.contextmenu, A Beautiful Site (http://abeautifulsite.net/) -->
<script src="../lib/contextmenu-abs/jquery.contextMenu-custom.js"></script>
<link href="../lib/contextmenu-abs/jquery.contextMenu.css" rel="stylesheet" >
<!-- Start_Exclude: This block is not part of the sample code -->
<link href="../lib/prettify.css" rel="stylesheet">
<script src="../lib/prettify.js"></script>
<link href="sample.css" rel="stylesheet">
<script src="sample.js"></script>
<!-- End_Exclude -->
<script type="text/javascript">
// --- Implement Cut/Copy/Paste --------------------------------------------
var clipboardNode = null;
var pasteMode = null;
function copyPaste(action, node) {
switch( action ) {
case "cut":
case "copy":
clipboardNode = node;
pasteMode = action;
break;
case "paste":
if( !clipboardNode ) {
alert("Clipoard is empty.");
break;
}
if( pasteMode == "cut" ) {
// Cut mode: check for recursion and remove source
var cb = clipboardNode.toDict(true);
if( node.isDescendantOf(cb) ) {
alert("Cannot move a node to it's sub node.");
return;
}
node.addChildren(cb);
node.render();
clipboardNode.remove();
} else {
// Copy mode: prevent duplicate keys:
var cb = clipboardNode.toDict(true, function(dict, node){
dict.title = "Copy of " + dict.title;
delete dict.key; // Remove key, so a new one will be created
});
alert("cb = " + JSON.stringify(cb));
// node.addChildren(cb);
// node.render();
node.applyPatch(cb);
}
clipboardNode = pasteMode = null;
break;
default:
alert("Unhandled clipboard action '" + action + "'");
}
};
// --- Contextmenu helper --------------------------------------------------
function bindContextMenu(span) {
// Add context menu to this node:
$(span).contextMenu({menu: "myMenu"}, function(action, el, pos) {
// The event was bound to the <span> tag, but the node object
// is stored in the parent <li> tag
var node = $.ui.fancytree.getNode(el);
switch( action ) {
case "cut":
case "copy":
case "paste":
copyPaste(action, node);
break;
default:
alert("Todo: appply action '" + action + "' to node " + node);
}
});
};
// --- Init fancytree during startup ----------------------------------------
$(function(){
$("#tree").fancytree({
extensions: ["dnd"],
activate: function(event, data) {
var node = data.node;
$("#echoActivated").text(node.title + ", key=" + node.key);
},
click: function(event, data) {
// Close menu on click
if( $(".contextMenu:visible").length > 0 ){
$(".contextMenu").hide();
// return false;
}
},
keydown: function(event, data) {
var node = data.node;
// Eat keyboard events, when a menu is open
if( $(".contextMenu:visible").length > 0 )
return false;
switch( event.which ) {
// Open context menu on [Space] key (simulate right click)
case 32: // [Space]
$(node.span).trigger("mousedown", {
preventDefault: true,
button: 2
})
.trigger("mouseup", {
preventDefault: true,
pageX: node.span.offsetLeft,
pageY: node.span.offsetTop,
button: 2
});
return false;
// Handle Ctrl-C, -X and -V
case 67:
if( event.ctrlKey ) { // Ctrl-C
copyPaste("copy", node);
return false;
}
break;
case 86:
if( event.ctrlKey ) { // Ctrl-V
copyPaste("paste", node);
return false;
}
break;
case 88:
if( event.ctrlKey ) { // Ctrl-X
copyPaste("cut", node);
return false;
}
break;
}
},
/*Bind context menu for every node when its DOM element is created.
We do it here, so we can also bind to lazy nodes, which do not
exist at load-time. (abeautifulsite.net menu control does not
support event delegation)*/
createNode: function(event, data){
bindContextMenu(data.node.span);
},
/*Load lazy content (to show that context menu will work for new items too)*/
lazyLoad: function(event, data){
data.result = {url: "sample-data2.json"};
},
/* D'n'd, just to show it's compatible with a context menu.
See http://code.google.com/p/dynatree/issues/detail?id=174 */
dnd: {
preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
preventRecursiveMoves: true, // Prevent dropping nodes on own descendants
autoExpandMS: 400,
dragStart: function(node, data) {
return true;
},
dragEnter: function(node, data) {
// return true;
if(node.parent !== data.otherNode.parent)
return false;
return ["before", "after"];
},
dragDrop: function(node, data) {
data.otherNode.moveTo(node, data.hitMode);
}
}
});
});
</script>
</head>
<body class="example">
<h1>Example: Context Menu</h1>
<div class="description">
Implementation of a context menu. Right-click a node and see what happens.
<ul>
<li>Also [space] key is supported to open the menu.
<li>This example also demonstrates, how to copy or move branches and how
to implement clipboard functionality.
<li>A keyboard handler implements Cut, Copy, and Paste with <kbd>Ctrl-X</kbd>,
<kbd>Ctrl-C</kbd>, <kbd>Ctrl-V</kbd>.
</ul>
This sample uses the jQuery Context Menu Plugin by Cory S.N. LaViska.
Visit <a href="http://abeautifulsite.net/">A Beautiful Site</a> for usage and more information.
<br>
<b>NOTE:</b></br>
I had to <a href="http://code.google.com/p/dynatree/issues/detail?id=174">patch Cory's code</a> in order to make it work. Please understand, that I am not able to support this plugin. There are many other context menus
out there :-)
</div>
<div>
<label for="skinswitcher">Skin:</label> <select id="skinswitcher"></select>
</div>
<!-- Definition of context menu -->
<ul id="myMenu" class="contextMenu">
<li class="edit"><a href="#edit">Edit</a></li>
<li class="cut separator"><a href="#cut">Cut</a></li>
<li class="copy"><a href="#copy">Copy</a></li>
<li class="paste"><a href="#paste">Paste</a></li>
<li class="delete"><a href="#delete">Delete</a></li>
<li class="quit separator"><a href="#quit">Quit</a></li>
</ul>
<!-- Definition tree structure -->
<div id="tree">
<ul>
<li id="id1" title="Look, a tool tip!">item1 with key and tooltip
<li id="id2" class="activate">item2: activated on init
<li id="id3" class="folder">Folder with some children
<ul>
<li id="id3.1">Sub-item 3.1
<li id="id3.2">Sub-item 3.2
</ul>
<li id="id4" class="expanded">Document with some children (expanded on init)
<ul>
<li id="id4.1">Sub-item 4.1
<li id="id4.2">Sub-item 4.2
</ul>
<li id="id5" class="lazy folder">Lazy folder
</ul>
</div>
<div>Selected node: <span id="echoActivated">-</span></div>
<!-- Start_Exclude: This block is not part of the sample code -->
<hr>
<p class="sample-links no_code">
<a class="hideInsideFS" href="https://github.com/mar10/fancytree">jquery.fancytree.js project home</a>
<a class="hideOutsideFS" href="#">Link to this page</a>
<a class="hideInsideFS" href="index.html">Example Browser</a>
<a href="#" id="codeExample">View source code</a>
</p>
<pre id="sourceCode" class="prettyprint" style="display:none"></pre>
<!-- End_Exclude -->
</body>
</html>

View File

@ -0,0 +1,460 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>Fancytree - Example: Viewport</title>
<script src="../lib/jquery.js"></script>
<!--
<script src="//code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="//code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
-->
<link href="../src/skin-win8/ui.fancytree.css" rel="stylesheet">
<script src="../src/jquery-ui-dependencies/jquery.fancytree.ui-deps.js"></script>
<script src="../src/jquery.fancytree.js"></script>
<script src="../src/jquery.fancytree.ariagrid.js"></script>
<script src="../src/jquery.fancytree.clones.js"></script>
<script src="../src/jquery.fancytree.dnd5.js"></script>
<script src="../src/jquery.fancytree.edit.js"></script>
<script src="../src/jquery.fancytree.filter.js"></script>
<script src="../src/jquery.fancytree.grid.js"></script>
<script src="../src/jquery.fancytree.logger.js"></script>
<!-- Start_Exclude: This block is not part of the sample code -->
<link href="../lib/prettify.css" rel="stylesheet">
<script src="../lib/prettify.js"></script>
<link href="../demo/sample.css" rel="stylesheet">
<script src="../demo/sample.js"></script>
<!-- End_Exclude -->
<link href="//cdn.jsdelivr.net/gh/ewya/PlainScrollbar/plain-scrollbar.css" rel="stylesheet">
<script src="//cdn.jsdelivr.net/gh/ewya/PlainScrollbar/plain-scrollbar.js"></script>
<style type="text/css">
*, *:before, *:after {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
html, body.flexbox-body {
height: 100%;
padding: 0;
margin: 0;
}
.page-container {
/* background: rgba(255, 255, 255, .1); */
padding: 10px;
}
.flexbox-parent {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: flex-start; /* align items in Main Axis */
align-items: stretch; /* align items in Cross Axis */
align-content: stretch; /* Extra space in Cross Axis */
}
.flexbox-item {
padding: 8px;
}
.flexbox-item-grow {
flex: 1; /* same as flex: 1 1 auto; */
}
/* .flexbox-item.header {
background: rgba(255, 0, 0, .1);
}
.flexbox-item.footer {
background: rgba(0, 255, 0, .1);
}
.flexbox-item.content {
background: rgba(0, 0, 255, .1);
} */
.fill-area {
display: flex;
flex-direction: row;
justify-content: flex-start; /* align items in Main Axis */
align-items: stretch; /* align items in Cross Axis */
align-content: stretch; /* Extra space in Cross Axis */
}
.fill-area-content {
background: rgba(0, 0, 0, .3);
border: 1px solid #000000;
/* Needed for when the area gets squished too far and there is content that can't be displayed */
overflow: auto;
}
header, footer {
/* flex: 0 0; */
background-color: #f7f7f7;
/* padding: 1rem; */
}
/* custom alignment (set by 'renderColumns' event) */
table.fancytree-ext-table {
/* flex: 1; */
width: 100%;
border-collapse: collapse;
border: 1px dotted #f4f4f8;
caption-side: bottom;
}
/* Support scrolling */
div.fancytree-grid-container {
/* Use whole parent heigt*/
flex: 1;
/* Stretch embedded table */
display: flex;
flex-direction: column;
min-height: 30px;
/* */
padding: 0;
border: 1px solid gray;
/* The div should not be stretched by the content rows, because we want to
adust the row count from div height instead: */
overflow-y: hidden;
position: relative;
padding-right: 16px;
}
div.fancytree-grid-container > table.fancytree-ext-grid {
flex: 1;
width: 100%;
border: 0;
margin: 1px 0 1px 0; /* 1px above and below. */
}
/* Ext-grid breaks if another extension hides rows. */
table.fancytree-ext-grid tbody tr.fancytree-hide {
display: table-row;
}
/* Set alternating row colors (define BEFORE standard css). */
table.fancytree-ext-table tbody tr:nth-child(even){
background-color: #fafafa;
}
table.fancytree-ext-table thead th.parent-path {
text-align: left;
}
table.fancytree-ext-table td:nth-child(2) {
width: 50px;
}
table.fancytree-ext-table td:nth-child(4) {
text-align: right;
}
table.fancytree-ext-table td:nth-child(5) {
text-align: center;
}
/* PlainScrollbar-specific Styles */
.plain-scrollbar[data-scrollable="false"] {
visibility: hidden;
}
/* End of PlainScrollbar-specific Styles */
</style>
<script type="text/javascript">
$(function(){
// --- Demo GUI: ---------------------------------------------------
$( "#optionsForm [name=cellFocus]" ).change( function( e ) {
var value = $( this ).find( ":selected" ).val();
window.sessionStorage.setItem( "cellFocus", value );
$.ui.fancytree.getTree( "#treegrid" ).setOption("ariagrid.cellFocus", value);
}).val( window.sessionStorage.getItem( "cellFocus" ) || "allow" );
var modelCount = 0;
// --- Fancytree widget --------------------------------------------
// var sourceUrl = getUrlParam("source");
// if( sourceUrl ){
// sourceUrl = "https://cdn.jsdelivr.net/gh/mar10/assets@master/fancytree/" + sourceUrl;
// } else {
// sourceUrl = "ajax-tree-products.json";
// }
// var sourceUrl = getUrlParam("source");
// var sourceUrl = "../test/ajax10k_nodes.json";
// var sourceUrl = "ajax10k_nodes.json";
var sourceUrl = "https://cdn.jsdelivr.net/gh/mar10/assets@master/fancytree/ajax_101k.json";
$("#treetable").fancytree({
extensions: ["clones", "dnd5", "edit", "filter", "grid", "ariagrid", "logger"],
checkbox: true,
quicksearch: true,
autoScroll: true,
debugLevel: 5,
ariagrid: {
// Internal behavior flags
activateCellOnDoubelclick: true,
cellFocus: $( "#optionsForm [name=cellFocus]" ).find( ":selected" ).val(),
// TODO: use a global tree option `name` or `title` instead?:
label: "Tree Grid", // Added as `aria-label` attribute
},
dnd5: {
autoExpandMS: 1500,
dragStart: function(node, data) {
return true;
},
dragEnter: function(node, data) {
return true;
},
dragDrop: function(node, data) {
var transfer = data.dataTransfer;
if( data.otherNode ) {
data.otherNode.moveTo(node, data.hitMode);
} else {
node.addNode({
title: transfer.getData("text")
}, data.hitMode);
}
// Expand target node when a child was created:
if (data.hitMode === "over") {
node.setExpanded();
}
},
},
edit: {
// triggerStart: ["f2", "mac+enter", "shift+click"],
},
filter: {
autoExpand: true,
},
table: {
indentation: 20, // indent 20px per node level
nodeColumnIdx: 2, // render the node title into the 2nd column
checkboxColumnIdx: 0, // render the checkboxes into the 1st column
},
viewport: {
enabled: true,
count: 15,
},
source: {
url: sourceUrl,
cache: true,
},
preInit: function(event, data) {
var tree = data.tree;
tree.verticalScrollbar = new PlainScrollbar({
alwaysVisible: true,
arrows: true,
orientation: "vertical",
onSet: function(numberOfItems) {
tree.debug("verticalScrollbar:onSet", numberOfItems);
tree.setViewport({
start: Math.round(numberOfItems.start),
// count: tree.viewport.count,
});
},
scrollbarElement: document.getElementById("verticalScrollbar"),
});
},
init: function(event, data) {
var tree = data.tree;
tree.debug(event.type, data);
modelCount = tree.count();
$("#treetable caption").text("Loaded " + modelCount + " nodes.");
tree.getNodeByKey("1.1.88").setActive();
// data.tree.getNodeByKey("10_2_1").setActive();
// Recalc the viewport's row count from the flexed size of the container:
tree.adjustViewportSize();
},
lazyLoad: function(event, data) {
data.result = {url: "ajax-sub2.json"}
},
activateCell: function(event, data) {
data.node.debug(event.type, data);
},
defaultGridAction: function( event, data ) {
// Called when ENTER is pressed in cell-mode.
data.node.debug(event.type, data);
},
renderColumns: function(event, data) {
var node = data.node,
$tdList = $(node.tr).find(">td");
// (index #0 is rendered by fancytree by adding the checkbox)
$tdList.eq(1).text(node.getIndexHier()); //.addClass("alignRight");
// (index #2 is rendered by fancytree)
$tdList.eq(3).text(node._rowIdx);
// $tdList.eq(3).text(node.data.qty);
$tdList.eq(4).html("<input type='checkbox' name='like' value='" + node.key + "'>");
},
updateViewport: function(event, data) {
var tree = data.tree,
topNode = tree.visibleNodeList[tree.viewport.start],
path = (topNode && !topNode.isTopLevel()) ? topNode.getPath(false) + "/..." : "";
tree.debug(event.type, data, tree.isVpUpdating);
// Display breadcrumb/parent-path in header
tree.$container.find("thead th.parent-path").text(path);
// Update edit controls
if (!tree.isVpUpdating ) {
$("input#vpStart").val(tree.viewport.start);
$("input#vpCount").val(tree.viewport.count);
$("span.statistics").text(
", rows: " +
(tree.visibleNodeList ? tree.visibleNodeList.length : "-") +
"/" +
modelCount
);
}
// Handle PlainScrollbar events
tree.verticalScrollbar.set({
start: tree.viewport.start,
total: tree.visibleNodeList.length,
visible: tree.viewport.count,
}, true); // do not trigger `onSet`
},
});
$(window).on("resize", function(e){
// console.log(e.type, e);
var tree = $.ui.fancytree.getTree();
// Resize scroll wrapper to window height:
// $wrapper.height(window.innerHeight - $wrapper[0].offsetTop - BOTTOM_OFS);
// Re-calculate viewport.count from current wrapper height:
tree.adjustViewportSize();
}).resize();
/* Handle inputs */
$(document).on("change", "#vpStart,#vpCount", function(e){
var tree = $.ui.fancytree.getTree(),
opts = {
start: $("#vpStart").val(),
count: $("#vpCount").val(),
};
tree.setViewport(opts);
});
$("input[name=search]").on("change search", function(e){
if (e.type === "change" && e.target.onsearch !== undefined ) {
// We fall back to handling the change event only if the search event is not supported.
return;
}
var n,
tree = $.ui.fancytree.getTree(),
match = $.trim($(this).val());
// Pass a string to perform case insensitive matching
n = tree.filterNodes(match, { mode: "hide" });
// This will adjust the start value in case the filtered row set
// is not inside the current viewport
// tree.setViewport();
$("span.matches").text(n ? "(" + n + " matches)" : "");
});
$("#expandAll").on("click", function(e){
$.ui.fancytree.getTree().expandAll();
});
$("#collapseAll").on("click", function(e){
$.ui.fancytree.getTree().expandAll(false);
});
$("#redraw").on("click", function(e){
$.ui.fancytree.getTree().redrawViewport(true);
});
$("#cbRbAlwaysVisible ").on("change", function(e){
$.ui.fancytree.getTree().verticalScrollbar.alwaysVisible($(this).is(":checked"));
});
});
</script>
</head>
<body class="example flexbox-body">
<div class="page-container flexbox-parent">
<header class="description flexbox-item">
<h1>Example: Viewport Feature with Scrollbar</h1>
<p>
This example uses the 3rd-party plugin
<a target="_blank" href="https://github.com/ewya/PlainScrollbar">PlainScrollbar</a>
to add scrollbar functionality to the
<a target="_top" href="index.html#sample-ext-grid.html">ext-grid viewport feature</a>.
</p>
<p>
<b>Status:</b> 3rd-party example.
<b>Details:</b> <a target="_top" href="index.html#sample-ext-grid.html">ext-grid</a>.
</p>
</header>
<!-- Add a <table> element where the tree should appear: -->
<div class="flexbox-item">
<label for="vpStart">Viewport start:</label>
<input id="vpStart" type="number" value="0" min="0" style="width: 6em;" >
<label for="vpCount">, count:</label>
<input id="vpCount" type="number" value="15" min="1" style="width: 3em;" readonly >
<span class="statistics"></span>
<br>
<label for="filter">Filter:</label>
<input type="search" name="search" incremental placeholder="Search text" autocomplete="off">
<span class="matches"></span>
<form id="optionsForm">
<label>Cell Navigation:
<select name="cellFocus">
<option value="start">start</option>
<option value="allow" selected="selected">allow</option>
<option value="force">force</option>
<option value="off">off</option>
</select>
</label>
(Please reload page for changes to take effect.)
</form>
<div>
<button type="button" id="expandAll">Expand all</button>
<button type="button" id="collapseAll">Collapse all</button>
<button type="button" id="redraw">Redraw viewport</button>
<input id="cbRbAlwaysVisible" type="checkbox" checked="checked">
<label for="cbRbAlwaysVisible">Always show scrollbar</label>
</div>
</div>
<div class="fancytree-grid-container flexbox-item-grow">
<table id="treetable">
<!-- <caption>Loading&hellip;</caption> -->
<colgroup>
<col width="30px"></col>
<col width="30px"></col>
<col width="*"></col>
<col width="50px"></col>
<col width="30px"></col>
</colgroup>
<thead>
<tr> <th></th> <th>#</th> <th class="parent-path"></th> <th>RowIdx</th> <th>Order</th> </tr>
</thead>
</table>
<div id="verticalScrollbar" style="top:19px; height:calc(100% - 18px);"></div>
</div>
<!-- Start_Exclude: This block is not part of the sample code -->
<footer class="flexbox-item">
<p class="sample-links no_code">
<a class="hideInsideFS" href="https://github.com/mar10/fancytree">jquery.fancytree.js project home</a>
<a class="hideOutsideFS" href="#">Link to this page</a>
<a class="hideInsideFS" href="index.html">Example Browser</a>
<a href="#" id="codeExample">View source code</a>
</p>
<pre id="sourceCode" class="prettyprint" style="display:none"></pre>
</footer>
<!-- End_Exclude -->
</div>
</body>
</html>

View File

@ -0,0 +1,114 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>Fancytree - 3rd Party Example: jQuery contextMenu</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" />
<script src="//code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="//code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<link href="../src/skin-win8/ui.fancytree.css" rel="stylesheet">
<script src="../src/jquery.fancytree.js"></script>
<!-- jquery-contextmenu (https://github.com/swisnl/jQuery-contextMenu) -->
<link rel="stylesheet"
href="//cdn.jsdelivr.net/npm/jquery-contextmenu@2.9.0/dist/jquery.contextMenu.min.css" />
<script src="//cdn.jsdelivr.net/npm/jquery-contextmenu@2.9.0/dist/jquery.contextMenu.min.js">
</script>
<!-- Start_Exclude: This block is not part of the sample code -->
<link href="../lib/prettify.css" rel="stylesheet">
<script src="../lib/prettify.js"></script>
<link href="sample.css" rel="stylesheet">
<script src="sample.js"></script>
<!-- End_Exclude -->
<style type="text/css">
</style>
<script type="text/javascript">
$(function() {
$("#tree").fancytree({
extensions: [],
// checkbox: true,
// selectMode: 2,
source: {
url: "ajax-tree-plain.json"
},
lazyLoad: function(event, data) {
data.result = { url: "ajax-sub2.json" }
}
});
$.contextMenu({
selector: "#tree span.fancytree-title",
items: {
"cut": {name: "Cut", icon: "cut",
callback: function(key, opt){
var node = $.ui.fancytree.getNode(opt.$trigger);
alert("Clicked on " + key + " on " + node);
}
},
"copy": {name: "Copy", icon: "copy"},
"paste": {name: "Paste", icon: "paste", disabled: false },
"sep1": "----",
"edit": {name: "Edit", icon: "edit", disabled: true },
"delete": {name: "Delete", icon: "delete", disabled: true },
"more": {name: "More", items: {
"sub1": {name: "Sub 1"},
"sub1": {name: "Sub 2"}
}}
},
callback: function(itemKey, opt) {
var node = $.ui.fancytree.getNode(opt.$trigger);
alert("select " + itemKey + " on " + node);
}
});
});
</script>
</head>
<body class="example">
<h1>Example: use 'jQuery contextMenu'</h1>
<div class="description">
<p>
This example integrates the
<a href="https://github.com/mar10/jquery-ui-contextmenu" target="_blank" class="external">jQuery contextMenu plugin</a>,
which is maintained independantly from Fancytree and is based on
<a href="http://api.jqueryui.com/menu/">jQuery UI Menu</a>
(part of jQuery UI 1.9+).
</p>
<p>
This is only one of more options. See the
<a href="index.html#sample-ext-menu.html">menu overview</a> for details.
</p>
</div>
<div>
<label for="skinswitcher">Skin:</label> <select id="skinswitcher"></select>
</div>
<!-- Tree wrapper -->
<div id="tree"></div>
<hr />
<div id="selected-action">Click right mouse button on node</div>
<!-- Start_Exclude: This block is not part of the sample code -->
<hr>
<p class="sample-links no_code">
<a class="hideInsideFS" href="https://github.com/mar10/fancytree">jquery.fancytree.js project home</a>
<a class="hideOutsideFS" href="#">Link to this page</a>
<a class="hideInsideFS" href="index.html">Example Browser</a>
<a href="#" id="codeExample">View source code</a>
</p>
<pre id="sourceCode" class="prettyprint" style="display:none"></pre>
<!-- End_Exclude -->
</body>
</html>

View File

@ -0,0 +1,134 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>Fancytree - 3rd Party Example: jquery.ui-contextmenu</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" />
<script src="//code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="//code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<link href="../src/skin-win8/ui.fancytree.css" rel="stylesheet">
<script src="../src/jquery.fancytree.js"></script>
<!-- jquery-contextmenu (https://github.com/mar10/jquery-ui-contextmenu/) -->
<script src="//cdn.jsdelivr.net/npm/ui-contextmenu/jquery.ui-contextmenu.min.js"></script>
<!-- Start_Exclude: This block is not part of the sample code -->
<link href="../lib/prettify.css" rel="stylesheet">
<script src="../lib/prettify.js"></script>
<link href="sample.css" rel="stylesheet">
<script src="sample.js"></script>
<!-- End_Exclude -->
<style type="text/css">
.ui-menu {
width: 100px;
font-size: 63%;
z-index: 3; /* over ext-wide titles */
}
</style>
<!-- Add code to initialize the tree when the document is loaded: -->
<script type="text/javascript">
$(function() {
$("#tree").fancytree({
extensions: [],
source: {
url: "ajax-tree-plain.json"
},
lazyLoad: function(event, data) {
data.result = { url: "ajax-sub2.json" }
}
});
$("#tree").contextmenu({
delegate: "span.fancytree-title",
autoFocus: true,
// menu: "#options",
menu: [
{title: "Cut", cmd: "cut", uiIcon: "ui-icon-scissors"},
{title: "Copy", cmd: "copy", uiIcon: "ui-icon-copy"},
{title: "Paste", cmd: "paste", uiIcon: "ui-icon-clipboard", disabled: false },
{title: "----"},
{title: "Edit", cmd: "edit", uiIcon: "ui-icon-pencil", disabled: true },
{title: "Delete", cmd: "delete", uiIcon: "ui-icon-trash", disabled: true },
{title: "More", children: [
{title: "Sub 1", cmd: "sub1"},
{title: "Sub 2", cmd: "sub1"}
]}
],
beforeOpen: function(event, ui) {
var node = $.ui.fancytree.getNode(ui.target);
// Modify menu entries depending on node status
$("#tree").contextmenu("enableEntry", "paste", node.isFolder());
// Show/hide single entries
// $("#tree").contextmenu("showEntry", "cut", false);
// Activate node on right-click
node.setActive();
// Disable tree keyboard handling
ui.menu.prevKeyboard = node.tree.options.keyboard;
node.tree.options.keyboard = false;
},
close: function(event, ui) {
// Restore tree keyboard handling
// console.log("close", event, ui, this)
// Note: ui is passed since v1.15.0
var node = $.ui.fancytree.getNode(ui.target);
node.tree.options.keyboard = ui.menu.prevKeyboard;
node.setFocus();
},
select: function(event, ui) {
var node = $.ui.fancytree.getNode(ui.target);
alert("select " + ui.cmd + " on " + node);
}
});
});
</script>
</head>
<body class="example">
<h1>Example: use 'jquery.ui-contextmenu'</h1>
<div class="description">
<p>
This example integrates the
<a href="https://github.com/mar10/jquery-ui-contextmenu" target="_blank" class="external">jquery-ui-contextmenu plugin</a>,
which is maintained independantly from Fancytree and is based on
<a href="http://api.jqueryui.com/menu/">jQuery UI Menu</a>
(part of jQuery UI 1.9+).
</p>
<p>
This is only one of more options. See the
<a href="index.html#sample-ext-menu.html">menu overview</a> for details.
</p>
</div>
<div>
<label for="skinswitcher">Skin:</label> <select id="skinswitcher"></select>
</div>
<!-- Tree wrapper -->
<div id="tree"></div>
<hr />
<div id="selected-action">Click right mouse button on node</div>
<!-- Start_Exclude: This block is not part of the sample code -->
<hr>
<p class="sample-links no_code">
<a class="hideInsideFS" href="https://github.com/mar10/fancytree">jquery.fancytree.js project home</a>
<a class="hideOutsideFS" href="#">Link to this page</a>
<a class="hideInsideFS" href="index.html">Example Browser</a>
<a href="#" id="codeExample">View source code</a>
</p>
<pre id="sourceCode" class="prettyprint" style="display:none"></pre>
<!-- End_Exclude -->
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More