Webpack all the things! Fixes #2135

This significantly speeds up loading of the application; in an average of 3 tests, v1.6
loaded in 11.5s in the runtime on a Mac, whilst the webpacked version of the code
loaded in 5.53s.
REL-1_X
Surinder Kumar 2017-07-18 15:13:16 +01:00 committed by Dave Page
parent d04ac7656a
commit 4a91bcde30
406 changed files with 3556 additions and 164707 deletions

View File

@ -4,12 +4,14 @@
"babel-loader": "~6.4.1",
"babel-preset-es2015": "~6.24.0",
"babel-preset-react": "~6.23.0",
"css-loader": "^0.28.4",
"cross-env": "^5.0.1",
"enzyme": "~2.8.2",
"enzyme-matchers": "^3.1.0",
"eslint": "^3.19.0",
"eslint": "3.19.0",
"eslint-plugin-react": "^6.10.3",
"extract-text-webpack-plugin": "^2.1.2",
"file-loader": "^0.11.2",
"image-webpack-loader": "^3.3.1",
"jasmine-core": "~2.5.2",
"jasmine-enzyme": "^3.1.0",
"karma": "~1.5.0",
@ -22,38 +24,72 @@
"karma-sourcemap-loader": "~0.3.7",
"karma-webpack": "~2.0.3",
"node-sass": "^4.5.3",
"optimize-css-assets-webpack-plugin": "^2.0.0",
"raw-loader": "^0.5.1",
"react-addons-test-utils": "~15.4.2",
"sass-loader": "^6.0.6",
"style-loader": "^0.18.2",
"webpack": "~2.3.1"
"uglifyjs-webpack-plugin": "^0.4.6",
"url-loader": "^0.5.9",
"webpack": "^3.0.0"
},
"dependencies": {
"acitree": "git+https://github.com/imsurinder90/jquery-aciTree.git#rc.7",
"alertifyjs": "^1.10.0",
"axios": "^0.16.1",
"babel-plugin-transform-es2015-modules-amd": "^6.24.1",
"babel-polyfill": "^6.23.0",
"babel-preset-es2015-without-strict": "~0.0.4",
"babelify": "~7.3.0",
"backbone": "1.1.2",
"backform": "^0.2.0",
"backgrid": "^0.3.8",
"backgrid-filter": "^0.3.7",
"backgrid-select-all": "^0.3.5",
"backgrid-sizeable-columns": "^0.1.1",
"bignumber.js": "^4.0.2",
"bootstrap": "^3.3.7",
"bootstrap-datepicker": "^1.7.0",
"bootstrap-datetime-picker": "^2.4.4",
"bootstrap-switch": "3.3.2",
"bowser": "1.6.1",
"browserify": "~14.1.0",
"codemirror": "^5.27.2",
"css-loader": "0.14.0",
"cssnano": "^3.10.0",
"dropzone": "^5.1.1",
"exports-loader": "~0.6.4",
"flotr2": "^0.1.0",
"font-awesome": "^4.7.0",
"font-mfizz": "^1.2.2",
"hard-source-webpack-plugin": "^0.4.9",
"immutability-helper": "^2.2.0",
"imports-loader": "git+https://github.com/webpack-contrib/imports-loader.git#44d6f48463b256a17c1ba6fd9b5cc1449b4e379d",
"imports-loader": "^0.7.1",
"jquery": "1.11.2",
"jquery-contextmenu": "^2.5.0",
"jquery-ui": "^1.12.1",
"moment": "^2.18.1",
"react": "file:../web/pgadmin/static/vendor/react",
"react-dom": "file:../web/pgadmin/static/vendor/react-dom",
"react-split-pane": "^0.1.63",
"requirejs": "~2.3.3",
"select2": "^4.0.3",
"shim-loader": "^1.0.1",
"slickgrid": "git+https://github.com/6pac/SlickGrid.git#2.3.7",
"underscore": "~1.8.3",
"watchify": "~3.9.0"
"snapsvg": "^0.5.1",
"underscore": "^1.8.3",
"underscore.string": "^3.3.4",
"watchify": "~3.9.0",
"webcabin-docker": "^2.2.2"
},
"scripts": {
"linter": "yarn run eslint pgadmin/static/jsx/**/*.jsx pgadmin/static/js/selection/*.js regression/javascript/**/*.jsx regression/javascript/**/*.js *.js",
"webpacker": "yarn run webpack -- --config webpack.config.js",
"webpacker:dev": "yarn run webpack -- --config webpack.config.js",
"webpacker:prod": "yarn run linter && yarn run webpack -- --config webpack.config.js",
"bundle": "yarn run linter && yarn run webpacker",
"bundle:dev": "yarn run linter && yarn run webpacker:dev",
"bundle:prod": "cross-env NODE_ENV=production yarn run webpacker:prod",
"test:karma-once": "yarn run linter && yarn run karma start -- --single-run",
"test:karma": "yarn run linter && yarn run karma start",
"test:feature": "yarn run bundle && python regression/runtests.py --pkg feature_tests",

View File

@ -47,6 +47,8 @@ class AboutModule(PgAdminModule):
'when': None
}]
def get_exposed_url_endpoints(self):
return ['about.index']
blueprint = AboutModule(MODULE_NAME, __name__,
static_url_path='')
@ -55,7 +57,7 @@ blueprint = AboutModule(MODULE_NAME, __name__,
##########################################################################
# A test page
##########################################################################
@blueprint.route("/")
@blueprint.route("/", endpoint='index')
@login_required
def index():
"""Render the about box."""

View File

@ -1,6 +1,8 @@
define(
['jquery', 'alertify', 'pgadmin', 'sources/gettext'],
function($, alertify, pgAdmin, gettext) {
['jquery', 'alertify', 'pgadmin', 'underscore.string', 'sources/gettext',
'sources/url_for'
],
function($, alertify, pgAdmin, S, gettext, url_for) {
pgAdmin = pgAdmin || window.pgAdmin || {};
/* Return back, this has been called more than once */
@ -39,9 +41,11 @@ define(
}
var content = '';
$.get("{{ url_for('about.index') }}",
$.get(url_for('about.index'),
function(data) {
alertify.aboutDialog(gettext("About %(appname)s", {appname: "{{ config.APP_NAME }}"}), data).resizeTo(800, 450);
alertify.aboutDialog(
S(gettext("About %s")).sprintf(pgAdmin.Browser.utils.app_name).value(), data
).resizeTo(800, 450);
});
}
};

View File

@ -523,9 +523,9 @@ def index():
return response
@blueprint.route("/js/browser.js")
@blueprint.route("/js/utils.js")
@login_required
def browser_js():
def utils():
layout = get_setting('Browser/Layout', default='')
snippets = []
@ -559,7 +559,7 @@ def browser_js():
snippets.extend(submodule.jssnippets)
return make_response(
render_template(
'browser/js/browser.js',
'browser/js/utils.js',
layout=layout,
jssnippets=snippets,
pg_help_path=pg_help_path,
@ -569,7 +569,7 @@ def browser_js():
editor_wrap_code=editor_wrap_code,
editor_brace_matching=brace_matching,
editor_insert_pair_brackets=insert_pair_brackets,
_=gettext
app_name=config.APP_NAME
),
200, {'Content-Type': 'application/x-javascript'})

View File

@ -217,7 +217,7 @@ define('pgadmin.node.language', [
}
return true;
}
}, pgBrowser.SecurityGroupUnderSchema, {
}, {
id: 'lanacl', label: gettext('Privileges'), type: 'collection',
group: 'security', control: 'unique-col-collection', mode: ['edit', 'create'],
model: pgBrowser.Node.PrivilegeRoleModel.extend({

View File

@ -237,8 +237,8 @@ define('pgadmin.node.collation', [
if ('coll-collation' == d._type) {
//Check if we are not child of catalog
prev_i = t.hasParent(i) ? t.parent(i) : null;
prev_d = prev_i ? t.itemData(prev_i) : null;
var prev_i = t.hasParent(i) ? t.parent(i) : null,
prev_d = prev_i ? t.itemData(prev_i) : null;
if( prev_d._type == 'catalog') {
return false;
} else {

View File

@ -306,8 +306,8 @@ define('pgadmin.node.domain', [
if ('coll-domain' == d._type) {
//Check if we are not child of catalog
prev_i = t.hasParent(i) ? t.parent(i) : null;
prev_d = prev_i ? t.itemData(prev_i) : null;
var prev_i = t.hasParent(i) ? t.parent(i) : null,
prev_d = prev_i ? t.itemData(prev_i) : null;
if( prev_d._type == 'catalog') {
return false;
} else {

View File

@ -25,9 +25,9 @@ define('pgadmin.node.foreign-table', [
this.$el.empty();
var model = this.model;
var column = this.column;
editable = this.column.get("editable");
var editable = this.column.get("editable");
var is_editable = _.isFunction(editable) ? !!editable.apply(column, [model]) : !!editable;
is_editable = _.isFunction(editable) ? !!editable.apply(column, [model]) : !!editable;
if (is_editable){ this.$el.addClass("editable"); }
else { this.$el.removeClass("editable"); }
@ -364,7 +364,7 @@ define('pgadmin.node.foreign-table', [
cache_node = (cache_node && pgBrowser.Nodes['cache_node']) || node;
m.trigger('pgadmin:view:fetching', m, self.field);
data = {attrelid: table_id}
var data = {attrelid: table_id}
// Fetching Columns data for the selected table.
$.ajax({
@ -591,8 +591,8 @@ define('pgadmin.node.foreign-table', [
'cache_level': 'database',
transform: function(d, self){
if (this.field.get('mode') == 'edit') {
oid = this.model.get('oid');
s = _.findWhere(d, {'id': oid});
var oid = this.model.get('oid');
var s = _.findWhere(d, {'id': oid});
if (s) {
d = _.reject(d, s);
}
@ -697,8 +697,8 @@ define('pgadmin.node.foreign-table', [
if ('coll-foreign-table' == d._type) {
//Check if we are not child of catalog
prev_i = t.hasParent(i) ? t.parent(i) : null;
prev_d = prev_i ? t.itemData(prev_i) : null;
var prev_i = t.hasParent(i) ? t.parent(i) : null,
prev_d = prev_i ? t.itemData(prev_i) : null;
if( prev_d._type == 'catalog') {
return false;
} else {

View File

@ -14,7 +14,7 @@ define('pgadmin.node.fts_configuration', [
// Define the schema for the token/dictionary list
schema: [{
id: 'token', label:'Token', type:'text', group: null,
cellHeaderClasses:'width_percent_50', editable: true,
cellHeaderClasses:'width_percent_50',
editable: false, cell: 'string', url: 'tokens'
},{
id: 'dictname', label: 'Dictionaries', type: 'text', group:null,
@ -57,6 +57,7 @@ define('pgadmin.node.fts_configuration', [
this, arguments
);
var that;
var self = that = this,
node = 'fts_configuration',
headerSchema = [{
@ -134,7 +135,7 @@ define('pgadmin.node.fts_configuration', [
/*
* Transform the data
*/
transform = (this.field.get('transform')
var transform = (this.field.get('transform')
|| self.defaults.transform);
if (transform && _.isFunction(transform)) {
self.field.set('options', transform.bind(self, data));
@ -338,7 +339,7 @@ define('pgadmin.node.fts_configuration', [
// Find if token exists in grid
self.collection.each(function(m) {
_.each(checkVars, function(v) {
val = m.get(v);
var val = m.get(v);
if(val == token) {
idx = coll.indexOf(m);
}
@ -592,8 +593,8 @@ define('pgadmin.node.fts_configuration', [
if ('coll-fts_configuration' == d._type) {
//Check if we are not child of catalog
prev_i = t.hasParent(i) ? t.parent(i) : null;
prev_d = prev_i ? t.itemData(prev_i) : null;
var prev_i = t.hasParent(i) ? t.parent(i) : null,
prev_d = prev_i ? t.itemData(prev_i) : null;
if( prev_d._type == 'catalog') {
return false;
} else {

View File

@ -197,8 +197,8 @@ define('pgadmin.node.fts_dictionary', [
if ('coll-fts_dictionary' == d._type) {
//Check if we are not child of catalog
prev_i = t.hasParent(i) ? t.parent(i) : null;
prev_d = prev_i ? t.itemData(prev_i) : null;
var prev_i = t.hasParent(i) ? t.parent(i) : null,
prev_d = prev_i ? t.itemData(prev_i) : null;
if( prev_d._type == 'catalog') {
return false;
} else {

View File

@ -112,7 +112,6 @@ define('pgadmin.node.fts_parser', [
type: 'text', disabled: function(m) { return !m.isNew(); },
control: 'node-ajax-options', url: 'end_functions',
group: gettext('Definition'), cache_level: 'database',
cache_node: 'schema',
cache_node: 'schema'
},{
id: 'prslextype', label: gettext('Lextypes function'),
@ -214,8 +213,8 @@ define('pgadmin.node.fts_parser', [
if ('coll-fts_parser' == d._type) {
//Check if we are not child of catalog
prev_i = t.hasParent(i) ? t.parent(i) : null;
prev_d = prev_i ? t.itemData(prev_i) : null;
var prev_i = t.hasParent(i) ? t.parent(i) : null,
prev_d = prev_i ? t.itemData(prev_i) : null;
if( prev_d._type == 'catalog') {
return false;
} else {

View File

@ -153,8 +153,8 @@ define('pgadmin.node.fts_template', [
if ('coll-fts_template' == d._type) {
//Check if we are not child of catalog
prev_i = t.hasParent(i) ? t.parent(i) : null;
prev_d = prev_i ? t.itemData(prev_i) : null;
var prev_i = t.hasParent(i) ? t.parent(i) : null,
prev_d = prev_i ? t.itemData(prev_i) : null;
if( prev_d._type == 'catalog') {
return false;
} else {

View File

@ -34,7 +34,7 @@ define('pgadmin.node.function', [
'node-ajax-options', cellHeaderClasses: 'width_percent_30',
control: 'node-ajax-options', type: 'text', url: 'get_types',
editable: function(m) {
node_info = this.get('node_info');
var node_info = this.get('node_info');
if(node_info && 'catalog' in node_info) {
return false;
}
@ -49,7 +49,7 @@ define('pgadmin.node.function', [
{'label': 'INOUT', 'value': 'INOUT'},
{'label': 'VARIADIC', 'value': 'VARIADIC'}
], editable: function(m) {
node_info = this.get('node_info');
var node_info = this.get('node_info');
if(node_info && 'catalog' in node_info) {
return false;
}
@ -65,7 +65,7 @@ define('pgadmin.node.function', [
],
toJSON: Backbone.Model.prototype.toJSON,
isInCatalog: function(m){
node_info = this.get('node_info');
var node_info = this.get('node_info');
if(node_info && 'catalog' in node_info) {
return false;
}
@ -131,7 +131,7 @@ define('pgadmin.node.function', [
var isNew = (_.size(attrs) === 0);
if (isNew) {
// Set Selected Schema
schema_id = args.node_info.schema._id
var schema_id = args.node_info.schema._id;
this.set({'pronamespace': schema_id}, {silent: true});
// Set Current User
@ -217,7 +217,7 @@ define('pgadmin.node.function', [
mode: ['create'], visible: 'isVisible'
},{
id: 'prorettypename', label: gettext('Return type'), cell: 'string',
type: 'text', group: gettext('Definition'), disabled: true,
type: 'text', group: gettext('Definition'),
mode: ['properties', 'edit'], disabled: 'isDisabled', visible: 'isVisible'
}, {
id: 'lanname', label: gettext('Language'), cell: 'string',
@ -457,8 +457,8 @@ define('pgadmin.node.function', [
if ('coll-function' == d._type) {
//Check if we are not child of catalog
prev_i = t.hasParent(i) ? t.parent(i) : null;
prev_d = prev_i ? t.itemData(prev_i) : null;
var prev_i = t.hasParent(i) ? t.parent(i) : null,
prev_d = prev_i ? t.itemData(prev_i) : null;
if( prev_d._type == 'catalog') {
return false;
} else {

View File

@ -17,7 +17,7 @@ define('pgadmin.node.procedure', [
});
};
pgSchemaNode = pgBrowser.Nodes['schema'];
var pgSchemaNode = pgBrowser.Nodes['schema'];
// Inherit Functions Node
if (!pgBrowser.Nodes['procedure']) {

View File

@ -64,7 +64,7 @@ define('pgadmin.node.trigger_function', [
var isNew = (_.size(attrs) === 0);
if (isNew) {
// Set Selected Schema
schema_id = args.node_info.schema._id
var schema_id = args.node_info.schema._id
this.set({'pronamespace': schema_id}, {silent: true});
// Set Current User
@ -153,7 +153,7 @@ define('pgadmin.node.trigger_function', [
]
},{
id: 'prorettypename', label: gettext('Return type'), cell: 'string',
type: 'text', group: gettext('Definition'), disabled: true,
type: 'text', group: gettext('Definition'),
mode: ['properties', 'edit'], disabled: 'isDisabled', visible: 'isVisible'
}, {
id: 'lanname', label: gettext('Language'), cell: 'string',
@ -378,8 +378,8 @@ define('pgadmin.node.trigger_function', [
if ('coll-trigger_function' == d._type) {
//Check if we are not child of catalog
prev_i = t.hasParent(i) ? t.parent(i) : null;
prev_d = prev_i ? t.itemData(prev_i) : null;
var prev_i = t.hasParent(i) ? t.parent(i) : null,
prev_d = prev_i ? t.itemData(prev_i) : null;
if( prev_d._type == 'catalog') {
return false;
} else {

View File

@ -74,8 +74,8 @@ define('pgadmin.node.sequence', [
if ('coll-sequence' == d._type) {
//Check if we are not child of catalog
prev_i = t.hasParent(i) ? t.parent(i) : null;
prev_d = prev_i ? t.itemData(prev_i) : null;
var prev_i = t.hasParent(i) ? t.parent(i) : null,
prev_d = prev_i ? t.itemData(prev_i) : null;
if( prev_d._type == 'catalog') {
return false;
} else {
@ -202,7 +202,7 @@ define('pgadmin.node.sequence', [
validate: function() {
var msg = undefined,
minimum = this.get('minimum'),
maximum = this.get('maximum');
maximum = this.get('maximum'),
start = this.get('start');
if (_.isUndefined(this.get('name'))

View File

@ -13,7 +13,7 @@ define('pgadmin.node.schema', [
initialize: function() {
Backform.Control.prototype.initialize.apply(this, arguments);
var self = this,
m = this.model;
m = this.model,
url = self.field.get('url');
if (url && m.isNew()) {
@ -457,9 +457,9 @@ define('pgadmin.node.schema', [
return true;
//Check if we are not child of catalog
prev_i = t.hasParent(i) ? t.parent(i) : null;
var prev_i = t.hasParent(i) ? t.parent(i) : null,
prev_d = prev_i ? t.itemData(prev_i) : null;
if( prev_d && prev_d._type == 'catalog') {
if(prev_d && prev_d._type == 'catalog') {
return false;
}
i = t.hasParent(i) ? t.parent(i) : null;
@ -476,7 +476,7 @@ define('pgadmin.node.schema', [
t = pgBrowser.tree;
do {
d = t.itemData(i);
var d = t.itemData(i);
if (
d._type in pgBrowser.Nodes && pgBrowser.Nodes[d._type].hasId
) {
@ -509,7 +509,8 @@ define('pgadmin.node.schema', [
column = this.column,
editable = this.column.get("editable"),
input = this.$el.find('input[type=checkbox]').first(),
self_name = column.get('name');
self_name = column.get('name'),
is_editable;
is_editable = _.isFunction(editable) ? !!editable.apply(column, [model]) : !!editable;
if (is_editable) {

View File

@ -51,7 +51,7 @@ define('pgadmin.node.check_constraints', [
},
callbacks: {
validate_check_constraint: function(args) {
var input = args || {};
var input = args || {},
obj = this,
t = pgBrowser.tree,
i = input.item || t.selected(),

View File

@ -286,7 +286,7 @@ define('pgadmin.node.exclusion_constraint', [
},
remove: function () {
if(self.model.handler) {
tableCols = self.model.top.get('columns');
var tableCols = self.model.top.get('columns');
this.stopListening(tableCols, 'remove' , this.removeColumn);
this.stopListening(tableCols, 'change:name' , this.resetColOptions);
this.stopListening(tableCols, 'change:cltype' , this.resetColOptions);
@ -561,7 +561,7 @@ define('pgadmin.node.exclusion_constraint', [
newRow.addClass("new");
$(newRow).pgMakeVisible('backform-tab');
} else {
delete m;
//delete m;
}
return false;
@ -770,7 +770,7 @@ define('pgadmin.node.exclusion_constraint', [
}
},{
id: 'columns', label: gettext('Columns'),
type: 'collection', group: gettext('Columns'), disabled: false,
type: 'collection', group: gettext('Columns'),
deps:['amname'], canDelete: true, editable: false,
canAdd: function(m) {
// We can't update columns of existing exclusion constraint.
@ -815,7 +815,7 @@ define('pgadmin.node.exclusion_constraint', [
}, 10);
setTimeout(function () {
constraints = self.model.top.get("exclude_constraint");
var constraints = self.model.top.get("exclude_constraint");
var removed = [];
constraints.each(function(constraint) {
if (constraint.get("columns").length == 0) {
@ -837,7 +837,7 @@ define('pgadmin.node.exclusion_constraint', [
}, 10);
setTimeout(function () {
constraints = self.model.top.get("exclude_constraint");
var constraints = self.model.top.get("exclude_constraint");
var removed = [];
constraints.each(function(constraint) {
if (constraint.get("columns").length == 0) {

View File

@ -225,7 +225,7 @@ define('pgadmin.node.foreign_key', [
/*
* Transform the data
*/
transform = this.field.get('transform') || self.defaults.transform;
var transform = this.field.get('transform') || self.defaults.transform;
if (transform && _.isFunction(transform)) {
// We will transform the data later, when rendering.
// It will allow us to generate different data based on the
@ -494,7 +494,7 @@ define('pgadmin.node.foreign_key', [
newRow.addClass("new");
$(newRow).pgMakeVisible('backform-tab');
} else {
delete m;
//delete m;
}
return false;
@ -534,7 +534,7 @@ define('pgadmin.node.foreign_key', [
var self = this,
url = 'get_coveringindex',
m = self.model
m = self.model,
cols = [],
coveringindex = null;
@ -610,7 +610,6 @@ define('pgadmin.node.foreign_key', [
sqlCreateHelp: 'ddl-constraints.html',
dialogHelp: url_for('help.static', {'filename': 'foreign_key_dialog.html'}),
hasSQL: true,
hasDepends: false,
parent_type: ['table','partition'],
canDrop: true,
canDropCascade: true,
@ -641,7 +640,7 @@ define('pgadmin.node.foreign_key', [
},
callbacks: {
validate_foreign_key: function(args) {
var input = args || {};
var input = args || {},
obj = this,
t = pgBrowser.tree,
i = input.item || t.selected(),
@ -926,7 +925,7 @@ define('pgadmin.node.foreign_key', [
}, 10);
setTimeout(function () {
constraints = self.model.top.get("foreign_key");
var constraints = self.model.top.get("foreign_key");
var removed = [];
constraints.each(function(constraint) {
if (constraint.get("columns").length == 0) {

View File

@ -1,6 +1,8 @@
define('pgadmin.node.constraints', [
'sources/gettext', 'jquery', 'underscore', 'underscore.string', 'pgadmin',
'pgadmin.browser', 'pgadmin.browser.collection'{% for c in constraints %}, 'pgadmin.node.{{ c|safe }}'{%endfor%}
'pgadmin.browser', 'pgadmin.browser.collection', 'pgadmin.node.unique_constraint',
'pgadmin.node.check_constraints', 'pgadmin.node.foreign_key',
'pgadmin.node.exclusion_constraint', 'pgadmin.node.primary_key'
], function(gettext, $, _, S, pgAdmin, pgBrowser) {
if (!pgBrowser.Nodes['coll-constraints']) {

View File

@ -32,7 +32,7 @@ define('pgadmin.node.index', [
editable = this.column.get("editable"),
input = this.$el.find('select').first();
is_editable = _.isFunction(editable) ? !!editable.apply(column, [model]) : !!editable;
var is_editable = _.isFunction(editable) ? !!editable.apply(column, [model]) : !!editable;
if (is_editable) {
this.$el.addClass("editable");
input.prop('disabled', false);
@ -165,7 +165,7 @@ define('pgadmin.node.index', [
if (_.isUndefined(this.get('colname'))
|| String(this.get('colname')).replace(/^\s+|\s+$/g, '') == '') {
msg = gettext('Column Name cannot be empty.');
var msg = gettext('Column Name cannot be empty.');
this.errorModel.set('colname', msg);
return msg;
}

View File

@ -230,12 +230,12 @@ define('pgadmin.node.rule', [
if ('coll-rule' == d._type) {
//Check if we are not child of rule
prev_i = t.hasParent(i) ? t.parent(i) : null;
prev_d = prev_i ? t.itemData(prev_i) : null;
prev_j = t.hasParent(prev_i) ? t.parent(prev_i) : null;
prev_e = prev_j ? t.itemData(prev_j) : null;
prev_k = t.hasParent(prev_j) ? t.parent(prev_j) : null;
prev_f = prev_k ? t.itemData(prev_k) : null;
var prev_i = t.hasParent(i) ? t.parent(i) : null,
prev_d = prev_i ? t.itemData(prev_i) : null,
prev_j = t.hasParent(prev_i) ? t.parent(prev_i) : null,
prev_e = prev_j ? t.itemData(prev_j) : null,
prev_k = t.hasParent(prev_j) ? t.parent(prev_j) : null,
prev_f = prev_k ? t.itemData(prev_k) : null;
if( prev_f._type == 'catalog') {
return false;
} else {

View File

@ -1,4 +1,4 @@
define(
define('pgadmin.node.table_partition_utils',
['sources/gettext', 'jquery', 'underscore', 'pgadmin.browser',
'backform','backgrid', 'pgadmin.browser.collection'],
function(gettext, $, _, pgBrowser, Backform, Backgrid) {
@ -205,21 +205,21 @@ function(gettext, $, _, pgBrowser, Backform, Backgrid) {
if (_.isUndefined(col_type) || _.isNull(col_type) ||
String(col_type).replace(/^\s+|\s+$/g, '') == '') {
msg = gettext('Partition key type cannot be empty.');
var msg = gettext('Partition key type cannot be empty.');
this.errorModel.set('key_type', msg);
return msg;
}
else if (col_type == 'column' &&
_.isUndefined(pt_column) || _.isNull(pt_column) ||
String(pt_column).replace(/^\s+|\s+$/g, '') == '') {
msg = gettext('Partition key column cannot be empty.');
var msg = gettext('Partition key column cannot be empty.');
this.errorModel.set('pt_column', msg);
return msg;
}
else if (col_type == 'expression' &&
_.isUndefined(expression) || _.isNull(expression) ||
String(expression).replace(/^\s+|\s+$/g, '') == '') {
msg = gettext('Partition key expression cannot be empty.');
var msg = gettext('Partition key expression cannot be empty.');
this.errorModel.set('expression', msg);
return msg;
}
@ -306,7 +306,7 @@ function(gettext, $, _, pgBrowser, Backform, Backgrid) {
if (_.isUndefined(partition_name) || _.isNull(partition_name) ||
String(partition_name).replace(/^\s+|\s+$/g, '') == '') {
msg = gettext('Partition name cannot be empty.');
var msg = gettext('Partition name cannot be empty.');
this.errorModel.set('partition_name', msg);
return msg;
}
@ -314,19 +314,19 @@ function(gettext, $, _, pgBrowser, Backform, Backgrid) {
if (this.top.get('partition_type') == 'range') {
if (_.isUndefined(values_from) || _.isNull(values_from) ||
String(values_from).replace(/^\s+|\s+$/g, '') == '') {
msg = gettext('For range partition From field cannot be empty.');
var msg = gettext('For range partition From field cannot be empty.');
this.errorModel.set('values_from', msg);
return msg;
} else if (_.isUndefined(values_to) || _.isNull(values_to) ||
String(values_to).replace(/^\s+|\s+$/g, '') == '') {
msg = gettext('For range partition To field cannot be empty.');
var msg = gettext('For range partition To field cannot be empty.');
this.errorModel.set('values_to', msg);
return msg;
}
} else if (this.top.get('partition_type') == 'list') {
if (_.isUndefined(values_in) || _.isNull(values_in) ||
String(values_in).replace(/^\s+|\s+$/g, '') == '') {
msg = gettext('For list partition In field cannot be empty.');
var msg = gettext('For list partition In field cannot be empty.');
this.errorModel.set('values_in', msg);
return msg;
}

View File

@ -114,7 +114,7 @@ define('pgadmin.node.table', [
set_triggers: function(args, params) {
// This function will send request to enable or
// disable triggers on table level
var input = args || {};
var input = args || {},
obj = this,
t = pgBrowser.tree,
i = input.item || t.selected(),
@ -162,7 +162,7 @@ define('pgadmin.node.table', [
this.callbacks.truncate.apply(this, [args, params]);
},
truncate: function(args, params) {
var input = args || {};
var input = args || {},
obj = this,
t = pgBrowser.tree,
i = input.item || t.selected(),
@ -708,7 +708,7 @@ define('pgadmin.node.table', [
}]
},{
id: 'typname', label: gettext('Of type'), type: 'text',
control: 'node-ajax-options', mode: ['properties', 'create', 'edit'],
mode: ['properties', 'create', 'edit'],
disabled: 'checkOfType', url: 'get_oftype', group: gettext('Advanced'),
deps: ['coll_inherits'], transform: function(data, cell) {
var control = cell || this,
@ -1244,7 +1244,7 @@ define('pgadmin.node.table', [
var self = this,
url = 'get_columns',
m = self.model.top || self.model,
old_columns = _.clone(m.get('columns'))
old_columns = _.clone(m.get('columns')),
data = undefined,
node = this.field.get('schema_node'),
node_info = this.field.get('node_info'),
@ -1291,7 +1291,7 @@ define('pgadmin.node.table', [
if ('coll-table' == d._type) {
//Check if we are not child of catalog
prev_i = t.hasParent(i) ? t.parent(i) : null;
var prev_i = t.hasParent(i) ? t.parent(i) : null,
prev_d = prev_i ? t.itemData(prev_i) : null;
if( prev_d._type == 'catalog') {
return false;

View File

@ -24,9 +24,9 @@ define('pgadmin.node.type', [
this.$el.empty();
var model = this.model;
var column = this.column;
editable = this.column.get("editable");
var editable = this.column.get("editable");
is_editable = _.isFunction(editable) ? !!editable.apply(column, [model]) : !!editable;
var is_editable = _.isFunction(editable) ? !!editable.apply(column, [model]) : !!editable;
if (is_editable){ this.$el.addClass("editable"); }
else { this.$el.removeClass("editable"); }
@ -48,7 +48,7 @@ define('pgadmin.node.type', [
editable = this.column.get("editable"),
input = this.$el.find('select').first();
is_editable = _.isFunction(editable) ? !!editable.apply(column, [model]) : !!editable;
var is_editable = _.isFunction(editable) ? !!editable.apply(column, [model]) : !!editable;
if (is_editable) {
this.$el.addClass("editable");
input.prop('disabled', false);
@ -337,7 +337,6 @@ define('pgadmin.node.type', [
id: 'typtype', label: gettext('Type'),
mode: ['create','edit'], disabled: 'inSchemaWithModelCheck',
group: gettext('Definition'),
mode: ['edit', 'create'],
select2: { width: "50%", allowClear: false },
options: function(obj) {
return [
@ -929,7 +928,7 @@ define('pgadmin.node.type', [
if ('coll-type' == d._type) {
//Check if we are not child of catalog
prev_i = t.hasParent(i) ? t.parent(i) : null;
var prev_i = t.hasParent(i) ? t.parent(i) : null,
prev_d = prev_i ? t.itemData(prev_i) : null;
if( prev_d._type == 'catalog') {
return false;

View File

@ -261,8 +261,8 @@ define('pgadmin.node.mview', [
if ('coll-mview' == d._type) {
// Check if we are not child of view
prev_i = t.hasParent(i) ? t.parent(i) : null;
prev_d = prev_i ? t.itemData(prev_i) : null;
var prev_i = t.hasParent(i) ? t.parent(i) : null,
prev_d = prev_i ? t.itemData(prev_i) : null;
if( prev_d._type == 'catalog') {
return false;
} else {

View File

@ -113,8 +113,7 @@ define('pgadmin.node.view', [
id: 'schema', label: gettext('Schema'), cell: 'string', first_empty: false,
control: 'node-list-by-name', type: 'text', cache_level: 'database',
node: 'schema', disabled: 'notInSchema', mode: ['create', 'edit'],
select2: { allowClear: false }, cache_node: 'database',
cache_level: 'database'
select2: { allowClear: false }, cache_node: 'database'
},{
id: 'system_view', label: gettext('System view?'), cell: 'string',
type: 'switch', disabled: true, mode: ['properties']
@ -221,8 +220,8 @@ define('pgadmin.node.view', [
if ('coll-view' == d._type) {
// Check if we are not child of view
prev_i = t.hasParent(i) ? t.parent(i) : null;
prev_d = prev_i ? t.itemData(prev_i) : null;
var prev_i = t.hasParent(i) ? t.parent(i) : null,
prev_d = prev_i ? t.itemData(prev_i) : null;
if( prev_d._type == 'catalog') {
return false;
} else {

View File

@ -1,6 +1,6 @@
define('pgadmin.node.database', [
'sources/gettext', 'sources/url_for', 'jquery', 'underscore',
'underscore.string', 'pgadmin', 'pgadmin.browser', 'alertify',
'underscore.string', 'pgadmin', 'pgadmin.browser.utils', 'alertify',
'sources/alerts/alertify_wrapper',
'pgadmin.browser.collection', 'pgadmin.browser.server.privilege',

View File

@ -1,31 +1,5 @@
(function(root, factory) {
// Set up Backform appropriately for the environment. Start with AMD.
if (typeof define === 'function' && define.amd) {
define(['sources/gettext', 'underscore', 'jquery', 'backbone', 'backform', 'backgrid', 'alertify', 'pgadmin.browser.node'],
function(gettext, _, $, Backbone, Backform, Backgrid, Alertify, pgNode) {
// Export global even in AMD case in case this script is loaded with
// others that may still expect a global Backform.
return factory(root, gettext, _, $, Backbone, Backform, Backgrid, Alertify, pgNode);
});
// Next for Node.js or CommonJS. jQuery may not be needed as a module.
} else if (typeof exports !== 'undefined') {
var _ = require('underscore') || root._,
$ = root.jQuery || root.$ || root.Zepto || root.ender,
Backbone = require('backbone') || root.Backbone,
Backform = require('backform') || root.Backform;
Backgrid = require('backgrid') || root.Backgrid;
Alertify = require('alertify') || root.Alertify;
pgAdmin = require('pgadmin.browser.node') || root.pgAdmin.Browser.Node,
gettext = require('sources/gettext') || root.gettext;
factory(root, gettext, _, $, Backbone, Backform, Alertify, pgNode);
// Finally, as a browser global.
} else {
factory(root, root.gettext, root._, (root.jQuery || root.Zepto || root.ender || root.$), root.Backbone, root.Backform, root.Backgrid, root.alertify, root.pgAdmin.Browser.Node);
}
} (this, function(root, gettext, _, $, Backbone, Backform, Backgrid, Alertify, pgNode) {
define(['sources/gettext', 'underscore', 'jquery', 'backbone', 'backform', 'backgrid', 'alertify', 'pgadmin.browser.node', 'pgadmin.browser.node.ui'],
function(gettext, _, $, Backbone, Backform, Backgrid, Alertify, pgNode) {
/**
* Each Privilege, supporeted by an database object, will be represented
* using this Model.
@ -715,4 +689,4 @@
return PrivilegeRoleModel;
}));
});

View File

@ -3,7 +3,7 @@ define('pgadmin.node.server', [
'underscore.string', 'pgadmin', 'pgadmin.browser', 'alertify',
'pgadmin.server.supported_servers',
'pgadmin.user_management.current_user',
'sources/alerts/alertify_wrapper',
'sources/alerts/alertify_wrapper', 'pgadmin.browser.server.privilege'
], function(
gettext, url_for, $, _, S, pgAdmin, pgBrowser, alertify,
supported_servers, current_user, AlertifyWrapper
@ -1037,7 +1037,7 @@ define('pgadmin.node.server', [
};
data.is_connecting = true;
url = obj.generate_url(item, "connect", data, true);
var url = obj.generate_url(item, "connect", data, true);
$.post(url)
.done(function(res) {
if (res.success == 1) {

View File

@ -1,36 +1,8 @@
(function(root, factory) {
// Set up Backform appropriately for the environment. Start with AMD.
if (typeof define === 'function' && define.amd) {
define([
'underscore', 'jquery', 'backbone', 'backform', 'backgrid', 'alertify',
'pgadmin', 'pgadmin.browser.node', 'pgadmin.browser.node.ui'
],
function(_, $, Backbone, Backform, Backgrid, Alertify, pgAdmin, pgNode) {
// Export global even in AMD case in case this script is loaded with
// others that may still expect a global Backform.
return factory(root, _, $, Backbone, Backform, Alertify, pgAdmin, pgNode);
});
// Next for Node.js or CommonJS. jQuery may not be needed as a module.
} else if (typeof exports !== 'undefined') {
var _ = require('underscore') || root._,
$ = root.jQuery || root.$ || root.Zepto || root.ender,
Backbone = require('backbone') || root.Backbone,
Backform = require('backform') || root.Backform;
Alertify = require('alertify') || root.Alertify;
pgAdmin = require('pgadmin') || root.pgAdmin,
pgNode = require('pgadmin.browser.node') || root.pgAdmin.Browser.Node;
factory(root, _, $, Backbone, Backform, Alertify, pgAdmin, pgNode);
// Finally, as a browser global.
} else {
factory(
root, root._, (root.jQuery || root.Zepto || root.ender || root.$),
root.Backbone, root.Backform, root.pgAdmin.Browser.Node
);
}
} (this, function(root, _, $, Backbone, Backform, Alertify, pgAdmin, pgNode) {
define([
'underscore', 'jquery', 'backbone', 'backform', 'backgrid', 'alertify',
'pgadmin', 'pgadmin.browser.node', 'pgadmin.browser.node.ui'
],
function(_, $, Backbone, Backform, Backgrid, Alertify, pgAdmin, pgNode) {
/*
* cellFunction for variable control.
@ -159,7 +131,7 @@
},
schema: [
{
id: 'name', label:'Name', type:'text', editable: true, cellHeaderClasses: 'width_percent_30',
id: 'name', label:'Name', type:'text', cellHeaderClasses: 'width_percent_30',
editable: function(m) {
return (m instanceof Backbone.Collection) ? true : m.isNew();
},
@ -513,8 +485,6 @@
newRow.addClass("new");
$(newRow).pgMakeVisible('backform-tab');
} else {
delete m;
}
return false;
@ -522,4 +492,4 @@
});
return VariableModel;
}));
});

View File

@ -1,4 +1,4 @@
define('pgadmin.node.server-group', [
define('pgadmin.node.server_group', [
'sources/gettext', 'sources/url_for', 'jquery', 'underscore', 'pgadmin',
'backbone', 'pgadmin.browser', 'pgadmin.browser.node'
], function(gettext, url_for, $, _, pgAdmin, Backbone) {

View File

@ -52,8 +52,6 @@ function(_, S, pgAdmin, $, Backbone) {
}
}
else {
if (obj)
delete obj;
obj = null;
}
self.set(s.id, obj, {silent: true});
@ -81,8 +79,6 @@ function(_, S, pgAdmin, $, Backbone) {
}
obj.set(val, {parse: true, silent: true});
} else {
if (obj)
delete obj;
obj = null;
}
res[s.id] = obj;
@ -258,19 +254,16 @@ function(_, S, pgAdmin, $, Backbone) {
if (opts && opts.stop)
this.stopSession();
for(id in this.objects) {
for(var id in this.objects) {
obj = this.get(id);
if (obj) {
if (obj instanceof pgBrowser.DataModel) {
obj.reset(opts);
delete obj;
} else if (obj instanceof Backbone.Model) {
obj.clear(opts);
delete obj;
} else if (obj instanceof pgBrowser.DataCollection) {
obj.reset(opts);
delete obj;
} else if (obj instanceof Backbone.Collection) {
obj.each(function(m) {
if (m instanceof Backbone.DataModel) {
@ -280,7 +273,6 @@ function(_, S, pgAdmin, $, Backbone) {
});
if (!(opts instanceof Array)){ opts = [opts] }
Backbone.Collection.prototype.reset.apply(obj, opts);
delete obj;
}
}
}
@ -331,7 +323,7 @@ function(_, S, pgAdmin, $, Backbone) {
self = this,
msg;
attrChanged = function(v, k) {
var attrChanged = function(v, k) {
if (k in self.objects) {
return;
}
@ -520,7 +512,7 @@ function(_, S, pgAdmin, $, Backbone) {
if (!objName) {
var hasPrimaryKey = obj.primary_key &&
typeof(obj.primary_key) === 'function';
key = hasPrimaryKey ? obj.primary_key() : obj.cid,
var key = hasPrimaryKey ? obj.primary_key() : obj.cid,
comparator = hasPrimaryKey ?
function(k) {
var o = self.get('k');
@ -570,7 +562,7 @@ function(_, S, pgAdmin, $, Backbone) {
if (!objName) {
var hasPrimaryKey = (obj.primary_key &&
(typeof(obj.primary_key) === 'function'));
key = hasPrimaryKey ? obj.primary_key() : obj.cid,
var key = hasPrimaryKey ? obj.primary_key() : obj.cid,
comparator = hasPrimaryKey ?
function(k) {
var o = self.get('k');
@ -614,7 +606,7 @@ function(_, S, pgAdmin, $, Backbone) {
};
if (obj instanceof Backbone.Collection) {
for (idx in obj.models) {
for (var idx in obj.models) {
if (validate(obj.models[idx]))
break;
}
@ -1248,7 +1240,7 @@ function(_, S, pgAdmin, $, Backbone) {
self.clearInvalidSessionIfModelValid(m);
}
new_conflicting_models = self.where(condition);
var new_conflicting_models = self.where(condition);
if (new_conflicting_models.length == 0) {
self.clearInvalidSessionIfModelValid(model);
} else if (new_conflicting_models.length == 1) {

View File

@ -1,8 +1,8 @@
define([
'sources/gettext', 'jquery', 'underscore', 'pgadmin', 'backbone', 'backform', 'alertify',
'pgadmin.browser.node'
'sources/gettext', 'jquery', 'underscore', 'pgadmin', 'backbone', 'backform',
'alertify', 'backgrid', 'select2', 'pgadmin.browser.node'
],
function(gettext, $, _, pgAdmin, Backbone, Backform, Alertify, Node) {
function(gettext, $, _, pgAdmin, Backbone, Backform, Alertify, Backgrid) {
var pgBrowser = pgAdmin.Browser;
@ -169,7 +169,7 @@ function(gettext, $, _, pgAdmin, Backbone, Backform, Alertify, Node) {
/*
* Transform the data
*/
transform = this.field.get('transform') || self.defaults.transform;
var transform = this.field.get('transform') || self.defaults.transform;
if (transform && _.isFunction(transform)) {
// We will transform the data later, when rendering.
// It will allow us to generate different data based on the
@ -405,7 +405,7 @@ function(gettext, $, _, pgAdmin, Backbone, Backform, Alertify, Node) {
/*
* Transform the data
*/
transform = column.get('transform') || self.defaults.transform;
var transform = column.get('transform') || self.defaults.transform;
if (transform && _.isFunction(transform)) {
// We will transform the data later, when rendering.
// It will allow us to generate different data based on the

View File

@ -133,7 +133,7 @@ function(_, Backbone, pgAdmin, pgBrowser) {
this.options.disable_prev = (this.options.disable_prev ? true : this.evalASFunc(this.currPage.disable_prev));
this.options.disable_cancel = (this.currPage.canCancel ? true : this.evalASFunc(this.currPage.disable_cancel));
that = this;
var that = this;
/* HTML Content */
if (data.html) { data.content = data.html; }
@ -149,10 +149,9 @@ function(_, Backbone, pgAdmin, pgBrowser) {
return this;
},
nextPage: function() {
this.options.curr_page.el = this.$el;
if (!this.beforeNext()) { return false; }
page_id = this.onNext();
var page_id = this.onNext();
if (page_id ) {
this.currPage = this.collection.get(page_id).toJSON();
@ -171,7 +170,7 @@ function(_, Backbone, pgAdmin, pgBrowser) {
prevPage: function() {
if (!this.beforePrev()) { return false; }
page_id = this.onPrev();
var page_id = this.onPrev();
if (page_id){
this.currPage = this.collection.get(page_id).toJSON();
@ -264,16 +263,16 @@ function(_, Backbone, pgAdmin, pgBrowser) {
},
onDialogHelp: function() {
// See if we can find an existing panel, if not, create one
pnlDialogHelp = pgBrowser.docker.findPanels('pnl_online_help')[0];
var pnlDialogHelp = pgBrowser.docker.findPanels('pnl_online_help')[0];
if (pnlDialogHelp == null) {
pnlProperties = pgBrowser.docker.findPanels('properties')[0];
var pnlProperties = pgBrowser.docker.findPanels('properties')[0];
pgBrowser.docker.addPanel('pnl_online_help', wcDocker.DOCK.STACKED, pnlProperties);
pnlDialogHelp = pgBrowser.docker.findPanels('pnl_online_help')[0];
}
// Update the panel
iframe = $(pnlDialogHelp).data('embeddedFrame');
var iframe = $(pnlDialogHelp).data('embeddedFrame');
pnlDialogHelp.focus();
iframe.openURL(this.options.wizard_help);

View File

@ -1,549 +0,0 @@
@charset "utf-8";
/*
* aciTree jQuery Plugin
* http://acoderinsights.ro
*
*/
.aciTree {
outline: none;
}
/* the big loader */
.aciTree.aciTreeLoad {
background:url(../image/load-root.gif) center center no-repeat;
}
.aciTree .aciTreeUl {
list-style:none;
margin:0;
padding:0;
}
.aciTree .aciTreeLi {
display:block;
clear:both;
white-space:nowrap;
}
.aciTree .aciTreeLine:focus {
outline:none;
}
.aciTree .aciTreeLi.aciTreeHidden {
display:none;
}
/* the branch line */
.aciTree .aciTreeBranch {
padding-left:20px; /* branch indent */
background:url(../image/tree-branch.png) left 1px repeat-y;
}
.aciTree[dir=rtl] .aciTreeBranch {
padding-left:0;
padding-right:20px; /* branch indent */
background:url(../image/tree-branch.png) right 1px repeat-y;
}
/* if the parent is the last child on his level (this is level based; added for #8 levels, if you need more ... add them as needed) */
.aciTree .aciTreeLi.aciTreeLevel0.aciTreeLast .aciTreeBranch.aciTreeLevel0,
.aciTree .aciTreeLi.aciTreeLevel1.aciTreeLast .aciTreeBranch.aciTreeLevel1,
.aciTree .aciTreeLi.aciTreeLevel2.aciTreeLast .aciTreeBranch.aciTreeLevel2,
.aciTree .aciTreeLi.aciTreeLevel3.aciTreeLast .aciTreeBranch.aciTreeLevel3,
.aciTree .aciTreeLi.aciTreeLevel4.aciTreeLast .aciTreeBranch.aciTreeLevel4,
.aciTree .aciTreeLi.aciTreeLevel5.aciTreeLast .aciTreeBranch.aciTreeLevel5,
.aciTree .aciTreeLi.aciTreeLevel6.aciTreeLast .aciTreeBranch.aciTreeLevel6,
.aciTree .aciTreeLi.aciTreeLevel7.aciTreeLast .aciTreeBranch.aciTreeLevel7,
.aciTree .aciTreeLi.aciTreeLevel8.aciTreeLast .aciTreeBranch.aciTreeLevel8,
.aciTree.aciTreeNoBranches .aciTreeBranch {
background:none;
}
/* the branch line behind the button (for the siblings) */
.aciTree .aciTreeEntry {
overflow:hidden;
background:url(../image/tree-branch.png) left 1px repeat-y;
}
.aciTree[dir=rtl] .aciTreeEntry {
background:url(../image/tree-branch.png) right 1px repeat-y;
}
.aciTree .aciTreeLi.aciTreeLast>.aciTreeLine .aciTreeEntry,
.aciTree.aciTreeNoBranches .aciTreeEntry {
background:none;
}
.aciTree.aciTreeBig .aciTreeEntry {
padding:0 0 2px 0;
}
.aciTree .aciTreeButton, .aciTree .aciTreePush, .aciTree .aciTreeItem, .aciTree .aciTreeIcon, .aciTree .aciTreeText, .aciTree .aciTreeColumn {
display:inline-block;
height:20px;
line-height:20px;
font-family:Verdana, Geneva, sans-serif;
font-size:11px;
color:#000;
vertical-align:top;
}
.aciTree.aciTreeBig .aciTreeText, .aciTree.aciTreeBig .aciTreeColumn {
font-size:12px;
}
.aciTree .aciTreeDisabled>.aciTreeLine .aciTreeText, .aciTree .aciTreeDisabled>.aciTreeLine .aciTreeColumn {
color:#888;
}
.aciTree .aciTreeItem {
padding:0 2px 0 2px;
border:1px solid transparent;
height:auto;
white-space:normal;
cursor:pointer;
/* margin-right need to be set to icon width [.aciTree .aciTreeIcon = 20] +
item padding [.aciTree .aciTreeItem = 4] (+ the width of all columns, if any) */
margin-right:24px;
}
.aciTree[dir=rtl] .aciTreeItem{
margin-right:0;
/* margin-left need to be set to icon width [.aciTree .aciTreeIcon = 20] +
item padding [.aciTree .aciTreeItem = 4] (+ the width of all columns, if any) */
margin-left:24px;
}
.aciTree .aciTreeText {
display:inline;
height:auto;
}
.aciTree .aciTreeColumn {
float:right;
height:auto;
white-space:normal;
cursor:default;
}
.aciTree[dir=rtl] .aciTreeColumn {
float:left;
}
/* columns width/style (left to right, if any) */
.aciTree .aciTreeColumn0 {
width:80px;
}
.aciTree .aciTreeColumn1 {
width:60px;
}
/* item selection */
.aciTree .aciTreeLine.aciTreeHover .aciTreeItem {
background-color:#EFF5FD;
border:1px dashed #D9D9D9;
-webkit-border-radius:3px;
-moz-border-radius:3px;
border-radius:3px;
}
.aciTree .aciTreeFocus>.aciTreeLine .aciTreeItem {
/* not selected but with focus */
border:1px solid #D9D9D9;
-webkit-border-radius:3px;
-moz-border-radius:3px;
border-radius:3px;
}
.aciTree .aciTreeSelected>.aciTreeLine .aciTreeItem {
background-color:#E8E8E8;
border:1px dashed #D9D9D9;
-webkit-border-radius:3px;
-moz-border-radius:3px;
border-radius:3px;
}
.aciTree.aciTreeFocus .aciTreeSelected>.aciTreeLine .aciTreeItem {
background-color:#d0e5fe;
}
.aciTree.aciTreeFocus .aciTreeFocus>.aciTreeLine .aciTreeItem {
/* not selected but with focus */
border:1px solid #84acdd;
}
.aciTree.aciTreeFocus .aciTreeSelected.aciTreeFocus>.aciTreeLine .aciTreeItem {
border:1px dashed #84acdd;
}
/* full row selection */
.aciTree.aciTreeFullRow>.aciTreeUl {
margin:2px;
}
.aciTree.aciTreeFullRow .aciTreeLine {
margin:-2px;
border:1px solid transparent;
}
.aciTree.aciTreeFullRow .aciTreeLine.aciTreeHover .aciTreeItem {
background:none;
border:1px solid transparent;
}
.aciTree.aciTreeFullRow .aciTreeFocus>.aciTreeLine {
/* not selected but with focus */
border:1px solid #D9D9D9;
}
.aciTree.aciTreeFullRow .aciTreeSelected>.aciTreeLine .aciTreeItem,
.aciTree.aciTreeFullRow .aciTreeFocus>.aciTreeLine .aciTreeItem {
background:none;
border:1px solid transparent;
}
.aciTree.aciTreeFullRow.aciTreeFocus .aciTreeSelected>.aciTreeLine .aciTreeItem {
background:none;
border:1px solid transparent;
}
.aciTree.aciTreeFullRow .aciTreeLine.aciTreeHover {
background: #e3edf9;
background: -moz-linear-gradient(top, #e3edf9 0%, #9cb7d8 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#e3edf9), color-stop(100%,#9cb7d8));
background: -webkit-linear-gradient(top, #e3edf9 0%,#9cb7d8 100%);
background: -o-linear-gradient(top, #e3edf9 0%,#9cb7d8 100%);
background: -ms-linear-gradient(top, #e3edf9 0%,#9cb7d8 100%);
background: linear-gradient(to bottom, #e3edf9 0%,#9cb7d8 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#e3edf9', endColorstr='#9cb7d8',GradientType=0 );
}
.aciTree.aciTreeFullRow .aciTreeSelected>.aciTreeLine {
background: #f4f4f4;
background: -moz-linear-gradient(top, #f4f4f4 0%, #c6c6c6 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f4f4f4), color-stop(100%,#c6c6c6));
background: -webkit-linear-gradient(top, #f4f4f4 0%,#c6c6c6 100%);
background: -o-linear-gradient(top, #f4f4f4 0%,#c6c6c6 100%);
background: -ms-linear-gradient(top, #f4f4f4 0%,#c6c6c6 100%);
background: linear-gradient(to bottom, #f4f4f4 0%,#c6c6c6 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f4f4f4', endColorstr='#c6c6c6',GradientType=0 );
}
.aciTree.aciTreeFullRow.aciTreeFocus .aciTreeFocus>.aciTreeLine {
/* not selected but with focus */
border:1px solid #84acdd;
}
.aciTree.aciTreeFullRow.aciTreeFocus .aciTreeSelected>.aciTreeLine {
border:1px solid transparent;
background: #d0e5fe;
background: -moz-linear-gradient(top, #d0e5fe 0%, #84acdd 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#d0e5fe), color-stop(100%,#84acdd));
background: -webkit-linear-gradient(top, #d0e5fe 0%,#84acdd 100%);
background: -o-linear-gradient(top, #d0e5fe 0%,#84acdd 100%);
background: -ms-linear-gradient(top, #d0e5fe 0%,#84acdd 100%);
background: linear-gradient(to bottom, #d0e5fe 0%,#84acdd 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#d0e5fe', endColorstr='#84acdd',GradientType=0 );
}
.aciTree.aciTreeFullRow.aciTreeFocus .aciTreeSelected>.aciTreeLine.aciTreeHover,
.aciTree.aciTreeFullRow .aciTreeSelected>.aciTreeLine.aciTreeHover {
background: #c3dbf7;
background: -moz-linear-gradient(top, #c3dbf7 0%, #84a9d6 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#c3dbf7), color-stop(100%,#84a9d6));
background: -webkit-linear-gradient(top, #c3dbf7 0%,#84a9d6 100%);
background: -o-linear-gradient(top, #c3dbf7 0%,#84a9d6 100%);
background: -ms-linear-gradient(top, #c3dbf7 0%,#84a9d6 100%);
background: linear-gradient(to bottom, #c3dbf7 0%,#84a9d6 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#c3dbf7', endColorstr='#84a9d6',GradientType=0 );
}
/* checkbox/radio tree */
.aciTree .aciTreeCheckbox label, .aciTree .aciTreeRadio label {
cursor:pointer;
}
.aciTree .aciTreeCheck {
width:20px;
height:20px;
display:inline-block;
margin:0 2px 0 2px;
padding:0;
vertical-align:text-bottom;
background:url(../image/tree-check-small.png) 0 0 no-repeat;
}
.aciTree.aciTreeBig .aciTreeCheck {
background:url(../image/tree-check-big.png) 0 0 no-repeat;
}
.aciTree[dir=rtl] .aciTreeCheck {
background:url(../image/tree-check-small-rtl.png) 0 0 no-repeat;
}
.aciTree.aciTreeBig[dir=rtl] .aciTreeCheck {
background:url(../image/tree-check-big-rtl.png) 0 0 no-repeat;
}
.aciTree .aciTreeCheckbox>.aciTreeLine .aciTreeCheck { background-position:-5px -65px; }
.aciTree .aciTreeCheckbox.aciTreeChecked>.aciTreeLine .aciTreeCheck { background-position:-5px -5px; }
.aciTree .aciTreeCheckbox.aciTreeChecked.aciTreeTristate>.aciTreeLine .aciTreeCheck { background-position:-5px -35px; }
.aciTree .aciTreeCheckbox>.aciTreeLine.aciTreeHover .aciTreeCheck { background-position:-35px -65px; }
.aciTree .aciTreeCheckbox.aciTreeChecked>.aciTreeLine.aciTreeHover .aciTreeCheck { background-position:-35px -5px; }
.aciTree .aciTreeCheckbox.aciTreeChecked.aciTreeTristate>.aciTreeLine.aciTreeHover .aciTreeCheck { background-position:-35px -35px; }
.aciTree .aciTreeCheckbox.aciTreeDisabled>.aciTreeLine .aciTreeCheck { background-position:-65px -65px; }
.aciTree .aciTreeCheckbox.aciTreeDisabled.aciTreeChecked>.aciTreeLine .aciTreeCheck { background-position:-65px -5px; }
.aciTree .aciTreeCheckbox.aciTreeDisabled.aciTreeChecked.aciTreeTristate>.aciTreeLine .aciTreeCheck { background-position:-65px -35px; }
.aciTree .aciTreeRadio>.aciTreeLine .aciTreeCheck { background-position:-95px -65px; }
.aciTree .aciTreeRadio.aciTreeChecked>.aciTreeLine .aciTreeCheck { background-position:-95px -5px; }
.aciTree .aciTreeRadio.aciTreeChecked.aciTreeTristate>.aciTreeLine .aciTreeCheck { background-position:-95px -35px; }
.aciTree .aciTreeRadio>.aciTreeLine.aciTreeHover .aciTreeCheck { background-position:-125px -65px; }
.aciTree .aciTreeRadio.aciTreeChecked>.aciTreeLine.aciTreeHover .aciTreeCheck { background-position:-125px -5px; }
.aciTree .aciTreeRadio.aciTreeChecked.aciTreeTristate>.aciTreeLine.aciTreeHover .aciTreeCheck { background-position:-125px -35px; }
.aciTree .aciTreeRadio.aciTreeDisabled>.aciTreeLine .aciTreeCheck { background-position:-155px -65px; }
.aciTree .aciTreeRadio.aciTreeDisabled.aciTreeChecked>.aciTreeLine .aciTreeCheck { background-position:-155px -5px; }
.aciTree .aciTreeRadio.aciTreeDisabled.aciTreeChecked.aciTreeTristate>.aciTreeLine .aciTreeCheck { background-position:-155px -35px; }
/* inplace editable */
.aciTree .aciTreeEdited input[type=text] {
outline: none;
border:1px solid #000;
padding:0;
margin:0;
line-height:18px;
height:18px;
display:inline-block;
font-family:Verdana, Geneva, sans-serif;
font-size:11px;
color:#000;
vertical-align:top;
}
.aciTree.aciTreeBig .aciTreeEdited input[type=text] {
font-size:12px;
}
/* sortable items */
.aciTree .aciTreeChild {
height:0;
line-height:0;
}
.aciTree .aciTreePlaceholder {
height:0;
line-height:0;
overflow:visible;
position:relative;
}
.aciTree .aciTreePlaceholder div {
position:absolute;
left:0;
width:16px;
height:16px;
margin-left:20px;
background:#fff url(../image/drag-drop.png) -7px -37px no-repeat;
border:1px solid #999;
}
.aciTree[dir=rtl] .aciTreePlaceholder div {
background:#fff url(../image/drag-drop-rtl.png) -7px -37px no-repeat;
}
.aciTree .aciTreeChild .aciTreePlaceholder div {
top:-20px;
left:-20px;
}
.aciTree.aciTreeBig .aciTreeChild .aciTreePlaceholder div {
top:-22px;
}
.aciTree .aciTreePlaceholder.aciTreeBefore div {
top:2px;
background-position:-7px -7px !important;
}
.aciTree .aciTreePlaceholder.aciTreeAfter div {
top:-20px;
background-position:-7px -67px !important;
}
.aciTree.aciTreeBig .aciTreePlaceholder.aciTreeAfter div {
top:-22px;
}
.aciTree.aciTreeDragDrop .aciTreeItem, .aciTree.aciTreeDragDrop .aciTreeColumn,
.aciTree.aciTreeDragDrop .aciTreeCheckbox label, .aciTree.aciTreeDragDrop .aciTreeRadio label {
cursor:inherit !important;
}
/* this is level based; added for #8 levels, if you need more ... add them as needed */
.aciTree .aciTreeLi.aciTreeLevel0 .aciTreePlaceholder div { margin-left:40px; }
.aciTree .aciTreeLi.aciTreeLevel1 .aciTreePlaceholder div { margin-left:60px; }
.aciTree .aciTreeLi.aciTreeLevel2 .aciTreePlaceholder div { margin-left:80px; }
.aciTree .aciTreeLi.aciTreeLevel3 .aciTreePlaceholder div { margin-left:100px; }
.aciTree .aciTreeLi.aciTreeLevel4 .aciTreePlaceholder div { margin-left:120px; }
.aciTree .aciTreeLi.aciTreeLevel5 .aciTreePlaceholder div { margin-left:140px; }
.aciTree .aciTreeLi.aciTreeLevel6 .aciTreePlaceholder div { margin-left:160px; }
.aciTree .aciTreeLi.aciTreeLevel7 .aciTreePlaceholder div { margin-left:180px; }
.aciTree .aciTreeLi.aciTreeLevel8 .aciTreePlaceholder div { margin-left:200px; }
.aciTree[dir=rtl] .aciTreePlaceholder div {
left:auto;
right:0;
margin-left:0;
margin-right:20px;
}
.aciTree .aciTreeChild .aciTreePlaceholder div {
right:-20px;
}
/* this is level based; added for #8 levels, if you need more ... add them as needed */
.aciTree[dir=rtl] .aciTreeLi.aciTreeLevel0 .aciTreePlaceholder div { margin-right:40px; }
.aciTree[dir=rtl] .aciTreeLi.aciTreeLevel1 .aciTreePlaceholder div { margin-right:60px; }
.aciTree[dir=rtl] .aciTreeLi.aciTreeLevel2 .aciTreePlaceholder div { margin-right:80px; }
.aciTree[dir=rtl] .aciTreeLi.aciTreeLevel3 .aciTreePlaceholder div { margin-right:100px; }
.aciTree[dir=rtl] .aciTreeLi.aciTreeLevel4 .aciTreePlaceholder div { margin-right:120px; }
.aciTree[dir=rtl] .aciTreeLi.aciTreeLevel5 .aciTreePlaceholder div { margin-right:140px; }
.aciTree[dir=rtl] .aciTreeLi.aciTreeLevel6 .aciTreePlaceholder div { margin-right:160px; }
.aciTree[dir=rtl] .aciTreeLi.aciTreeLevel7 .aciTreePlaceholder div { margin-right:180px; }
.aciTree[dir=rtl] .aciTreeLi.aciTreeLevel8 .aciTreePlaceholder div { margin-right:200px; }
.aciTreeHelper {
position:absolute;
max-width:300px;
color:#000;
background-color:#d0e5fe;
border:1px dashed #84acdd;
-webkit-border-radius:3px;
-moz-border-radius:3px;
border-radius:3px;
padding:4px;
margin:20px 0 0 20px;
}
/* default - item in the middle (comment the hover part to keep the same button image) */
.aciTree .aciTreeButton, .aciTree .aciTreePush {
width:18px;
background:url(../image/tree-small.png) -7px -35px no-repeat;
}
.aciTree.aciTreeBig .aciTreeButton, .aciTree.aciTreeBig .aciTreePush {
background:url(../image/tree-big.png) -7px -35px no-repeat;
}
.aciTree[dir=rtl] .aciTreeButton, .aciTree[dir=rtl] .aciTreePush {
background:url(../image/tree-small-rtl.png) -7px -35px no-repeat;
}
.aciTree.aciTreeBig[dir=rtl] .aciTreeButton, .aciTree.aciTreeBig[dir=rtl] .aciTreePush {
background:url(../image/tree-big-rtl.png) -7px -35px no-repeat;
}
.aciTree.aciTreeArrow .aciTreeButton, .aciTree.aciTreeArrow .aciTreePush {
background:url(../image/tree-arrow-small.png) -7px -35px no-repeat;
}
.aciTree.aciTreeBig.aciTreeArrow .aciTreeButton, .aciTree.aciTreeBig.aciTreeArrow .aciTreePush {
background:url(../image/tree-arrow-big.png) -7px -35px no-repeat;
}
.aciTree.aciTreeArrow[dir=rtl] .aciTreeButton, .aciTree.aciTreeArrow[dir=rtl] .aciTreePush {
background:url(../image/tree-arrow-small-rtl.png) -7px -35px no-repeat;
}
.aciTree.aciTreeBig.aciTreeArrow[dir=rtl] .aciTreeButton, .aciTree.aciTreeBig.aciTreeArrow[dir=rtl] .aciTreePush {
background:url(../image/tree-arrow-big-rtl.png) -7px -35px no-repeat;
}
.aciTree.aciTreeNoBranches .aciTreeButton,
.aciTree .aciTreeLeaf>.aciTreeLine .aciTreePush { background:none !important; }
.aciTree .aciTreeInodeMaybe>.aciTreeLine .aciTreePush { background-position:-67px -5px !important; }
.aciTree .aciTreeInodeMaybe>.aciTreeLine .aciTreePush.aciTreeHover { background-position:-67px -35px !important; }
.aciTree .aciTreeInode>.aciTreeLine .aciTreePush { background-position:-97px -5px !important; }
.aciTree .aciTreeInode>.aciTreeLine .aciTreePush.aciTreeHover { background-position:-97px -35px !important; }
.aciTree .aciTreeOpen>.aciTreeLine .aciTreePush { background-position:-127px -5px !important; }
.aciTree .aciTreeOpen>.aciTreeLine .aciTreePush.aciTreeHover { background-position:-127px -35px !important; }
/* if it's the last item in list */
.aciTree .aciTreeLi.aciTreeLast>.aciTreeLine .aciTreeButton { background-position:-37px -5px !important; }
/* the item loader */
.aciTree .aciTreePush>span {
display:none;
position:absolute;
width:18px;
height:18px;
left:0;
top:2px;
background:url(../image/load-node.gif) 0 0 no-repeat;
}
.aciTree .aciTreeLoad>.aciTreeLine .aciTreePush {
position:relative;
/* uncomment next line to hide the button while loading */
/*background:none !important;*/
}
.aciTree .aciTreeLoad>.aciTreeLine .aciTreePush>span {
display:inline-block;
}
/* tree item icon */
.aciTree .aciTreeIcon {
width:20px;
background:url(../image/tree-small.png) 0 0 no-repeat;
}
.aciTree.aciTreeBig .aciTreeIcon {
background:url(../image/tree-big.png) 0 0 no-repeat;
}
.aciTree[dir=rtl] .aciTreeIcon {
width:16px;
margin-left:4px;
background:url(../image/tree-small-rtl.png) 0 0 no-repeat;
}
.aciTree.aciTreeBig[dir=rtl] .aciTreeIcon {
background:url(../image/tree-big-rtl.png) 0 0 no-repeat;
}
.aciTree.aciTreeArrow .aciTreeIcon { background:url(../image/tree-arrow-small.png) 0 0 no-repeat; }
.aciTree.aciTreeBig.aciTreeArrow .aciTreeIcon { background:url(../image/tree-arrow-big.png) 0 0 no-repeat; }
.aciTree.aciTreeArrow[dir=rtl] .aciTreeIcon { background:url(../image/tree-arrow-small-rtl.png) 0 0 no-repeat; }
.aciTree.aciTreeBig.aciTreeArrow[dir=rtl] .aciTreeIcon { background:url(../image/tree-arrow-big-rtl.png) 0 0 no-repeat; }
/* demo file/folder icon class */
.aciTree .aciTreeIcon.folder {
background-position:-157px -5px !important;
}
.aciTree .aciTreeLine.aciTreeHover .aciTreeIcon.folder {
/* comment next line to keep the same icon on hover */
background-position:-157px -35px !important;
}
.aciTree .aciTreeIcon.file {
background-position:-187px -5px !important;
}
.aciTree .aciTreeLine.aciTreeHover .aciTreeIcon.file {
/* comment next line to keep the same icon on hover */
background-position:-187px -35px !important;
}
/* demo row colors */
.aciTree.aciTreeColors .aciTreeOdd>.aciTreeLine {
/* odd rows */
background-color:#FFFFC4;
}
.aciTree.aciTreeColors .aciTreeEven>.aciTreeLine {
/* even rows */
background-color:#CAFFCA;
}
.aciTree.aciTreeColors .aciTreeFirst>.aciTreeLine {
/* first item on each level */
/*background-color:#B0DFFF;*/
}
.aciTree.aciTreeColors .aciTreeLast>.aciTreeLine {
/* last item on each level */
/*background-color:#FFCEFF;*/
}
/* uncomment below to keep the item in one line and scroll the tree horizontally when needed */
/*
.aciTree .aciTreeEntry {
overflow:visible;
}
.aciTree .aciTreeItem {
white-space:nowrap;
margin-right:12px;
}
*/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 908 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -1,15 +0,0 @@
/*
* aciFragment jQuery Plugin v1.1.0
* http://acoderinsights.ro
*
* Copyright (c) 2013 Dragos Ursu
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Require jQuery Library >= v1.7.1 http://jquery.com
* + aciPlugin >= v1.1.1 https://github.com/dragosu/jquery-aciPlugin
*
* Date: Apr Fri 26 18:00 2013 +0200
*/
(function(e,t,n){var r={anchor:"anchor",poolDelay:250,scroll:{duration:"medium",easing:"linear"}};var i={__extend:function(){e.extend(this._instance,{lastHash:null,lastParsed:null,parsed:{},anchor:true,timeOut:null,"native":"onhashchange"in t&&(t.document.documentMode===n||t.document.documentMode>7)})},init:function(){var n=this;if(this.wasInit()){return}if(this._instance.native){e(t).bind("hashchange"+this._instance.nameSpace,function(){n._trigger()})}else{this._change()}this._instance.anchor=true;this._trigger();this._super()},_trigger:function(){this._instance.jQuery.trigger("acifragment",[this,this._instance.anchor]);this._instance.anchor=false},_change:function(){var e=this;var n=t.location.hash;if(n!=this._instance.lastHash){this._trigger();this._instance.lastHash=n}this._instance.timeOut=t.setTimeout(function(){e._change()},this._instance.options.poolDelay)},scroll:function(){var n=this.get(this._instance.options.anchor);if(n&&n.length){var r=e("#"+n+":first");if(!r.length){r=e('[name="'+n+'"]:first')}if(r.length){var i=r.get(0).getBoundingClientRect();var s=e(t).scrollLeft()+i.left,o=e(t).scrollTop()+i.top;if(this._instance.options.scroll){e("html,body").stop(true).animate({scrollLeft:s,scrollTop:o},this._instance.options.scroll)}else{t.scrollTo(s,o)}}}},click:function(e,t){var n=e.attr("href");if(n){var r=this.parse(n);this.update(r);if(t&&this.hasAnchor(r)){this.scroll()}}},parse:function(e){var n=e.indexOf("#"),r={};if(n!=-1){e=e.substr(n+1);var i=e.split("&"),s;for(var o in i){s=i[o].split("=");if(s.length>1){r[t.decodeURIComponent(s[0])]=t.decodeURIComponent(s[1])}else{r[this._instance.options.anchor]=t.decodeURIComponent(s[0])}}}return r},hasAnchor:function(e){return e[this._instance.options.anchor]&&e[this._instance.options.anchor].length>0},setAnchor:function(e){this.set(this._instance.options.anchor,e)},getAnchor:function(e){return this.get(this._instance.options.anchor,e)},parseHash:function(){var e=t.location.hash;if(e==this._instance.lastParsed){return this._instance.parsed}var n=this.parse(e);this._instance.parsed=n;this._instance.lastParsed=e;return n},get:function(e,r){var i=this.parseHash();if(i[e]!==null&&i[e]!==n&&t.String(i[e]).length){return i[e]}else{return r}},replace:function(e,r){var i=[];for(var s in e){if(e[s]!==null&&e[s]!==n&&t.String(e[s]).length){i[i.length]=t.encodeURIComponent(s)+"="+t.encodeURIComponent(e[s])}}if(!r&&this.hasAnchor(e)){this._instance.anchor=true}var o=t.location.hash;if(i.length){t.location.hash="#"+i.join("&")}else if(t.history&&t.history.pushState){t.history.pushState("",t.document.title,t.location.pathname+t.location.search)}else{t.location.hash=""}if(t.location.hash==o){this._trigger()}},update:function(e){var t=this.parseHash();for(var n in e){t[n]=e[n]}if(this.hasAnchor(e)){this._instance.anchor=true}this.replace(t,true)},set:function(e,t){var n=this.parseHash();n[e]=t;if(e==this._instance.options.anchor){this._instance.anchor=true}this.replace(n,true)},destroy:function(){if(!this.wasInit()){return}if(this._instance.native){e(t).unbind(this._instance.nameSpace)}t.clearTimeout(this._instance.timeOut);this._super()}};aciPluginClass.plugins.aciFragment=aciPluginClass.aciPluginUi.extend(i,"aciFragment");aciPluginClass.publish("aciFragment",r)})(jQuery,this);

View File

@ -1,12 +0,0 @@
/*
* aciPlugin little jQuery plugin helper v1.5.1
* http://acoderinsights.ro
*
* Copyright (c) 2013 Dragos Ursu
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Require jQuery Library >= v1.2.3 http://jquery.com
*/
(function(d,c,e){if(typeof aciPluginClass!=="undefined"){return}var a;this.aciPluginClass=function(){};aciPluginClass.extend=function(g,j){i.extend=arguments.callee;function i(){if(a){this._instance={};return this.__construct.apply(this,arguments)}}a=false;i.prototype=new this();a=true;var h=this.prototype;for(var f in g){i.prototype[f]=((typeof g[f]=="function")&&(f!="proxy"))?(function(k){return function(){var p=this._parent;this._parent=h;var n=this._super;this._super=h[k];var o=this._private;if(this._instance&&j){var m=this._instance._private;if(m[j]===e){m[j]={nameSpace:"."+j}}this._private=m[j]}var l=g[k].apply(this,arguments);this._parent=p;this._super=n;this._private=o;return l}})(f):g[f]}return i};var b=0;aciPluginClass.aciPluginUi=aciPluginClass.extend({__construct:function(k,l,i,h,j){var f="."+k;var g=l.data(f);if(g){this._instance=g._instance;return g.__request(i,h,j)}l.data(f,this);d.extend(true,this._instance,{_private:{},nameSpace:f,jQuery:l,options:d.extend(true,{},d.fn[k].defaults,(typeof i=="object")?i:{}),index:b++,wasInit:false});this.__extend();return this.__request(i,h,j)},__extend:function(){},__request:function(g,f,h){if((g===e)||(typeof g=="object")){if(this._instance.options.autoInit){this.init()}}else{if(typeof g=="string"){switch(g){case"init":this.init();break;case"api":return{object:this};case"options":if(f===e){return{object:this.options()}}else{if(typeof f=="string"){return{object:this.options(f)}}else{this.options(f)}}break;case"option":this.option(f,h);break;case"destroy":this.destroy();break}}}return this._instance.jQuery},proxy:function(j,h){var m=c.Array.prototype.slice;var f=m.call(arguments,2);var i=this,g=i._parent,l=i._super,k=i._private;return function(){i._parent=g;i._super=l;i._private=k;return j.apply(i,h?f.concat([this],m.call(arguments)):f.concat(m.call(arguments)))}},init:function(){if(!this._instance.wasInit){this._instance.wasInit=true;return true}return false},wasInit:function(){return this._instance.wasInit},__parent:function(h,f,l){var m=f.split(".");if(m.length>1){var j=h,k;for(var g in m){k=j;j=j[m[g]]}l.name=m[g];return k}l.name=f;return h},options:function(f){if(f){var i={name:null};var h;if(typeof f=="string"){h=this.__parent(this._instance.options,f,i);return h[i.name]}else{for(var g in f){h=this.__parent(this._instance.options,g,i);h[i.name]=f[g]}}}else{return this._instance.options}},option:function(g,i){var h={name:null};var f=this.__parent(this._instance.options,g,h);f[h.name]=i},destroy:function(){if(this._instance.wasInit){this._instance.wasInit=false;this._instance.jQuery.removeData(this._instance.nameSpace);return true}return false}});aciPluginClass.plugins={};aciPluginClass.publish=function(f,g){d.fn[f]=function(j,m,n){var h=null;for(var l=0,k=this.length;l<k;l++){h=new aciPluginClass.plugins[f](f,d(this[l]),j,m,n);if(!(h instanceof d)){return h.object}}return this};d.fn[f].defaults=d.extend(true,{autoInit:true},(typeof g=="object")?g:{})};aciPluginClass.defaults=function(f,g){d.extend(true,d.fn[f].defaults,(typeof g=="object")?g:{})}})(jQuery,this);

File diff suppressed because one or more lines are too long

View File

@ -1,483 +0,0 @@
/*
* aciTree jQuery Plugin v4.5.0-rc.7
* http://acoderinsights.ro
*
* Copyright (c) 2014 Dragos Ursu
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Require jQuery Library >= v1.9.0 http://jquery.com
* + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin
*/
/*
* This extension adds checkbox support to aciTree,
* should be used with the selectable extension.
*
* The are a few extra properties for the item data:
*
* {
* ...
* checkbox: true, // TRUE (default) means the item will have a checkbox (can be omitted if the `radio` extension is not used)
* checked: false, // if should be checked or not
* ...
* }
*
*/
(function($, window, undefined) {
// extra default options
var options = {
checkbox: false, // if TRUE then each item will have a checkbox
checkboxChain: true,
// if TRUE the selection will propagate to the parents/children
// if -1 the selection will propagate only to parents
// if +1 the selection will propagate only to children
// if FALSE the selection will not propagate in any way
checkboxBreak: true, // if TRUE then a missing checkbox will break the chaining
checkboxClick: false // if TRUE then a click will trigger a state change only when made over the checkbox itself
};
// aciTree checkbox extension
var aciTree_checkbox = {
// init checkbox
_checkboxInit: function() {
this._instance.jQuery.bind('acitree' + this._private.nameSpace, function(event, api, item, eventName, options) {
switch (eventName) {
case 'loaded':
// check/update on item load
api._checkboxLoad(item);
break;
}
}).bind('keydown' + this._private.nameSpace, this.proxy(function(e) {
switch (e.which) {
case 32: // space
// support `selectable` extension
if (this.extSelectable && this.extSelectable() && !e.ctrlKey) {
var item = this.focused();
if (this.hasCheckbox(item) && this.isEnabled(item)) {
if (this.isChecked(item)) {
this.uncheck(item);
} else {
this.check(item);
}
e.stopImmediatePropagation();
// prevent page scroll
e.preventDefault();
}
}
break;
}
})).on('click' + this._private.nameSpace, '.aciTreeItem', this.proxy(function(e) {
if (!this._instance.options.checkboxClick || $(e.target).is('.aciTreeCheck')) {
var item = this.itemFrom(e.target);
if (this.hasCheckbox(item) && this.isEnabled(item) && (!this.extSelectable || !this.extSelectable() || (!e.ctrlKey && !e.shiftKey))) {
// change state on click
if (this.isChecked(item)) {
this.uncheck(item);
} else {
this.check(item);
}
e.preventDefault();
}
}
}));
},
// override `_initHook`
_initHook: function() {
if (this.extCheckbox()) {
this._checkboxInit();
}
// call the parent
this._super();
},
// override `_itemHook`
_itemHook: function(parent, item, itemData, level) {
if (this.extCheckbox()) {
// support `radio` extension
var radio = this.extRadio && this.hasRadio(item);
if (!radio && (itemData.checkbox || ((itemData.checkbox === undefined) && (!this.extRadio || !this.extRadio())))) {
this._checkboxDOM.add(item, itemData);
}
}
// call the parent
this._super(parent, item, itemData, level);
},
// low level DOM functions
_checkboxDOM: {
// add item checkbox
add: function(item, itemData) {
domApi.addClass(item[0], itemData.checked ? ['aciTreeCheckbox', 'aciTreeChecked'] : 'aciTreeCheckbox');
var text = domApi.childrenByClass(item[0].firstChild, 'aciTreeText');
var parent = text.parentNode;
var label = window.document.createElement('LABEL');
var check = window.document.createElement('SPAN');
check.className = 'aciTreeCheck';
label.appendChild(check);
label.appendChild(text);
parent.appendChild(label);
item[0].firstChild.setAttribute('aria-checked', !!itemData.checked);
},
// remove item checkbox
remove: function(item) {
domApi.removeClass(item[0], ['aciTreeCheckbox', 'aciTreeChecked', 'aciTreeTristate']);
var text = domApi.childrenByClass(item[0].firstChild, 'aciTreeText');
var label = text.parentNode;
var parent = label.parentNode;
parent.replaceChild(text, label)
item[0].firstChild.removeAttribute('aria-checked');
},
// (un)check items
check: function(items, state) {
domApi.toggleListClass(items.toArray(), 'aciTreeChecked', state, function(node) {
node.firstChild.setAttribute('aria-checked', state);
});
},
// (un)set tristate items
tristate: function(items, state) {
domApi.toggleListClass(items.toArray(), 'aciTreeTristate', state);
}
},
// update items on load, starting from the loaded node
_checkboxLoad: function(item) {
if (this._instance.options.checkboxChain === false) {
// do not update on load
return;
}
var state = undefined;
if (this.hasCheckbox(item)) {
if (this.isChecked(item)) {
if (!this.checkboxes(this.children(item, false, true), true).length) {
// the item is checked but no children are, check them all
state = true;
}
} else {
// the item is not checked, uncheck all children
state = false;
}
}
this._checkboxUpdate(item, state);
},
// get children list
_checkboxChildren: function(item) {
if (this._instance.options.checkboxBreak) {
var list = [];
var process = this.proxy(function(item) {
var children = this.children(item, false, true);
children.each(this.proxy(function(element) {
var item = $(element);
// break on missing checkbox
if (this.hasCheckbox(item)) {
list.push(element);
process(item);
}
}, true));
});
process(item);
return $(list);
} else {
var children = this.children(item, true, true);
return this.checkboxes(children);
}
},
// update checkbox state
_checkboxUpdate: function(item, state) {
// update children
var checkDown = this.proxy(function(item, count, state) {
var children = this.children(item, false, true);
var total = 0;
var checked = 0;
children.each(this.proxy(function(element) {
var item = $(element);
var subCount = {
total: 0,
checked: 0
};
if (this.hasCheckbox(item)) {
if ((state !== undefined) && (this._instance.options.checkboxChain !== -1)) {
this._checkboxDOM.check(item, state);
}
total++;
if (this.isChecked(item)) {
checked++;
}
checkDown(item, subCount, state);
} else {
if (this._instance.options.checkboxBreak) {
var reCount = {
total: 0,
checked: 0
};
checkDown(item, reCount);
} else {
checkDown(item, subCount, state);
}
}
total += subCount.total;
checked += subCount.checked;
}, true));
if (item) {
this._checkboxDOM.tristate(item, (checked > 0) && (checked != total));
count.total += total;
count.checked += checked;
}
});
var count = {
total: 0,
checked: 0
};
checkDown(item, count, state);
// update parents
var checkUp = this.proxy(function(item, tristate, state) {
var parent = this.parent(item);
if (parent.length) {
if (!tristate) {
var children = this._checkboxChildren(parent);
var checked = this.checkboxes(children, true).length;
var tristate = (checked > 0) && (checked != children.length);
}
if (this.hasCheckbox(parent)) {
if ((state !== undefined) && (this._instance.options.checkboxChain !== 1)) {
this._checkboxDOM.check(parent, tristate ? true : state);
}
this._checkboxDOM.tristate(parent, tristate);
checkUp(parent, tristate, state);
} else {
if (this._instance.options.checkboxBreak) {
checkUp(parent);
} else {
checkUp(parent, tristate, state);
}
}
}
});
checkUp(item, undefined, state);
},
// test if item have a checkbox
hasCheckbox: function(item) {
return item && domApi.hasClass(item[0], 'aciTreeCheckbox');
},
// add checkbox
addCheckbox: function(item, options) {
options = this._options(options, 'checkboxadded', 'addcheckboxfail', 'wascheckbox', item);
if (this.isItem(item)) {
// a way to cancel the operation
if (!this._trigger(item, 'beforeaddcheckbox', options)) {
this._fail(item, options);
return;
}
if (this.hasCheckbox(item)) {
this._notify(item, options);
} else {
var process = function() {
this._checkboxDOM.add(item, {
});
this._success(item, options);
};
// support `radio` extension
if (this.extRadio && this.hasRadio(item)) {
// remove radio first
this.removeRadio(item, this._inner(options, {
success: process,
fail: options.fail
}));
} else {
process.apply(this);
}
}
} else {
this._fail(item, options);
}
},
// remove checkbox
removeCheckbox: function(item, options) {
options = this._options(options, 'checkboxremoved', 'removecheckboxfail', 'notcheckbox', item);
if (this.isItem(item)) {
// a way to cancel the operation
if (!this._trigger(item, 'beforeremovecheckbox', options)) {
this._fail(item, options);
return;
}
if (this.hasCheckbox(item)) {
this._checkboxDOM.remove(item);
this._success(item, options);
} else {
this._notify(item, options);
}
} else {
this._fail(item, options);
}
},
// test if it's checked
isChecked: function(item) {
if (this.hasCheckbox(item)) {
return domApi.hasClass(item[0], 'aciTreeChecked');
}
// support `radio` extension
if (this._super) {
// call the parent
return this._super(item);
}
return false;
},
// check checkbox
check: function(item, options) {
if (this.extCheckbox && this.hasCheckbox(item)) {
options = this._options(options, 'checked', 'checkfail', 'waschecked', item);
// a way to cancel the operation
if (!this._trigger(item, 'beforecheck', options)) {
this._fail(item, options);
return;
}
if (this.isChecked(item)) {
this._notify(item, options);
} else {
this._checkboxDOM.check(item, true);
if (this._instance.options.checkboxChain !== false) {
// chain them
this._checkboxUpdate(item, true);
}
this._success(item, options);
}
} else {
// support `radio` extension
if (this._super) {
// call the parent
this._super(item, options);
} else {
this._trigger(item, 'checkfail', options);
this._fail(item, options);
}
}
},
// uncheck checkbox
uncheck: function(item, options) {
if (this.extCheckbox && this.hasCheckbox(item)) {
options = this._options(options, 'unchecked', 'uncheckfail', 'notchecked', item);
// a way to cancel the operation
if (!this._trigger(item, 'beforeuncheck', options)) {
this._fail(item, options);
return;
}
if (this.isChecked(item)) {
this._checkboxDOM.check(item, false);
if (this._instance.options.checkboxChain !== false) {
// chain them
this._checkboxUpdate(item, false);
}
this._success(item, options);
} else {
this._notify(item, options);
}
} else {
// support `radio` extension
if (this._super) {
// call the parent
this._super(item, options);
} else {
this._trigger(item, 'uncheckfail', options);
this._fail(item, options);
}
}
},
// filter items with checkbox by state (if set)
checkboxes: function(items, state) {
if (state !== undefined) {
return $(domApi.withClass(items.toArray(), state ? ['aciTreeCheckbox', 'aciTreeChecked'] : 'aciTreeCheckbox', state ? null : 'aciTreeChecked'));
}
return $(domApi.withClass(items.toArray(), 'aciTreeCheckbox'));
},
// override `_serialize`
_serialize: function(item, callback) {
var data = this._super(item, callback);
if (data && this.extCheckbox()) {
if (data.hasOwnProperty('checkbox')) {
data.checkbox = this.hasCheckbox(item);
data.checked = this.isChecked(item);
} else if (this.hasCheckbox(item)) {
if (this.extRadio && this.extRadio()) {
data.checkbox = true;
}
data.checked = this.isChecked(item);
}
}
return data;
},
// override `serialize`
serialize: function(item, what, callback) {
if (what == 'checkbox') {
var serialized = '';
var children = this.children(item, true, true);
this.checkboxes(children, true).each(this.proxy(function(element) {
var item = $(element);
if (callback) {
serialized += callback.call(this, item, what, this.getId(item));
} else {
serialized += this._instance.options.serialize.call(this, item, what, this.getId(item));
}
}, true));
return serialized;
}
return this._super(item, what, callback);
},
// test if item is in tristate
isTristate: function(item) {
return item && domApi.hasClass(item[0], 'aciTreeTristate');
},
// filter tristate items
tristate: function(items) {
return $(domApi.withClass(items.toArray(), 'aciTreeTristate'));
},
// test if checkbox is enabled
extCheckbox: function() {
return this._instance.options.checkbox;
},
// override set `option`
option: function(option, value) {
if (this.wasInit() && !this.isLocked()) {
if ((option == 'checkbox') && (value != this.extCheckbox())) {
if (value) {
this._checkboxInit();
} else {
this._checkboxDone();
}
}
}
// call the parent
this._super(option, value);
},
// done checkbox
_checkboxDone: function(destroy) {
this._instance.jQuery.unbind(this._private.nameSpace);
this._instance.jQuery.off(this._private.nameSpace, '.aciTreeItem');
if (!destroy) {
// remove checkboxes
this.checkboxes(this.children(null, true, true)).each(this.proxy(function(element) {
this.removeCheckbox($(element));
}, true));
}
},
// override `_destroyHook`
_destroyHook: function(unloaded) {
if (unloaded) {
this._checkboxDone(true);
}
// call the parent
this._super(unloaded);
}
};
// extend the base aciTree class and add the checkbox stuff
aciPluginClass.plugins.aciTree = aciPluginClass.plugins.aciTree.extend(aciTree_checkbox, 'aciTreeCheckbox');
// add extra default options
aciPluginClass.defaults('aciTree', options);
// for internal access
var domApi = aciPluginClass.plugins.aciTree_dom;
})(jQuery, this);

View File

@ -1,250 +0,0 @@
/*
* aciTree jQuery Plugin v4.5.0-rc.7
* http://acoderinsights.ro
*
* Copyright (c) 2014 Dragos Ursu
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Require jQuery Library >= v1.9.0 http://jquery.com
* + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin
*/
/*
* This extension adds multiple column support to aciTree.
*
* The `columnData` option is used to tell what are the columns and show one or
* more values that will be read from the item data object.
*
* Column data is an array of column definitions, each column definition is
* an object:
*
* {
* width: 100,
* props: 'column_x',
* value: 'default'
* }
*
* where the `width` is the column width in [px], if undefined - then the value
* from the CSS will be used; the `props` is the property name that will be
* read from the item data, if undefined (or the `item-data[column.props]`
* is undefined) then a default value will be set for the column: the `value`.
*
*/
(function($, window, undefined) {
// extra default options
var options = {
columnData: [] // column definitions list
};
// aciTree columns extension
// adds item columns, set width with CSS or using the API
var aciTree_column = {
__extend: function() {
// add extra data
$.extend(this._private, {
propsIndex: { // column index cache
}
});
// call the parent
this._super();
},
// override `_initHook`
_initHook: function() {
if (this._instance.options.columnData.length) {
// check column width
var found = false, data;
for (var i in this._instance.options.columnData) {
data = this._instance.options.columnData[i];
if (data.width !== undefined) {
// update column width
this._updateCss('.aciTree.aciTree' + this._instance.index + ' .aciTreeColumn' + i, 'width:' + data.width + 'px;');
found = true;
}
this._private.propsIndex[data.props] = i;
}
if (found) {
// at least a column width set
this._updateWidth();
}
}
// call the parent
this._super();
},
// read property value from a CSS class name
_getCss: function(className, property, numeric) {
var id = '_getCss_' + window.String(className).replace(/[^a-z0-9_-]/ig, '_');
var test = $('body').find('#' + id);
if (!test.length) {
if (className instanceof Array) {
var style = '', end = '';
for (var i in className) {
style += '<div class="' + className[i] + '">';
end += '</div>';
}
style += end;
} else {
var style = '<div class="' + className + '"></div>';
}
$('body').append('<div id="' + id + '" style="position:relative;display:inline-block;width:0px;height:0px;line-height:0px;overflow:hidden">' + style + '</div>');
test = $('body').find('#' + id);
}
var value = test.find('*:last').css(property);
if (numeric) {
value = parseInt(value);
if (isNaN(value)) {
value = null;
}
}
return value;
},
// dynamically change a CSS class definition
_updateCss: function(className, definition) {
var id = '_updateCss_' + window.String(className).replace('>', '_gt_').replace(/[^a-z0-9_-]/ig, '_');
var style = '<style id="' + id + '" type="text/css">' + className + '{' + definition + '}</style>';
var test = $('body').find('#' + id);
if (test.length) {
test.replaceWith(style);
} else {
$('body').prepend(style);
}
},
// get column width
// `index` is the #0 based column index
getWidth: function(index) {
if ((index >= 0) && (index < this.columns())) {
return this._getCss(['aciTree aciTree' + this._instance.index, 'aciTreeColumn' + index], 'width', true);
}
return null;
},
// set column width
// `index` is the #0 based column index
setWidth: function(index, width) {
if ((index >= 0) && (index < this.columns())) {
this._updateCss('.aciTree.aciTree' + this._instance.index + ' .aciTreeColumn' + index, 'width:' + width + 'px;');
this._updateWidth();
}
},
// update item margins
_updateWidth: function() {
var width = 0;
for (var i in this._instance.options.columnData) {
if (this.isColumn(i)) {
width += this.getWidth(i);
}
}
var icon = this._getCss(['aciTree', 'aciTreeIcon'], 'width', true);
// add item padding
width += this._getCss(['aciTree', 'aciTreeItem'], 'padding-left', true) + this._getCss(['aciTree', 'aciTreeItem'], 'padding-right', true);
this._updateCss('.aciTree.aciTree' + this._instance.index + ' .aciTreeItem', 'margin-right:' + (icon + width) + 'px;');
this._updateCss('.aciTree[dir=rtl].aciTree' + this._instance.index + ' .aciTreeItem', 'margin-right:0;margin-left:' + (icon + width) + 'px;');
},
// test if column is visible
// `index` is the #0 based column index
isColumn: function(index) {
if ((index >= 0) && (index < this.columns())) {
return this._getCss(['aciTree aciTree' + this._instance.index, 'aciTreeColumn' + index], 'display') != 'none';
}
return false;
},
// get column index by `props`
// return -1 if the column does not exists
columnIndex: function(props) {
if (this._private.propsIndex[props] !== undefined) {
return this._private.propsIndex[props];
}
return -1;
},
// get the column count
columns: function() {
return this._instance.options.columnData.length;
},
// set column to be visible or hidden
// `index` is the #0 based column index
// if `show` is undefined then the column visibility will be toggled
toggleColumn: function(index, show) {
if ((index >= 0) && (index < this.columns())) {
if (show === undefined) {
var show = !this.isColumn(index);
}
this._updateCss('.aciTree.aciTree' + this._instance.index + ' .aciTreeColumn' + index, 'display:' + (show ? 'inherit' : 'none') + ';');
this._updateWidth();
}
},
// override `_itemHook`
_itemHook: function(parent, item, itemData, level) {
if (this.columns()) {
var position = domApi.childrenByClass(item[0].firstChild, 'aciTreeEntry'), data, column;
for (var i in this._instance.options.columnData) {
data = this._instance.options.columnData[i];
column = this._createColumn(itemData, data, i);
position.insertBefore(column, position.firstChild);
}
}
// call the parent
this._super(parent, item, itemData, level);
},
// create column markup
// `itemData` item data object
// `columnData` column data definition
// `index` is the #0 based column index
_createColumn: function(itemData, columnData, index) {
var value = columnData.props && (itemData[columnData.props] !== undefined) ? itemData[columnData.props] :
((columnData.value === undefined) ? '' : columnData.value);
var column = window.document.createElement('DIV');
column.className = 'aciTreeColumn aciTreeColumn' + index;
column.innerHTML = value.length ? value : '&nbsp;';
return column;
},
// set column content
// `options.index` the #0 based column index
// `options.value` is the new content
// `options.oldValue` will keep the old content
setColumn: function(item, options) {
options = this._options(options, 'columnset', 'columnfail', 'wascolumn', item);
if (this.isItem(item) && (options.index >= 0) && (options.index < this.columns())) {
// a way to cancel the operation
if (!this._trigger(item, 'beforecolumn', options)) {
this._fail(item, options);
return;
}
var data = this.itemData(item);
// keep the old one
options.oldValue = data[this._instance.options.columnData[options.index].props];
if (options.value == options.oldValue) {
this._notify(item, options);
} else {
// set the column
item.children('.aciTreeLine').find('.aciTreeColumn' + options.index).html(options.value);
// remember this one
data[this._instance.options.columnData[options.index].props] = options.value;
this._success(item, options);
}
} else {
this._fail(item, options);
}
},
// get column content
getColumn: function(item, index) {
if ((index >= 0) && (index < this.columns())) {
var data = this.itemData(item);
return data ? data[this._instance.options.columnData[index].props] : null;
}
return null;
}
};
// extend the base aciTree class and add the columns stuff
aciPluginClass.plugins.aciTree = aciPluginClass.plugins.aciTree.extend(aciTree_column, 'aciTreeColumn');
// add extra default options
aciPluginClass.defaults('aciTree', options);
// for internal access
var domApi = aciPluginClass.plugins.aciTree_dom;
})(jQuery, this);

File diff suppressed because it is too large Load Diff

View File

@ -1,87 +0,0 @@
/*
* aciTree jQuery Plugin v4.5.0-rc.7
* http://acoderinsights.ro
*
* Copyright (c) 2014 Dragos Ursu
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Require jQuery Library >= v1.9.0 http://jquery.com
* + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin
*/
/*
* This extension adds debug capabilities, for now it's just a log of the aciTree events.
*/
(function($, window, undefined) {
// extra default options
var options = {
logTo: null // selector for the element where to log the errors to
};
// aciTree debug extension
var aciTree_debug = {
__extend: function() {
$.extend(this._private, {
logTo: null
});
// call the parent
this._super();
},
// init debug
_debugInit: function() {
if (this._instance.options.logTo) {
this._private.logTo = $(this._instance.options.logTo);
}
this._instance.jQuery.bind('acitree' + this._private.nameSpace, this.proxy(function(event, api, item, eventName, options) {
var message = 'aciTree event:' + eventName + ' for:' + (item ? api.getId(item) : 'ROOT') + ' uid:' + options.uid +
' success:' + (options.success ? 'Y' : 'N') + ' fail:' + (options.fail ? 'Y' : 'N') + ' expand:' + (options.expand ? 'Y' : 'N') +
' collapse:' + (options.collapse ? 'Y' : 'N') + ' unique:' + (options.unique ? 'Y' : 'N') + ' animated:' + (options.unanimated ? 'N' : 'Y');
if (this._private.logTo) {
this._private.logTo.prepend(message.replace(/([^\s]+:)/g, '<span style="color:#888">$1</span>') + '<br>');
} else if (console && console.log) {
console.log(message);
} else {
throw new Error(message);
}
}));
},
// override `_initHook`
_initHook: function() {
this._debugInit();
// call the parent
this._super();
},
// override set `option`
option: function(option, value) {
if (option == 'logTo') {
this._private.logTo = value ? $(value) : null;
}
// call the parent
this._super(option, value);
},
// done debug
_debugDone: function() {
this._instance.jQuery.unbind(this._private.nameSpace);
},
// override _destroyHook
_destroyHook: function(unloaded) {
if (unloaded) {
this._debugDone();
}
// call the parent
this._super(unloaded);
}
};
// extend the base aciTree class and add the hash stuff
aciPluginClass.plugins.aciTree = aciPluginClass.plugins.aciTree.extend(aciTree_debug, 'aciTreeDebug');
// add extra default options
aciPluginClass.defaults('aciTree', options);
})(jQuery, this);

View File

@ -1,660 +0,0 @@
/*
* aciTree jQuery Plugin v4.5.0-rc.7
* http://acoderinsights.ro
*
* Copyright (c) 2014 Dragos Ursu
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Require jQuery Library >= v1.9.0 http://jquery.com
* + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin
*/
/*
* The aciTree low-level DOM functions.
*
* A collection of functions optimised for aciTree DOM structure.
*
* Need to be included before the aciTree core and after aciPlugin.
*/
aciPluginClass.plugins.aciTree_dom = {
// get the UL container from a LI
// `node` must be valid LI DOM node
// can return NULL
container: function(node) {
var container = node.lastChild;
if (container && (container.nodeName == 'UL')) {
return container;
}
return null;
},
// get the first children from a LI (with filtering)
// `node` must be valid LI DOM node
// `callback` can return FALSE to skip a node
// can return NULL
firstChild: function(node, callback) {
var container = this.container(node);
if (container) {
var firstChild = container.firstChild;
if (callback) {
while (firstChild && !callback.call(this, firstChild)) {
firstChild = firstChild.nextSibling;
}
}
return firstChild;
}
return null;
},
// get the last children from a LI (with filtering)
// `node` must be valid LI DOM node
// `callback` can return FALSE to skip a node
// can return NULL
lastChild: function(node, callback) {
var container = this.container(node);
if (container) {
var lastChild = container.lastChild;
if (callback) {
while (lastChild && !callback.call(this, lastChild)) {
lastChild = lastChild.previousSibling;
}
}
return lastChild;
}
return null;
},
// get the previous LI sibling (with filtering)
// `node` must be valid LI DOM node
// `callback` can return FALSE to skip a node
// can return NULL
prev: function(node, callback) {
var previous = node.previousSibling;
if (callback) {
while (previous && !callback.call(this, previous)) {
previous = previous.previousSibling;
}
}
return previous;
},
// get the next LI sibling (with filtering)
// `node` must be valid LI DOM node
// `callback` can return FALSE to skip a node
// can return NULL
next: function(node, callback) {
var next = node.nextSibling;
if (callback) {
while (next && !callback.call(this, next)) {
next = next.nextSibling;
}
}
return next;
},
// get the previous LI in tree order (with filtering)
// `node` must be valid LI DOM node
// `callback` can return FALSE to skip a node or NULL to prevent drill down/skip the node
// can return NULL
prevAll: function(node, callback) {
var previous, lastChild, drillDown, match, prev, parent;
while (true) {
previous = this.prev(node);
if (previous) {
if (callback) {
match = callback.call(this, previous);
if (match === null) {
node = previous;
continue;
}
}
lastChild = this.lastChild(previous);
if (lastChild) {
if (callback && (callback.call(this, lastChild) === null)) {
node = lastChild;
continue;
}
prev = false;
while (drillDown = this.lastChild(lastChild)) {
lastChild = drillDown;
if (callback) {
match = callback.call(this, lastChild);
if (match === null) {
node = lastChild;
prev = true;
break;
}
}
}
if (prev) {
continue;
}
if (callback) {
match = callback.call(this, lastChild);
if (match) {
return lastChild;
} else if (match !== null) {
node = lastChild;
continue;
}
} else {
return lastChild;
}
} else {
if (!callback || match) {
return previous;
} else {
node = previous;
continue;
}
}
}
parent = this.parent(node);
if (parent) {
if (callback) {
match = callback.call(this, parent);
if (match) {
return parent;
} else {
node = parent;
}
} else {
return parent;
}
} else {
return null;
}
}
return null;
},
// get the next LI in tree order (with filtering)
// `node` must be valid LI DOM node
// `callback` can return FALSE to skip a node or NULL to prevent drill down/skip the node
// can return NULL
nextAll: function(node, callback) {
var firstChild, match, next, parent, child;
while (true) {
firstChild = this.firstChild(node);
if (firstChild) {
if (callback) {
match = callback.call(this, firstChild);
if (match) {
return firstChild;
} else {
node = firstChild;
if (match !== null) {
continue;
}
}
} else {
return firstChild;
}
}
while (true) {
next = this.next(node);
if (next) {
if (callback) {
match = callback.call(this, next);
if (match) {
return next;
} else {
node = next;
if (match !== null) {
break;
} else {
continue;
}
}
} else {
return next;
}
} else {
parent = node;
child = null;
while (parent = this.parent(parent)) {
next = this.next(parent);
if (next) {
if (callback) {
match = callback.call(this, next);
if (match) {
return next;
} else {
node = next;
if (match !== null) {
child = true;
} else {
child = false;
}
break;
}
} else {
return next;
}
}
}
if (child !== null) {
if (child) {
break;
} else {
continue;
}
}
return null;
}
}
}
return null;
},
// get the first LI in tree order (with filtering)
// `node` must be valid LI DOM node
// `callback` can return FALSE to skip a node or NULL to prevent drill down/skip the node
// can return NULL
first: function(node, callback) {
var container = this.container(node);
if (container) {
var firstChild = container.firstChild;
if (firstChild) {
if (callback && !callback.call(this, firstChild)) {
return this.nextAll(firstChild, callback);
}
return firstChild;
}
}
return null;
},
// get the last LI in tree order (with filtering)
// `node` must be valid LI DOM node
// `callback` can return FALSE to skip a node or NULL to prevent drill down/skip the node
// can return NULL
last: function(node, callback) {
var container = this.container(node);
if (container) {
var lastChild = container.lastChild;
if (lastChild) {
if (callback && (callback.call(this, lastChild) === null)) {
return this.prevAll(lastChild, callback);
} else {
var drillDown;
while (drillDown = this.lastChild(lastChild)) {
lastChild = drillDown;
}
if (callback && !callback.call(this, lastChild)) {
return this.prevAll(lastChild, callback);
}
return lastChild;
}
}
}
return null;
},
// get the children LI from the node
// `node` must be valid LI DOM node
// `drillDown` if TRUE all children are returned
// `callback` can return FALSE to skip a node or NULL to prevent drill down/skip the node
children: function(node, drillDown, callback) {
var children = [], levels = [], match, next, skip;
var firstChild = this.firstChild(node);
if (firstChild) {
while (true) {
skip = false;
do {
if (callback) {
match = callback.call(this, firstChild);
if (match) {
children.push(firstChild);
}
if (drillDown && (match !== null)) {
next = this.firstChild(firstChild);
if (next) {
levels.push(firstChild);
firstChild = next;
skip = true;
break;
}
}
} else {
children.push(firstChild);
if (drillDown) {
next = this.firstChild(firstChild);
if (next) {
levels.push(firstChild);
firstChild = next;
skip = true;
break;
}
}
}
} while (firstChild = firstChild.nextSibling);
if (!skip) {
while (firstChild = levels.pop()) {
firstChild = firstChild.nextSibling;
if (firstChild) {
break;
}
}
if (!firstChild) {
break;
}
}
}
}
return children;
},
// get a children from the node
// `node` must be valid DOM node
// `callback` can return FALSE to skip a node or NULL to stop the search
// can return NULL
childrenTill: function(node, callback) {
var levels = [], match, next, skip;
var firstChild = node.firstChild;
if (firstChild) {
while (true) {
skip = false;
do {
match = callback.call(this, firstChild);
if (match) {
return firstChild;
} else if (match === null) {
return null;
}
next = firstChild.firstChild;
if (next) {
levels.push(firstChild);
firstChild = next;
skip = true;
break;
}
} while (firstChild = firstChild.nextSibling);
if (!skip) {
while (firstChild = levels.pop()) {
firstChild = firstChild.nextSibling;
if (firstChild) {
break;
}
}
if (!firstChild) {
break;
}
}
}
}
return null;
},
// get a children from the node having a class
// `node` must be valid DOM node
// `className` String or Array to check for
// can return NULL
childrenByClass: function(node, className) {
if (node.getElementsByClassName) {
var list = node.getElementsByClassName(className instanceof Array ? className.join(' ') : className);
return list ? list[0] : null;
} else {
return this.childrenTill(node, function(node) {
return this.hasClass(node, className);
});
}
},
// get the parent LI from the children LI
// `node` must be valid LI DOM node
// can return NULL
parent: function(node) {
var parent = node.parentNode.parentNode;
if (parent && (parent.nodeName == 'LI')) {
return parent;
}
return null;
},
// get the parent LI from any children
// `node` must be valid children of a LI DOM node
// can return NULL
parentFrom: function(node) {
while (node.nodeName != 'LI') {
node = node.parentNode;
if (!node) {
return null;
}
}
return node;
},
// get a parent from the node
// `node` must be valid DOM node
// `callback` can return FALSE to skip a node or NULL to stop the search
// can return NULL
parentTill: function(node, callback) {
var match;
while (node = node.parentNode) {
match = callback.call(this, node);
if (match) {
return node;
} else if (match === null) {
return null;
}
}
return null;
},
// get a parent from the node having a class
// `node` must be valid DOM node
// `className` String or Array to check for
// can return NULL
parentByClass: function(node, className) {
return this.parentTill(node, function(node) {
return this.hasClass(node, className);
});
},
// test if node has class(es)
// `className` String or Array to check for
// `withOut` String or Array to exclude with
hasClass: function(node, className, withOut) {
var oldClass = ' ' + node.className + ' ';
if (withOut instanceof Array) {
for (var i = 0; i < withOut.length; i++) {
if (oldClass.indexOf(' ' + withOut[i] + ' ') != -1) {
return false;
}
}
} else {
if (withOut && oldClass.indexOf(' ' + withOut + ' ') != -1) {
return false;
}
}
if (className instanceof Array) {
for (var i = 0; i < className.length; i++) {
if (oldClass.indexOf(' ' + className[i] + ' ') == -1) {
return false;
}
}
} else {
if (className && oldClass.indexOf(' ' + className + ' ') == -1) {
return false;
}
}
return true;
},
// filter nodes with class(es)
// `nodes` Array of DOM nodes
// @see `hasClass`
withClass: function(nodes, className, withOut) {
var filter = [];
for (var i = 0; i < nodes.length; i++) {
if (this.hasClass(nodes[i], className, withOut)) {
filter.push(nodes[i]);
}
}
return filter;
},
// test if node has any class(es)
// `className` String or Array to check for (any class)
// `withOut` String or Array to exclude with
hasAnyClass: function(node, className, withOut) {
var oldClass = ' ' + node.className + ' ';
if (withOut instanceof Array) {
for (var i = 0; i < withOut.length; i++) {
if (oldClass.indexOf(' ' + withOut[i] + ' ') != -1) {
return false;
}
}
} else {
if (withOut && oldClass.indexOf(' ' + withOut + ' ') != -1) {
return false;
}
}
if (className instanceof Array) {
for (var i = 0; i < className.length; i++) {
if (oldClass.indexOf(' ' + className[i] + ' ') != -1) {
return true;
}
}
} else {
if (className && oldClass.indexOf(' ' + className + ' ') != -1) {
return true;
}
}
return false;
},
// filter nodes with any class(es)
// `nodes` Array of DOM nodes
// @see `hasAnyClass`
withAnyClass: function(nodes, className, withOut) {
var filter = [];
for (var i = 0; i < nodes.length; i++) {
if (this.hasAnyClass(nodes[i], className, withOut)) {
filter.push(nodes[i]);
}
}
return filter;
},
// add class(es) to node
// `node` must be valid DOM node
// `className` String or Array to add
// return TRUE if className changed
addClass: function(node, className) {
var oldClass = ' ' + node.className + ' ', append = '';
if (className instanceof Array) {
for (var i = 0; i < className.length; i++) {
if (oldClass.indexOf(' ' + className[i] + ' ') == -1) {
append += ' ' + className[i];
}
}
} else {
if (oldClass.indexOf(' ' + className + ' ') == -1) {
append += ' ' + className;
}
}
if (append) {
node.className = node.className + append;
return true;
}
return false;
},
// add class(es) to nodes
// `nodes` Array of DOM nodes
// @see `addClass`
addListClass: function(nodes, className, callback) {
for (var i = 0; i < nodes.length; i++) {
this.addClass(nodes[i], className);
if (callback) {
callback.call(this, nodes[i]);
}
}
},
// remove class(es) from node
// `node` must be valid DOM node
// `className` String or Array to remove
// return TRUE if className changed
removeClass: function(node, className) {
var oldClass = ' ' + node.className + ' ';
if (className instanceof Array) {
for (var i = 0; i < className.length; i++) {
oldClass = oldClass.replace(' ' + className[i] + ' ', ' ');
}
} else {
oldClass = oldClass.replace(' ' + className + ' ', ' ');
}
oldClass = oldClass.substr(1, oldClass.length - 2);
if (node.className != oldClass) {
node.className = oldClass;
return true;
}
return false;
},
// remove class(es) from nodes
// `nodes` Array of DOM nodes
// @see `removeClass`
removeListClass: function(nodes, className, callback) {
for (var i = 0; i < nodes.length; i++) {
this.removeClass(nodes[i], className);
if (callback) {
callback.call(this, nodes[i]);
}
}
},
// toggle node class(es)
// `node` must be valid DOM node
// `className` String or Array to toggle
// `add` TRUE to add them
// return TRUE if className changed
toggleClass: function(node, className, add) {
if (add) {
return this.addClass(node, className);
} else {
return this.removeClass(node, className);
}
},
// toggle nodes class(es)
// `nodes` Array of DOM nodes
// @see `toggleClass`
toggleListClass: function(nodes, className, add, callback) {
for (var i = 0; i < nodes.length; i++) {
this.toggleClass(nodes[i], className, add);
if (callback) {
callback.call(this, nodes[i]);
}
}
},
// add/remove and keep old class(es)
// `node` must be valid DOM node
// `addClass` String or Array to add
// `removeClass` String or Array to remove
// return TRUE if className changed
addRemoveClass: function(node, addClass, removeClass) {
var oldClass = ' ' + node.className + ' ';
if (removeClass) {
if (removeClass instanceof Array) {
for (var i = 0; i < removeClass.length; i++) {
oldClass = oldClass.replace(' ' + removeClass[i] + ' ', ' ');
}
} else {
oldClass = oldClass.replace(' ' + removeClass + ' ', ' ');
}
}
if (addClass) {
var append = '';
if (addClass instanceof Array) {
for (var i = 0; i < addClass.length; i++) {
if (oldClass.indexOf(' ' + addClass[i] + ' ') == -1) {
append += addClass[i] + ' ';
}
}
} else {
if (oldClass.indexOf(' ' + addClass + ' ') == -1) {
append += addClass + ' ';
}
}
oldClass += append;
}
oldClass = oldClass.substr(1, oldClass.length - 2);
if (node.className != oldClass) {
node.className = oldClass;
return true;
}
return false;
},
// add/remove and keep old class(es)
// `nodes` Array of DOM nodes
// @see `addRemoveClass`
addRemoveListClass: function(nodes, addClass, removeClass, callback) {
for (var i = 0; i < nodes.length; i++) {
this.addRemoveClass(nodes[i], addClass, removeClass);
if (callback) {
callback.call(this, nodes[i]);
}
}
}
};

View File

@ -1,294 +0,0 @@
/*
* aciTree jQuery Plugin v4.5.0-rc.7
* http://acoderinsights.ro
*
* Copyright (c) 2014 Dragos Ursu
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Require jQuery Library >= v1.9.0 http://jquery.com
* + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin
*/
/*
* This extension adds inplace edit support to aciTree,
* should be used with the selectable extension.
*/
(function($, window, undefined) {
// extra default options
var options = {
editable: false, // if TRUE then each item will be inplace editable
editDelay: 250 // how many [ms] to wait (with mouse down) before starting the edit (on mouse release)
};
// aciTree editable extension
// add inplace item editing by pressing F2 key or mouse click (to enter edit mode)
// press enter/escape to save/cancel the text edit
var aciTree_editable = {
__extend: function() {
// add extra data
$.extend(this._private, {
editTimestamp: null
});
// call the parent
this._super();
},
// init editable
_editableInit: function() {
this._instance.jQuery.bind('acitree' + this._private.nameSpace, function(event, api, item, eventName, options) {
switch (eventName) {
case 'blurred':
// support `selectable` extension
var item = api.edited();
if (item.length) {
// cancel edit/save the changes
api.endEdit();
}
break;
case 'deselected':
// support `selectable` extension
if (api.isEdited(item)) {
// cancel edit/save the changes
api.endEdit();
}
break;
}
}).bind('click' + this._private.nameSpace, this.proxy(function() {
// click on the tree
var item = this.edited();
if (item.length) {
// cancel edit/save the changes
this.endEdit();
}
})).bind('keydown' + this._private.nameSpace, this.proxy(function(e) {
switch (e.which) {
case 113: // F2
// support `selectable` extension
if (this.extSelectable && this.extSelectable()) {
var item = this.focused();
if (item.length && !this.isEdited(item) && this.isEnabled(item)) {
// enable edit on F2 key
this.edit(item);
// prevent default F2 key function
e.preventDefault();
}
}
break;
}
})).on('mousedown' + this._private.nameSpace, '.aciTreeItem', this.proxy(function(e) {
if ($(e.target).is('.aciTreeItem,.aciTreeText')) {
this._private.editTimestamp = $.now();
}
})).on('mouseup' + this._private.nameSpace, '.aciTreeItem', this.proxy(function(e) {
if ($(e.target).is('.aciTreeItem,.aciTreeText')) {
var passed = $.now() - this._private.editTimestamp;
// start edit only after N [ms] but before N * 4 [ms] have passed
if ((passed > this._instance.options.editDelay) && (passed < this._instance.options.editDelay * 4)) {
var item = this.itemFrom(e.target);
if ((!this.extSelectable || !this.extSelectable() || (this.isFocused(item) && (this.selected().length == 1))) && this.isEnabled(item)) {
// edit on mouseup
this.edit(item);
}
}
}
})).on('keydown' + this._private.nameSpace, 'input[type=text]', this.proxy(function(e) {
// key handling
switch (e.which) {
case 13: // enter
this.itemFrom(e.target).focus();
this.endEdit();
e.stopPropagation();
break;
case 27: // escape
this.itemFrom(e.target).focus();
this.endEdit({
save: false
});
e.stopPropagation();
// prevent default action on ESC
e.preventDefault();
break;
case 38: // up
case 40: // down
case 37: // left
case 39: // right
case 33: // pgup
case 34: // pgdown
case 36: // home
case 35: // end
case 32: // space
case 107: // numpad [+]
case 109: // numpad [-]
case 106: // numpad [*]
e.stopPropagation();
break;
}
})).on('blur' + this._private.nameSpace, 'input[type=text]', this.proxy(function() {
if (!this.extSelectable || !this.extSelectable()) {
// cancel edit/save the changes
this.endEdit();
}
})).on('click' + this._private.nameSpace + ' dblclick' + this._private.nameSpace, 'input[type=text]', function(e) {
e.stopPropagation();
});
},
// override `_initHook`
_initHook: function() {
if (this.extEditable()) {
this._editableInit();
}
// call the parent
this._super();
},
// low level DOM functions
_editableDOM: {
// add edit field
add: function(item) {
var line = item.addClass('aciTreeEdited').children('.aciTreeLine');
line.find('.aciTreeText').html('<input id="aciTree-editable-tree-item" type="text" value="" style="-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;-o-user-select:text;user-select:text" />');
line.find('label').attr('for', 'aciTree-editable-tree-item');
this._editableDOM.get(item).val(this.getLabel(item));
},
// remove edit field
remove: function(item, label) {
var line = item.removeClass('aciTreeEdited').children('.aciTreeLine');
line.find('.aciTreeText').html(this.getLabel(item));
line.find('label').removeAttr('for');
},
// return edit field
get: function(item) {
return item ? item.children('.aciTreeLine').find('input[type=text]') : $([]);
}
},
// get edited item
edited: function() {
return this._instance.jQuery.find('.aciTreeEdited');
},
// test if item is edited
isEdited: function(item) {
return item && domApi.hasClass(item[0], 'aciTreeEdited');
},
// set focus to the input
_focusEdit: function(item) {
var field = this._editableDOM.get(item).focus().trigger('click')[0];
if (field) {
if (typeof field.selectionStart == 'number') {
field.selectionStart = field.selectionEnd = field.value.length;
} else if (field.createTextRange !== undefined) {
var range = field.createTextRange();
range.collapse(false);
range.select();
}
}
},
// override `setLabel`
setLabel: function(item, options) {
if (!this.extEditable() || !this.isEdited(item)) {
// call the parent
this._super(item, options);
}
},
// edit item inplace
edit: function(item, options) {
options = this._options(options, 'edit', 'editfail', 'wasedit', item);
if (this.extEditable() && this.isItem(item)) {
// a way to cancel the operation
if (!this._trigger(item, 'beforeedit', options)) {
this._fail(item, options);
return;
}
var edited = this.edited();
if (edited.length) {
if (edited[0] == item[0]) {
this._notify(item, options);
return;
} else {
this._editableDOM.remove.call(this, edited);
this._trigger(edited, 'endedit', options);
}
}
this._editableDOM.add.call(this, item);
this._focusEdit(item);
this._success(item, options);
} else {
this._fail(item, options);
}
},
// end edit
// `options.save` when set to FALSE will not save the changes
endEdit: function(options) {
var item = this.edited();
options = this._options(options, 'edited', 'endeditfail', 'endedit', item);
if (this.extEditable() && this.isItem(item)) {
// a way to cancel the operation
if (!this._trigger(item, 'beforeendedit', options)) {
this._fail(item, options);
return;
}
var text = this._editableDOM.get(item).val();
this._editableDOM.remove.call(this, item);
if ((options.save === undefined) || options.save) {
this.setLabel(item, {
label: text
});
this._success(item, options);
} else {
this._notify(item, options);
}
} else {
this._fail(item, options);
}
},
// test if editable is enabled
extEditable: function() {
return this._instance.options.editable;
},
// override set `option`
option: function(option, value) {
if (this.wasInit() && !this.isLocked()) {
if ((option == 'editable') && (value != this.extEditable())) {
if (value) {
this._editableInit();
} else {
this._editableDone();
}
}
}
// call the parent
this._super(option, value);
},
// done editable
_editableDone: function() {
this._instance.jQuery.unbind(this._private.nameSpace);
this._instance.jQuery.off(this._private.nameSpace, '.aciTreeItem');
this._instance.jQuery.off(this._private.nameSpace, 'input[type=text]');
var edited = this.edited();
if (edited.length) {
this.endEdit();
}
},
// override `_destroyHook`
_destroyHook: function(unloaded) {
if (unloaded) {
this._editableDone();
}
// call the parent
this._super(unloaded);
}
};
// extend the base aciTree class and add the editable stuff
aciPluginClass.plugins.aciTree = aciPluginClass.plugins.aciTree.extend(aciTree_editable, 'aciTreeEditable');
// add extra default options
aciPluginClass.defaults('aciTree', options);
// for internal access
var domApi = aciPluginClass.plugins.aciTree_dom;
})(jQuery, this);

View File

@ -1,170 +0,0 @@
/*
* aciTree jQuery Plugin v4.5.0-rc.7
* http://acoderinsights.ro
*
* Copyright (c) 2014 Dragos Ursu
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Require jQuery Library >= v1.9.0 http://jquery.com
* + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin
*/
/*
* This extension adds hash/fragment support using aciFragment, it opens/select item(s) based on variables stored in the fragment part of the URL.
* The states are loaded from the URL fragment and set on treeview init. Multiple item IDs separated with ";" are supported for
* opening/selecting deep items (if loading nodes is required).
* Require aciFragment https://github.com/dragosu/jquery-aciFragment and the utils extension for finding items by ID.
*/
(function($, window, undefined) {
// extra default options
var options = {
selectHash: null, // hash key name to select a item (item path IDs as key value, multiple item IDs separated with a ";")
openHash: null // hash key name to open item(s) (item path IDs as key value, multiple item IDs separated with a ";")
};
// aciTree hash extension
// select/open items based on IDs stored in the fragment of the current URL
var aciTree_hash = {
__extend: function() {
$.extend(this._private, {
lastSelect: null,
lastOpen: null,
// store `aciFragment` api
hashApi: null
});
// call the parent
this._super();
},
// init hash
_hashInit: function() {
// init `aciFragment`
this._instance.jQuery.aciFragment();
this._private.hashApi = this._instance.jQuery.aciFragment('api');
this._instance.jQuery.bind('acitree' + this._private.nameSpace, function(event, api, item, eventName, options) {
switch (eventName) {
case 'init':
api._hashRestore();
break;
}
}).bind('acifragment' + this._private.nameSpace, this.proxy(function(event, api, anchorChanged) {
event.stopPropagation();
this._hashRestore();
}));
},
// override `_initHook`
_initHook: function() {
if (this.extHast()) {
this._hashInit();
}
// call the parent
this._super();
},
// restore item states from hash
_hashRestore: function() {
var queue = this._instance.queue;
var process = function(opened) {
// open all hash items
for (var i in opened) {
(function(id) {
// add item to queue
queue.push(function(complete) {
this.search(null, {
success: function(item) {
this.open(item, {
uid: 'ui.hash',
success: complete,
fail: complete
});
},
fail: complete,
search: id
});
});
})(opened[i]);
}
};
if (this._instance.options.openHash) {
var hash = this._private.hashApi.get(this._instance.options.openHash, '');
if (hash.length && (hash != this._private.lastOpen)) {
this._private.lastOpen = hash;
var opened = hash.split(';');
process(opened);
}
}
// support `selectable` extension
if (this._instance.options.selectHash && this.extSelectable && this.extSelectable()) {
var hash = this._private.hashApi.get(this._instance.options.selectHash, '');
if (hash.length && (hash != this._private.lastSelect)) {
this._private.lastSelect = hash;
var opened = hash.split(';');
var selected = opened.pop();
process(opened);
if (selected) {
// select item
queue.push(function(complete) {
this.search(null, {
success: function(item) {
this.select(item, {
uid: 'ui.hash',
success: function(item) {
this.setVisible(item, {
center: true
});
complete();
},
fail: complete
});
},
fail: complete,
search: selected
});
});
}
}
}
},
// test if hash is enabled
extHast: function() {
return this._instance.options.selectHash || this._instance.options.openHash;
},
// override set option
option: function(option, value) {
var hash = this.extHast();
// call the parent
this._super(option, value);
if (this.extHast() != hash) {
if (hash) {
this._hashDone();
} else {
this._hashInit();
}
}
},
// done hash
_hashDone: function() {
this._instance.jQuery.unbind(this._private.nameSpace);
this._private.hashApi = null;
this._instance.jQuery.aciFragment('destroy');
},
// override `_destroyHook`
_destroyHook: function(unloaded) {
if (unloaded) {
this._hashDone();
}
// call the parent
this._super(unloaded);
}
};
// extend the base aciTree class and add the hash stuff
aciPluginClass.plugins.aciTree = aciPluginClass.plugins.aciTree.extend(aciTree_hash, 'aciTreeHash');
// add extra default options
aciPluginClass.defaults('aciTree', options);
})(jQuery, this);

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,290 +0,0 @@
/*
* aciTree jQuery Plugin v4.5.0-rc.7
* http://acoderinsights.ro
*
* Copyright (c) 2014 Dragos Ursu
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Require jQuery Library >= v1.9.0 http://jquery.com
* + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin
*/
/*
* This extension adds save/restore support for item states (open/selected) using local storage.
* The states are saved on item select/open and restored on treeview init.
* Require jStorage https://github.com/andris9/jStorage and the utils extension for finding items by ID.
*/
(function($, window, undefined) {
// extra default options
var options = {
persist: null // the storage key name to keep the states (should be unique/treeview)
};
// aciTree persist extension
// save/restore item state in/from local storage
var aciTree_persist = {
__extend: function() {
$.extend(this._private, {
// timeouts for the save operation
selectTimeout: null,
focusTimeout: null,
openTimeout: null
});
// call the parent
this._super();
},
// init persist
_initPersist: function() {
this._instance.jQuery.bind('acitree' + this._private.nameSpace, function(event, api, item, eventName, options) {
if (options.uid == 'ui.persist') {
// skip processing itself
return;
}
switch (eventName) {
case 'init':
api._persistRestore();
break;
case 'selected':
case 'deselected':
// support `selectable` extension
api._persistLater('selected');
break;
case 'focus':
case 'blur':
// support `selectable` extension
api._persistLater('focused');
break;
case 'opened':
case 'closed':
api._persistLater('opened');
break;
}
});
},
// override `_initHook`
_initHook: function() {
if (this.extPersist()) {
this._initPersist();
}
// call the parent
this._super();
},
// persist states
_persistLater: function(type) {
switch (type) {
case 'selected':
window.clearTimeout(this._private.selectTimeout);
this._private.selectTimeout = window.setTimeout(this.proxy(function() {
this._persistSelected();
}), 250);
break;
case 'focused':
window.clearTimeout(this._private.focusTimeout);
this._private.focusTimeout = window.setTimeout(this.proxy(function() {
this._persistFocused();
}), 250);
break;
case 'opened':
window.clearTimeout(this._private.openTimeout);
this._private.openTimeout = window.setTimeout(this.proxy(function() {
this._persistOpened();
}), 250);
break;
}
},
// restore item states
_persistRestore: function() {
var queue = new this._queue(this, this._instance.options.queue);
var task = new this._task(queue, function(complete) {
// support `selectable` extension
if (this.extSelectable && this.extSelectable()) {
var selected = $.jStorage.get('aciTree_' + this._instance.options.persist + '_selected');
if (selected instanceof Array) {
// select all saved items
for (var i in selected) {
(function(path) {
queue.push(function(complete) {
this.searchPath(null, {
success: function(item) {
this.select(item, {
uid: 'ui.persist',
success: function() {
complete();
},
fail: complete,
focus: false
});
},
fail: complete,
path: path.split(';')
});
});
})(selected[i]);
if (!this._instance.options.multiSelectable) {
break;
}
}
}
var focused = $.jStorage.get('aciTree_' + this._instance.options.persist + '_focused');
if (focused instanceof Array) {
// focus all saved items
for (var i in focused) {
(function(path) {
queue.push(function(complete) {
this.searchPath(null, {
success: function(item) {
this.focus(item, {
uid: 'ui.persist',
success: function(item) {
this.setVisible(item, {
center: true
});
complete();
},
fail: complete
});
},
fail: complete,
path: path.split(';')
});
});
})(focused[i]);
}
}
}
complete();
});
var opened = $.jStorage.get('aciTree_' + this._instance.options.persist + '_opened');
if (opened instanceof Array) {
// open all saved items
for (var i in opened) {
(function(path) {
// add item to queue
task.push(function(complete) {
this.searchPath(null, {
success: function(item) {
this.open(item, {
uid: 'ui.persist',
success: complete,
fail: complete
});
},
fail: complete,
path: path.split(';'),
load: true
});
});
})(opened[i]);
}
}
},
// persist selected items
_persistSelected: function() {
// support `selectable` extension
if (this.extSelectable && this.extSelectable()) {
var selected = [];
this.selected().each(this.proxy(function(element) {
var item = $(element);
var path = this.pathId(item);
path.push(this.getId(item));
selected.push(path.join(';'));
}, true));
$.jStorage.set('aciTree_' + this._instance.options.persist + '_selected', selected);
}
},
// persist focused item
_persistFocused: function() {
// support `selectable` extension
if (this.extSelectable && this.extSelectable()) {
var focused = [];
this.focused().each(this.proxy(function(element) {
var item = $(element);
var path = this.pathId(item);
path.push(this.getId(item));
focused.push(path.join(';'));
}, true));
$.jStorage.set('aciTree_' + this._instance.options.persist + '_focused', focused);
}
},
// persist opened items
_persistOpened: function() {
var opened = [];
this.inodes(this.children(null, true), true).each(this.proxy(function(element) {
var item = $(element);
if (this.isOpenPath(item)) {
var path = this.pathId(item);
path.push(this.getId(item));
opened.push(path.join(';'));
}
}, true));
$.jStorage.set('aciTree_' + this._instance.options.persist + '_opened', opened);
},
// test if there is any saved data
isPersist: function() {
if (this.extPersist()) {
var selected = $.jStorage.get('aciTree_' + this._instance.options.persist + '_selected');
if (selected instanceof Array) {
return true;
}
var focused = $.jStorage.get('aciTree_' + this._instance.options.persist + '_focused');
if (focused instanceof Array) {
return true;
}
var opened = $.jStorage.get('aciTree_' + this._instance.options.persist + '_opened');
if (opened instanceof Array) {
return true;
}
}
return false;
},
// remove any saved states
unpersist: function() {
if (this.extPersist()) {
$.jStorage.deleteKey('aciTree_' + this._instance.options.persist + '_selected');
$.jStorage.deleteKey('aciTree_' + this._instance.options.persist + '_focused');
$.jStorage.deleteKey('aciTree_' + this._instance.options.persist + '_opened');
}
},
// test if persist is enabled
extPersist: function() {
return this._instance.options.persist;
},
// override set `option`
option: function(option, value) {
var persist = this.extPersist();
// call the parent
this._super(option, value);
if (this.extPersist() != persist) {
if (persist) {
this._donePersist();
} else {
this._initPersist();
}
}
},
// done persist
_donePersist: function() {
this._instance.jQuery.unbind(this._private.nameSpace);
},
// override `_destroyHook`
_destroyHook: function(unloaded) {
if (unloaded) {
this._donePersist();
}
// call the parent
this._super(unloaded);
}
};
// extend the base aciTree class and add the persist stuff
aciPluginClass.plugins.aciTree = aciPluginClass.plugins.aciTree.extend(aciTree_persist, 'aciTreePersist');
// add extra default options
aciPluginClass.defaults('aciTree', options);
})(jQuery, this);

View File

@ -1,471 +0,0 @@
/*
* aciTree jQuery Plugin v4.5.0-rc.7
* http://acoderinsights.ro
*
* Copyright (c) 2014 Dragos Ursu
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Require jQuery Library >= v1.9.0 http://jquery.com
* + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin
*/
/*
* This extension adds radio-button support to aciTree,
* should be used with the selectable extension.
*
* The are a few extra properties for the item data:
*
* {
* ...
* radio: true, // TRUE (default) means the item will have a radio button (can be omitted if the `checkbox` extension is not used)
* checked: false, // if should be checked or not
* ...
* }
*
*/
(function($, window, undefined) {
// extra default options
var options = {
radio: false, // if TRUE then each item will have a radio button
radioChain: true, // if TRUE the selection will propagate to the parents/children
radioBreak: true, // if TRUE then a missing radio button will break the chaining
radioClick: false // if TRUE then a click will trigger a state change only when made over the radio-button itself
};
// aciTree radio extension
var aciTree_radio = {
// init radio
_radioInit: function() {
this._instance.jQuery.bind('acitree' + this._private.nameSpace, function(event, api, item, eventName, options) {
switch (eventName) {
case 'loaded':
if (item) {
// check/update on item load
api._radioLoad(item);
}
break;
}
}).bind('keydown' + this._private.nameSpace, this.proxy(function(e) {
switch (e.which) {
case 32: // space
// support `selectable` extension
if (this.extSelectable && this.extSelectable() && !e.ctrlKey) {
var item = this.focused();
if (this.hasRadio(item) && this.isEnabled(item)) {
if (!this.isChecked(item)) {
this.check(item);
}
e.stopImmediatePropagation();
// prevent page scroll
e.preventDefault();
}
}
break;
}
})).on('click' + this._private.nameSpace, '.aciTreeItem', this.proxy(function(e) {
if (!this._instance.options.radioClick || $(e.target).is('.aciTreeCheck')) {
var item = this.itemFrom(e.target);
if (this.hasRadio(item) && this.isEnabled(item) && (!this.extSelectable || !this.extSelectable() || (!e.ctrlKey && !e.shiftKey))) {
// change state on click
if (!this.isChecked(item)) {
this.check(item);
}
e.preventDefault();
}
}
}));
},
// override `_initHook`
_initHook: function() {
if (this.extRadio()) {
this._radioInit();
}
// call the parent
this._super();
},
// override `_itemHook`
_itemHook: function(parent, item, itemData, level) {
if (this.extRadio()) {
// support `checkbox` extension
var checkbox = this.extCheckbox && this.hasCheckbox(item);
if (!checkbox && (itemData.radio || ((itemData.radio === undefined) && (!this.extCheckbox || !this.extCheckbox())))) {
this._radioDOM.add(item, itemData);
}
}
// call the parent
this._super(parent, item, itemData, level);
},
// low level DOM functions
_radioDOM: {
// add item radio
add: function(item, itemData) {
domApi.addClass(item[0], itemData.checked ? ['aciTreeRadio', 'aciTreeChecked'] : 'aciTreeRadio');
var text = domApi.childrenByClass(item[0].firstChild, 'aciTreeText');
var parent = text.parentNode;
var label = window.document.createElement('LABEL');
var check = window.document.createElement('SPAN');
check.className = 'aciTreeCheck';
label.appendChild(check);
label.appendChild(text);
parent.appendChild(label);
item[0].firstChild.setAttribute('aria-checked', !!itemData.checked);
},
// remove item radio
remove: function(item) {
domApi.removeClass(item[0], ['aciTreeRadio', 'aciTreeChecked']);
var text = domApi.childrenByClass(item[0].firstChild, 'aciTreeText');
var label = text.parentNode;
var parent = label.parentNode;
parent.replaceChild(text, label)
item[0].firstChild.removeAttribute('aria-checked');
},
// (un)check items
check: function(items, state) {
domApi.toggleListClass(items.toArray(), 'aciTreeChecked', state, function(node) {
node.firstChild.setAttribute('aria-checked', state);
});
}
},
// update item on load
_radioLoad: function(item) {
if (!this._instance.options.radioChain) {
// do not update on load
return;
}
if (this.hasRadio(item)) {
if (this.isChecked(item)) {
if (!this.radios(this.children(item, false, true), true).length) {
// the item is checked but no children are, check the children
this._radioUpdate(item, true);
}
} else {
// the item is not checked, uncheck children
this._radioUpdate(item);
}
}
},
// get children list
_radioChildren: function(item) {
if (this._instance.options.radioBreak) {
var list = [];
var process = this.proxy(function(item) {
var children = this.children(item, false, true);
children.each(this.proxy(function(element) {
var item = $(element);
// break on missing radio
if (this.hasRadio(item)) {
list.push(element);
process(item);
}
}, true));
});
process(item);
return $(list);
} else {
var children = this.children(item, true, true);
return this.radios(children);
}
},
// get children across items
_radioLevel: function(items) {
var list = [];
items.each(this.proxy(function(element) {
var item = $(element);
var children = this.children(item, false, true);
children.each(this.proxy(function(element) {
var item = $(element);
if (!this._instance.options.radioBreak || this.hasRadio(item)) {
list.push(element);
}
}, true));
}, true));
return $(list);
},
// update radio state
_radioUpdate: function(item, state) {
// update siblings
var siblings = this.proxy(function(item) {
var siblings = this.siblings(item, true);
this._radioDOM.check(this.radios(siblings), false);
siblings.each(this.proxy(function(element) {
var item = $(element);
if (!this._instance.options.radioBreak || this.hasRadio(item)) {
this._radioDOM.check(this._radioChildren(item), false);
}
}, true));
});
if (state) {
siblings(item);
}
// update children
var checkDown = this.proxy(function(item) {
var children = this._radioLevel(item);
var radios = this.radios(children);
if (radios.length) {
var checked = this.radios(children, true);
if (checked.length) {
checked = checked.first();
this._radioDOM.check(checked, true);
siblings(checked);
checkDown(checked);
} else {
checked = radios.first();
this._radioDOM.check(checked, true);
siblings(checked);
checkDown(checked);
}
} else if (children.length) {
checkDown(children);
}
});
if (state) {
checkDown(item);
} else {
this._radioDOM.check(this._radioChildren(item), false);
}
// update parents
var checkUp = this.proxy(function(item) {
var parent = this.parent(item);
if (parent.length) {
if (this.hasRadio(parent)) {
if (state) {
siblings(parent);
}
this._radioDOM.check(parent, state);
checkUp(parent);
} else {
if (!this._instance.options.radioBreak) {
if (state) {
siblings(parent);
}
checkUp(parent);
}
}
}
});
if (state !== undefined) {
checkUp(item);
}
},
// test if item have a radio
hasRadio: function(item) {
return item && domApi.hasClass(item[0], 'aciTreeRadio');
},
// add radio button
addRadio: function(item, options) {
options = this._options(options, 'radioadded', 'addradiofail', 'wasradio', item);
if (this.isItem(item)) {
// a way to cancel the operation
if (!this._trigger(item, 'beforeaddradio', options)) {
this._fail(item, options);
return;
}
if (this.hasRadio(item)) {
this._notify(item, options);
} else {
var process = function() {
this._radioDOM.add(item, {
});
this._success(item, options);
};
// support `checkbox` extension
if (this.extCheckbox && this.hasCheckbox(item)) {
// remove checkbox first
this.removeCheckbox(item, this._inner(options, {
success: process,
fail: options.fail
}));
} else {
process.apply(this);
}
}
} else {
this._fail(item, options);
}
},
// remove radio button
removeRadio: function(item, options) {
options = this._options(options, 'radioremoved', 'removeradiofail', 'notradio', item);
if (this.isItem(item)) {
// a way to cancel the operation
if (!this._trigger(item, 'beforeremoveradio', options)) {
this._fail(item, options);
return;
}
if (this.hasRadio(item)) {
this._radioDOM.remove(item);
this._success(item, options);
} else {
this._notify(item, options);
}
} else {
this._fail(item, options);
}
},
// test if it's checked
isChecked: function(item) {
if (this.hasRadio(item)) {
return domApi.hasClass(item[0], 'aciTreeChecked');
}
// support `checkbox` extension
if (this._super) {
// call the parent
return this._super(item);
}
return false;
},
// check radio button
check: function(item, options) {
if (this.extRadio && this.hasRadio(item)) {
options = this._options(options, 'checked', 'checkfail', 'waschecked', item);
// a way to cancel the operation
if (!this._trigger(item, 'beforecheck', options)) {
this._fail(item, options);
return;
}
if (this.isChecked(item)) {
this._notify(item, options);
} else {
this._radioDOM.check(item, true);
if (this._instance.options.radioChain) {
// chain them
this._radioUpdate(item, true);
}
this._success(item, options);
}
} else {
// support `checkbox` extension
if (this._super) {
// call the parent
this._super(item, options);
} else {
this._trigger(item, 'checkfail', options);
this._fail(item, options);
}
}
},
// uncheck radio button
uncheck: function(item, options) {
if (this.extRadio && this.hasRadio(item)) {
options = this._options(options, 'unchecked', 'uncheckfail', 'notchecked', item);
// a way to cancel the operation
if (!this._trigger(item, 'beforeuncheck', options)) {
this._fail(item, options);
return;
}
if (this.isChecked(item)) {
this._radioDOM.check(item, false);
if (this._instance.options.radioChain) {
// chain them
this._radioUpdate(item, false);
}
this._success(item, options);
} else {
this._notify(item, options);
}
} else {
// support `checkbox` extension
if (this._super) {
// call the parent
this._super(item, options);
} else {
this._trigger(item, 'uncheckfail', options);
this._fail(item, options);
}
}
},
// filter items with radio by state (if set)
radios: function(items, state) {
if (state !== undefined) {
return $(domApi.withClass(items.toArray(), state ? ['aciTreeRadio', 'aciTreeChecked'] : 'aciTreeRadio', state ? null : 'aciTreeChecked'));
}
return $(domApi.withClass(items.toArray(), 'aciTreeRadio'));
},
// override `_serialize`
_serialize: function(item, callback) {
var data = this._super(item, callback);
if (data && this.extRadio()) {
if (data.hasOwnProperty('radio')) {
data.radio = this.hasRadio(item);
data.checked = this.isChecked(item);
} else if (this.hasRadio(item)) {
if (this.extCheckbox && this.extCheckbox()) {
data.radio = true;
}
data.checked = this.isChecked(item);
}
}
return data;
},
// override `serialize`
serialize: function(item, what, callback) {
if (what == 'radio') {
var serialized = '';
var children = this.children(item, true, true);
this.radios(children, true).each(this.proxy(function(element) {
var item = $(element);
if (callback) {
serialized += callback.call(this, item, what, this.getId(item));
} else {
serialized += this._instance.options.serialize.call(this, item, what, this.getId(item));
}
}, true));
return serialized;
}
return this._super(item, what, callback);
},
// test if radio is enabled
extRadio: function() {
return this._instance.options.radio;
},
// override set `option`
option: function(option, value) {
if (this.wasInit() && !this.isLocked()) {
if ((option == 'radio') && (value != this.extRadio())) {
if (value) {
this._radioInit();
} else {
this._radioDone();
}
}
}
// call the parent
this._super(option, value);
},
// done radio
_radioDone: function(destroy) {
this._instance.jQuery.unbind(this._private.nameSpace);
this._instance.jQuery.off(this._private.nameSpace, '.aciTreeItem');
if (!destroy) {
// remove radios
this.radios(this.children(null, true, true)).each(this.proxy(function(element) {
this.removeRadio($(element));
}, true));
}
},
// override `_destroyHook`
_destroyHook: function(unloaded) {
if (unloaded) {
this._radioDone(true);
}
// call the parent
this._super(unloaded);
}
};
// extend the base aciTree class and add the radio stuff
aciPluginClass.plugins.aciTree = aciPluginClass.plugins.aciTree.extend(aciTree_radio, 'aciTreeRadio');
// add extra default options
aciPluginClass.defaults('aciTree', options);
// for internal access
var domApi = aciPluginClass.plugins.aciTree_dom;
})(jQuery, this);

View File

@ -1,739 +0,0 @@
/*
* aciTree jQuery Plugin v4.5.0-rc.7
* http://acoderinsights.ro
*
* Copyright (c) 2014 Dragos Ursu
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Require jQuery Library >= v1.9.0 http://jquery.com
* + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin
*/
/*
* This extension adds item selection/keyboard navigation to aciTree and need to
* be always included if you care about accessibility.
*
* There is an extra property for the item data:
*
* {
* ...
* selected: false, // TRUE means the item will be selected
* ...
* }
*
*/
(function($, window, undefined) {
// extra default options
var options = {
selectable: true, // if TRUE then one item can be selected (and the tree navigation with the keyboard will be enabled)
multiSelectable: false, // if TRUE then multiple items can be selected at a time
// the 'tabIndex' attribute need to be >= 0 set on the tree container (by default will be set to 0)
fullRow: false, // if TRUE then the selection will be made on the entire row (the CSS should reflect this)
textSelection: false // if FALSE then the item text can't be selected
};
// aciTree selectable extension
// adds item selection & keyboard navigation (left/right, up/down, pageup/pagedown, home/end, space, enter, escape)
// dblclick also toggles the item
var aciTree_selectable = {
__extend: function() {
// add extra data
$.extend(this._instance, {
focus: false
});
$.extend(this._private, {
blurTimeout: null,
spinPoint: null // the selected item to operate against when using the shift key with selection
});
// call the parent
this._super();
},
// test if has focus
hasFocus: function() {
return this._instance.focus;
},
// init selectable
_selectableInit: function() {
if (this._instance.jQuery.attr('tabindex') === undefined) {
// ensure the tree can get focus
this._instance.jQuery.attr('tabindex', 0);
}
if (!this._instance.options.textSelection) {
// disable text selection
this._selectable(false);
}
this._instance.jQuery.bind('acitree' + this._private.nameSpace, function(event, api, item, eventName, options) {
switch (eventName) {
case 'closed':
var focused = api.focused();
if (api.isChildren(item, focused)) {
// move focus to parent on close
api._focusOne(item);
}
// deselect children on parent close
api.children(item, true).each(api.proxy(function(element) {
var item = $(element);
if (this.isSelected(item)) {
this.deselect(item);
}
}, true));
break;
}
}).bind('focusin' + this._private.nameSpace, this.proxy(function() {
// handle tree focus
window.clearTimeout(this._private.blurTimeout);
if (!this.hasFocus()) {
this._instance.focus = true;
domApi.addClass(this._instance.jQuery[0], 'aciTreeFocus');
this._trigger(null, 'focused');
}
})).bind('focusout' + this._private.nameSpace, this.proxy(function() {
// handle tree focus
window.clearTimeout(this._private.blurTimeout);
this._private.blurTimeout = window.setTimeout(this.proxy(function() {
if (this.hasFocus()) {
this._instance.focus = false;
domApi.removeClass(this._instance.jQuery[0], 'aciTreeFocus');
this._trigger(null, 'blurred');
}
}), 10);
})).bind('keydown' + this._private.nameSpace, this.proxy(function(e) {
if (!this.hasFocus()) {
// do not handle if we do not have focus
return;
}
var focused = this.focused();
if (focused.length && this.isBusy(focused)) {
// skip when busy
return false;
}
var item = $([]);
switch (e.which) {
case 65: // aA
if (this._instance.options.multiSelectable && e.ctrlKey) {
// select all visible items
var select = this.visible(this.enabled(this.children(null, true))).not(this.selected());
select.each(this.proxy(function(element) {
this.select($(element), {
focus: false
});
}, true));
if (!this.focused().length) {
// ensure one item has focus
this._focusOne(this.visible(select, true).first());
}
// prevent default action
e.preventDefault();
}
break;
case 38: // up
item = focused.length ? this._prev(focused) : this.first();
break;
case 40: // down
item = focused.length ? this._next(focused) : this.first();
break;
case 37: // left
if (focused.length) {
if (this.isOpen(focused)) {
item = focused;
// close the item
this.close(focused, {
collapse: this._instance.options.collapse,
expand: this._instance.options.expand,
unique: this._instance.options.unique
});
} else {
item = this.parent(focused);
}
} else {
item = this._first();
}
break;
case 39: // right
if (focused.length) {
if (this.isInode(focused) && this.isClosed(focused)) {
item = focused;
// open the item
this.open(focused, {
collapse: this._instance.options.collapse,
expand: this._instance.options.expand,
unique: this._instance.options.unique
});
} else {
item = this.first(focused);
}
} else {
item = this._first();
}
break;
case 33: // pgup
item = focused.length ? this._prevPage(focused) : this._first();
break;
case 34: // pgdown
item = focused.length ? this._nextPage(focused) : this._first();
break;
case 36: // home
item = this._first();
break;
case 35: // end
item = this._last();
break;
case 13: // enter
case 107: // numpad [+]
item = focused;
if (this.isInode(focused) && this.isClosed(focused)) {
// open the item
this.open(focused, {
collapse: this._instance.options.collapse,
expand: this._instance.options.expand,
unique: this._instance.options.unique
});
}
break;
case 27: // escape
case 109: // numpad [-]
item = focused;
if (this.isOpen(focused)) {
// close the item
this.close(focused, {
collapse: this._instance.options.collapse,
expand: this._instance.options.expand,
unique: this._instance.options.unique
});
}
if (e.which == 27) {
// prevent default action on ESC
e.preventDefault();
}
break;
case 32: // space
item = focused;
if (this.isInode(focused) && !e.ctrlKey) {
// toggle the item
this.toggle(focused, {
collapse: this._instance.options.collapse,
expand: this._instance.options.expand,
unique: this._instance.options.unique
});
}
// prevent page scroll
e.preventDefault();
break;
case 106: // numpad [*]
item = focused;
if (this.isInode(focused)) {
// open all children
this.open(focused, {
collapse: this._instance.options.collapse,
expand: true,
unique: this._instance.options.unique
});
}
break;
}
if (item.length) {
if (this._instance.options.multiSelectable && !e.ctrlKey && !e.shiftKey) {
// unselect others
this._unselect(this.selected().not(item));
}
if (!this.isVisible(item)) {
// bring it into view
this.setVisible(item);
}
if (e.ctrlKey) {
if ((e.which == 32) && this.isEnabled(item)) { // space
if (this.isSelected(item)) {
this.deselect(item);
} else {
this.select(item);
}
// remember for later
this._private.spinPoint = item;
} else {
this._focusOne(item);
}
} else if (e.shiftKey) {
this._shiftSelect(item);
} else {
if (!this.isSelected(item) && this.isEnabled(item)) {
this.select(item);
} else {
this._focusOne(item);
}
// remember for later
this._private.spinPoint = item;
}
return false;
}
}));
this._fullRow(this._instance.options.fullRow);
this._multiSelectable(this._instance.options.multiSelectable);
},
// change full row mode
_fullRow: function(state) {
this._instance.jQuery.off(this._private.nameSpace, '.aciTreeLine,.aciTreeItem').off(this._private.nameSpace, '.aciTreeItem');
this._instance.jQuery.on('mousedown' + this._private.nameSpace + ' click' + this._private.nameSpace, state ? '.aciTreeLine,.aciTreeItem' : '.aciTreeItem', this.proxy(function(e) {
var item = this.itemFrom(e.target);
if (!this.isVisible(item)) {
this.setVisible(item);
}
if (e.ctrlKey) {
if (e.type == 'click') {
if (this.isEnabled(item)) {
// (de)select item
if (this.isSelected(item)) {
this.deselect(item);
this._focusOne(item);
} else {
this.select(item);
}
} else {
this._focusOne(item);
}
}
} else if (this._instance.options.multiSelectable && e.shiftKey) {
this._shiftSelect(item);
} else {
if (this._instance.options.multiSelectable && (!this.isSelected(item) || (e.type == 'click'))) {
// deselect all other (keep the old focus)
this._unselect(this.selected().not(item));
}
this._selectOne(item);
}
if (!e.shiftKey) {
this._private.spinPoint = item;
}
})).on('dblclick' + this._private.nameSpace, state ? '.aciTreeLine,.aciTreeItem' : '.aciTreeItem', this.proxy(function(e) {
var item = this.itemFrom(e.target);
if (this.isInode(item)) {
// toggle the item
this.toggle(item, {
collapse: this._instance.options.collapse,
expand: this._instance.options.expand,
unique: this._instance.options.unique
});
return false;
}
}));
if (state) {
domApi.addClass(this._instance.jQuery[0], 'aciTreeFullRow');
} else {
domApi.removeClass(this._instance.jQuery[0], 'aciTreeFullRow');
}
},
// change selection mode
_multiSelectable: function(state) {
if (state) {
this._instance.jQuery.attr('aria-multiselectable', true);
} else {
var focused = this.focused();
this._unselect(this.selected().not(focused));
this._instance.jQuery.removeAttr('aria-multiselectable');
}
},
// process `shift` key selection
_shiftSelect: function(item) {
var spinPoint = this._private.spinPoint;
if (!spinPoint || !$.contains(this._instance.jQuery[0], spinPoint[0]) || !this.isOpenPath(spinPoint)) {
spinPoint = this.focused();
}
if (spinPoint.length) {
// select a range of items
var select = [item[0]], start = spinPoint[0], found = false, stop = item[0];
var visible = this.visible(this.children(null, true));
visible.each(this.proxy(function(element) {
// find what items to select
if (found) {
if (this.isEnabled($(element))) {
select.push(element);
}
if ((element == start) || (element == stop)) {
return false;
}
} else if ((element == start) || (element == stop)) {
if (this.isEnabled($(element))) {
select.push(element);
}
if ((element == start) && (element == stop)) {
return false;
}
found = true;
}
}, true));
this._unselect(this.selected().not(select));
// select the items
$(select).not(item).each(this.proxy(function(element) {
var item = $(element);
if (!this.isSelected(item)) {
// select item (keep the old focus)
this.select(item, {
focus: false
});
}
}, true));
}
this._selectOne(item);
},
// override `_initHook`
_initHook: function() {
if (this.extSelectable()) {
this._selectableInit();
}
// call the parent
this._super();
},
// override `_itemHook`
_itemHook: function(parent, item, itemData, level) {
if (this.extSelectable() && itemData.selected) {
this._selectableDOM.select(item, true);
}
// call the parent
this._super(parent, item, itemData, level);
},
// low level DOM functions
_selectableDOM: {
// (de)select one or more items
select: function(items, state) {
if (state) {
domApi.addListClass(items.toArray(), 'aciTreeSelected', function(node) {
node.firstChild.setAttribute('aria-selected', true);
});
} else {
domApi.removeListClass(items.toArray(), 'aciTreeSelected', function(node) {
node.firstChild.setAttribute('aria-selected', false);
});
}
},
// focus one item, unfocus one or more items
focus: function(items, state) {
if (state) {
domApi.addClass(items[0], 'aciTreeFocus');
items[0].firstChild.focus();
} else {
domApi.removeListClass(items.toArray(), 'aciTreeFocus');
}
}
},
// make element (un)selectable
_selectable: function(state) {
if (state) {
this._instance.jQuery.css({
'-webkit-user-select': 'text',
'-moz-user-select': 'text',
'-ms-user-select': 'text',
'-o-user-select': 'text',
'user-select': 'text'
}).attr({
'unselectable': null,
'onselectstart': null
}).unbind('selectstart' + this._private.nameSpace);
} else {
this._instance.jQuery.css({
'-webkit-user-select': 'none',
'-moz-user-select': '-moz-none',
'-ms-user-select': 'none',
'-o-user-select': 'none',
'user-select': 'none'
}).attr({
'unselectable': 'on',
'onselectstart': 'return false'
}).bind('selectstart' + this._private.nameSpace, function(e) {
if (!$(e.target).is('input,textarea')) {
return false;
}
});
}
},
// get first visible item
_first: function() {
return $(domApi.first(this._instance.jQuery[0], function(node) {
return this.hasClass(node, 'aciTreeVisible') ? true : null;
}));
},
// get last visible item
_last: function() {
return $(domApi.last(this._instance.jQuery[0], function(node) {
return this.hasClass(node, 'aciTreeVisible') ? true : null;
}));
},
// get previous visible starting with item
_prev: function(item) {
return $(domApi.prevAll(item[0], function(node) {
return this.hasClass(node, 'aciTreeVisible') ? true : null;
}));
},
// get next visible starting with item
_next: function(item) {
return $(domApi.nextAll(item[0], function(node) {
return this.hasClass(node, 'aciTreeVisible') ? true : null;
}));
},
// get previous page starting with item
_prevPage: function(item) {
var space = this._instance.jQuery.height();
var now = item[0].firstChild.offsetHeight;
var prev = item, last = $();
while (now < space) {
prev = this._prev(prev);
if (prev[0]) {
now += prev[0].firstChild.offsetHeight;
last = prev;
} else {
break;
}
}
return last;
},
// get next page starting with item
_nextPage: function(item) {
var space = this._instance.jQuery.height();
var now = item[0].firstChild.offsetHeight;
var next = item, last = $();
while (now < space) {
next = this._next(next);
if (next[0]) {
now += next[0].firstChild.offsetHeight;
last = next;
} else {
break;
}
}
return last;
},
// select one item
_selectOne: function(item) {
if (this.isSelected(item)) {
this._focusOne(item);
} else {
if (this.isEnabled(item)) {
// select the item
this.select(item);
} else {
this._focusOne(item);
}
}
},
// unselect the items
_unselect: function(items) {
items.each(this.proxy(function(element) {
this.deselect($(element));
}, true));
},
// focus one item
_focusOne: function(item) {
if (!this._instance.options.multiSelectable) {
this._unselect(this.selected().not(item));
}
if (!this.isFocused(item)) {
this.focus(item);
}
},
// select item
// `options.focus` when set to FALSE will not set the focus
// `options.oldSelected` will keep the old selected items
select: function(item, options) {
options = this._options(options, 'selected', 'selectfail', 'wasselected', item);
if (this.extSelectable() && this.isItem(item)) {
// a way to cancel the operation
if (!this._trigger(item, 'beforeselect', options)) {
this._fail(item, options);
return;
}
// keep the old ones
options.oldSelected = this.selected();
if (!this._instance.options.multiSelectable) {
// deselect all other
var unselect = options.oldSelected.not(item);
this._selectableDOM.select(unselect, false);
unselect.each(this.proxy(function(element) {
this._trigger($(element), 'deselected', options);
}, true));
}
if (this.isSelected(item)) {
this._notify(item, options);
} else {
this._selectableDOM.select(item, true);
this._success(item, options);
}
// process focus
if ((options.focus === undefined) || options.focus) {
if (!this.isFocused(item) || options.focus) {
this.focus(item, this._inner(options));
}
}
} else {
this._fail(item, options);
}
},
// deselect item
deselect: function(item, options) {
options = this._options(options, 'deselected', 'deselectfail', 'notselected', item);
if (this.extSelectable() && this.isItem(item)) {
// a way to cancel the operation
if (!this._trigger(item, 'beforedeselect', options)) {
this._fail(item, options);
return;
}
if (this.isSelected(item)) {
this._selectableDOM.select(item, false);
this._success(item, options);
} else {
this._notify(item, options);
}
} else {
this._fail(item, options);
}
},
// set `virtual` focus
// `options.oldFocused` will keep the old focused item
focus: function(item, options) {
options = this._options(options, 'focus', 'focusfail', 'wasfocused', item);
if (this.extSelectable() && this.isItem(item)) {
// a way to cancel the operation
if (!this._trigger(item, 'beforefocus', options)) {
this._fail(item, options);
return;
}
// keep the old ones
options.oldFocused = this.focused();
// blur all other
var unfocus = options.oldFocused.not(item);
this._selectableDOM.focus(unfocus, false);
// unfocus all others
unfocus.each(this.proxy(function(element) {
this._trigger($(element), 'blur', options);
}, true));
if (this.isFocused(item)) {
this._notify(item, options);
} else {
this._selectableDOM.focus(item, true);
this._success(item, options);
}
} else {
this._fail(item, options);
}
},
// remove `virtual` focus
blur: function(item, options) {
options = this._options(options, 'blur', 'blurfail', 'notfocused', item);
if (this.extSelectable() && this.isItem(item)) {
// a way to cancel the operation
if (!this._trigger(item, 'beforeblur', options)) {
this._fail(item, options);
return;
}
if (this.isFocused(item)) {
this._selectableDOM.focus(item, false);
this._success(item, options);
} else {
this._notify(item, options);
}
} else {
this._fail(item, options);
}
},
// get selected items
selected: function() {
return this._instance.jQuery.find('.aciTreeSelected');
},
// override `_serialize`
_serialize: function(item, callback) {
// call the parent
var data = this._super(item, callback);
if (data && this.extSelectable()) {
if (data.hasOwnProperty('selected')) {
data.selected = this.isSelected(item);
} else if (this.isSelected(item)) {
data.selected = true;
}
}
return data;
},
// test if item is selected
isSelected: function(item) {
return item && domApi.hasClass(item[0], 'aciTreeSelected');
},
// return the focused item
focused: function() {
return this._instance.jQuery.find('.aciTreeFocus');
},
// test if item is focused
isFocused: function(item) {
return item && domApi.hasClass(item[0], 'aciTreeFocus');
},
// test if selectable is enabled
extSelectable: function() {
return this._instance.options.selectable;
},
// override set `option`
option: function(option, value) {
if (this.wasInit() && !this.isLocked()) {
if ((option == 'selectable') && (value != this.extSelectable())) {
if (value) {
this._selectableInit();
} else {
this._selectableDone();
}
}
if ((option == 'multiSelectable') && (value != this._instance.options.multiSelectable)) {
this._multiSelectable(value);
}
if ((option == 'fullRow') && (value != this._instance.options.fullRow)) {
this._fullRow(value);
}
if ((option == 'textSelection') && (value != this._instance.options.textSelection)) {
this._selectable(value);
}
}
// call the parent
this._super(option, value);
},
// done selectable
_selectableDone: function(destroy) {
if (this._instance.jQuery.attr('tabindex') == 0) {
this._instance.jQuery.removeAttr('tabindex');
}
if (!this._instance.options.textSelection) {
this._selectable(true);
}
this._instance.jQuery.unbind(this._private.nameSpace);
this._instance.jQuery.off(this._private.nameSpace, '.aciTreeLine,.aciTreeItem').off(this._private.nameSpace, '.aciTreeItem');
domApi.removeClass(this._instance.jQuery[0], ['aciTreeFocus', 'aciTreeFullRow']);
this._instance.jQuery.removeAttr('aria-multiselectable');
this._instance.focus = false;
this._private.spinPoint = null;
if (!destroy) {
// remove selection
this._unselect(this.selected());
var focused = this.focused();
if (focused.length) {
this.blur(focused);
}
}
},
// override `_destroyHook`
_destroyHook: function(unloaded) {
if (unloaded) {
this._selectableDone(true);
}
// call the parent
this._super(unloaded);
}
};
// extend the base aciTree class and add the selectable stuff
aciPluginClass.plugins.aciTree = aciPluginClass.plugins.aciTree.extend(aciTree_selectable, 'aciTreeSelectable');
// add extra default options
aciPluginClass.defaults('aciTree', options);
// for internal access
var domApi = aciPluginClass.plugins.aciTree_dom;
})(jQuery, this);

View File

@ -1,339 +0,0 @@
/*
* aciTree jQuery Plugin v4.5.0-rc.7
* http://acoderinsights.ro
*
* Copyright (c) 2014 Dragos Ursu
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Require jQuery Library >= v1.9.0 http://jquery.com
* + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin
*/
/*
* This extension adds the possibility to sort the tree items.
* Require aciSortable https://github.com/dragosu/jquery-aciSortable and the utils extension for reordering items.
*/
(function($, window, undefined) {
// extra default options
var options = {
sortable: false, // if TRUE then the tree items can be sorted
sortDelay: 750, // how many [ms] before opening a inode on hovering when in drag
// called by the `aciSortable` inside the `drag` callback
sortDrag: function(item, placeholder, isValid, helper) {
if (!isValid) {
var move = this.getLabel(item);
if (this._private.dragDrop && (this._private.dragDrop.length > 1)) {
move += ' and #' + (this._private.dragDrop.length - 1) + ' more';
}
helper.html(move);
}
},
// called by the `aciSortable` inside the `valid` callback
sortValid: function(item, hover, before, isContainer, placeholder, helper) {
var move = this.getLabel(item);
if (this._private.dragDrop.length > 1) {
move += ' and #' + (this._private.dragDrop.length - 1) + ' more';
}
if (isContainer) {
helper.html('move ' + move + ' to ' + this.getLabel(this.itemFrom(hover)));
placeholder.removeClass('aciTreeAfter aciTreeBefore');
} else if (before !== null) {
if (before) {
helper.html('move ' + move + ' before ' + this.getLabel(hover));
placeholder.removeClass('aciTreeAfter').addClass('aciTreeBefore');
} else {
helper.html('move ' + move + ' after ' + this.getLabel(hover));
placeholder.removeClass('aciTreeBefore').addClass('aciTreeAfter');
}
}
}
};
// aciTree sortable extension
var aciTree_sortable = {
__extend: function() {
// add extra data
$.extend(this._private, {
openTimeout: null,
dragDrop: null // the items used in drag & drop
});
// call the parent
this._super();
},
// init sortable
_sortableInit: function() {
this._instance.jQuery.aciSortable({
container: '.aciTreeUl',
item: '.aciTreeLi',
child: 50,
childHolder: '<ul class="aciTreeUl aciTreeChild"></ul>',
childHolderSelector: '.aciTreeChild',
placeholder: '<li class="aciTreeLi aciTreePlaceholder"><div></div></li>',
placeholderSelector: '.aciTreePlaceholder',
helper: '<div class="aciTreeHelper"></div>',
helperSelector: '.aciTreeHelper',
// just before drag start
before: this.proxy(function(item) {
// init before drag
if (!this._initDrag(item)) {
return false;
}
// a way to cancel the operation
if (!this._trigger(item, 'beforedrag')) {
this._trigger(item, 'dragfail');
return false;
}
return true;
}),
// just after drag start, before dragging
start: this.proxy(function(item, placeholder, helper) {
this._instance.jQuery.addClass('aciTreeDragDrop');
helper.stop(true).css('opacity', 1);
}),
// when in drag
drag: this.proxy(function(item, placeholder, isValid, helper) {
if (!isValid) {
window.clearTimeout(this._private.openTimeout);
}
if (this._instance.options.sortDrag) {
this._instance.options.sortDrag.apply(this, arguments);
}
}),
// to check the drop target (when the placeholder is repositioned)
valid: this.proxy(function(item, hover, before, isContainer, placeholder, helper) {
window.clearTimeout(this._private.openTimeout);
if (!this._checkDrop(item, hover, before, isContainer, placeholder, helper)) {
return false;
}
var options = this._options({
hover: hover,
before: before,
isContainer: isContainer,
placeholder: placeholder,
helper: helper
});
// a way to cancel the operation
if (!this._trigger(item, 'checkdrop', options)) {
return false;
}
if (this.isInode(hover) && !this.isOpen(hover)) {
this._private.openTimeout = window.setTimeout(this.proxy(function() {
this.open(hover);
}), this._instance.options.sortDelay);
}
if (this._instance.options.sortValid) {
this._instance.options.sortValid.apply(this, arguments);
}
return true;
}),
// when dragged as child
create: this.proxy(function(api, item, hover) {
if (this.isLeaf(hover)) {
hover.append(api._instance.options.childHolder);
return true;
}
return false;
}, true),
// on drag end
end: this.proxy(function(item, hover, placeholder, helper) {
window.clearTimeout(this._private.openTimeout);
var options = {
placeholder: placeholder,
helper: helper
};
options = this._options(options, 'sorted', 'dropfail', null, item);
if (placeholder.parent().length) {
var prev = this.prev(placeholder, true);
if (prev.length) {
// add after a item
placeholder.detach();
var items = $(this._private.dragDrop.get().reverse());
this._private.dragDrop = null;
items.each(this.proxy(function(element) {
this.moveAfter($(element), this._inner(options, {
success: options.success,
fail: options.fail,
after: prev
}));
}, true));
} else {
var next = this.next(placeholder, true);
if (next.length) {
// add before a item
placeholder.detach();
var items = $(this._private.dragDrop.get().reverse());
this._private.dragDrop = null;
items.each(this.proxy(function(element) {
this.moveBefore($(element), this._inner(options, {
success: options.success,
fail: options.fail,
before: next
}));
}, true));
} else {
// add as a child
var parent = this.parent(placeholder);
var container = placeholder.parent();
placeholder.detach();
container.remove();
if (this.isLeaf(parent)) {
// we can set asChild only for leaves
var items = this._private.dragDrop;
this.asChild(items.eq(0), this._inner(options, {
success: function() {
this._success(item, options);
this.open(parent);
items.filter(':gt(0)').each(this.proxy(function(element) {
this.moveAfter($(element), this._inner(options, {
success: options.success,
fail: options.fail,
after: this.last(parent)
}));
}, true));
},
fail: options.fail,
parent: parent
}));
} else {
this._fail(item, options);
}
}
}
} else {
this._fail(item, options);
}
this._private.dragDrop = null;
if (helper.parent().length) {
// the helper is inserted in the DOM
var top = $(window).scrollTop();
var left = $(window).scrollLeft();
var rect = item[0].getBoundingClientRect();
// animate helper to item position
helper.animate({
top: rect.top + top,
left: rect.left + left,
opacity: 0
},
{
complete: function() {
// detach the helper when completed
helper.detach();
}
});
}
this._instance.jQuery.removeClass('aciTreeDragDrop');
})
});
},
// override `_initHook`
_initHook: function() {
if (this.extSortable()) {
this._sortableInit();
}
// call the parent
this._super();
},
// reduce items by removing the childrens
_parents: function(items) {
var len = items.length, a, b, remove = [];
for (var i = 0; i < len - 1; i++) {
a = items.eq(i);
for (var j = i + 1; j < len; j++) {
b = items.eq(j);
if (this.isChildren(a, b)) {
remove.push(items[j]);
} else if (this.isChildren(b, a)) {
remove.push(items[i]);
}
}
}
return items.not(remove);
},
// called before drag start
_initDrag: function(item) {
// support `selectable` extension
if (this.extSelectable && this.extSelectable()) {
if (!this.hasFocus()) {
this._instance.jQuery.focus();
}
if (!this.isEnabled(item)) {
return false;
}
var drag = this.selected();
if (drag.length) {
if (!this.isSelected(item)) {
return false;
}
} else {
drag = item;
}
this._private.dragDrop = this._parents(drag);
} else {
this._instance.jQuery.focus();
this._private.dragDrop = item;
}
return true;
},
// check the drop target
_checkDrop: function(item, hover, before, isContainer, placeholder, helper) {
var items = this._private.dragDrop;
if (!items) {
return false;
}
var test = this.itemFrom(hover);
if (items.is(test) || items.has(test[0]).length) {
return false;
}
if (!isContainer) {
test = before ? this.prev(hover) : this.next(hover);
if (items.is(test)) {
return false;
}
}
return true;
},
// test if sortable is enabled
extSortable: function() {
return this._instance.options.sortable;
},
// override set `option`
option: function(option, value) {
if (this.wasInit() && !this.isLocked()) {
if ((option == 'sortable') && (value != this.extSortable())) {
if (value) {
this._sortableInit();
} else {
this._sortableDone();
}
}
}
// call the parent
this._super(option, value);
},
// done sortable
_sortableDone: function() {
this._instance.jQuery.unbind(this._private.nameSpace);
this._instance.jQuery.aciSortable('destroy');
},
// override `_destroyHook`
_destroyHook: function(unloaded) {
if (unloaded) {
this._sortableDone();
}
// call the parent
this._super(unloaded);
}
};
// extend the base aciTree class and add the sortable stuff
aciPluginClass.plugins.aciTree = aciPluginClass.plugins.aciTree.extend(aciTree_sortable, 'aciTreeSortable');
// add extra default options
aciPluginClass.defaults('aciTree', options);
})(jQuery, this);

View File

@ -1,746 +0,0 @@
/*
* aciTree jQuery Plugin v4.5.0-rc.7
* http://acoderinsights.ro
*
* Copyright (c) 2014 Dragos Ursu
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Require jQuery Library >= v1.9.0 http://jquery.com
* + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin
*/
/*
* A few utility functions for aciTree.
*/
(function($, window, undefined) {
// extra default options
var options = {
// called when items need to be filtered, for each tree item
// return TRUE/FALSE to include/exclude items on filtering
filterHook: function(item, search, regexp) {
return search.length ? regexp.test(window.String(this.getLabel(item))) : true;
}
};
// aciTree utils extension
// adds item update option, branch processing, moving items & item swapping, item search by ID
var aciTree_utils = {
__extend: function() {
// add extra data
$.extend(this._instance, {
filter: new this._queue(this, this._instance.options.queue)
});
// stop queue until needed
this._instance.filter.destroy();
// call the parent
this._super();
},
// call the `callback` function (item) for each children of item
// when `load` is TRUE will also try to load nodes
branch: function(item, callback, load) {
var queue = this._instance.queue;
var process = this.proxy(function(item, callback, next) {
var child = next ? this.next(item) : this.first(item);
if (child.length) {
if (this.isInode(child)) {
if (this.wasLoad(child)) {
queue.push(function(complete) {
callback.call(this, child);
process(child, callback);
process(child, callback, true);
complete();
});
} else if (load) {
// load the item first
this.ajaxLoad(child, {
success: function() {
callback.call(this, child);
process(child, callback);
process(child, callback, true);
},
fail: function() {
process(child, callback, true);
}
});
} else {
queue.push(function(complete) {
callback.call(this, child);
process(child, callback, true);
complete();
});
}
} else {
queue.push(function(complete) {
callback.call(this, child);
process(child, callback, true);
complete();
});
}
}
});
process(item, callback);
},
// swap two items (they can't be parent & children)
// `options.item1` & `options.item2` are the swapped items
swap: function(options) {
options = this._options(options, null, 'swapfail', null, null);
var item1 = options.item1;
var item2 = options.item2;
if (this.isItem(item1) && this.isItem(item2) && !this.isChildren(item1, item2) && !this.isChildren(item2, item1) && (item1[0] != item2[0])) {
// a way to cancel the operation
if (!this._trigger(null, 'beforeswap', options)) {
this._fail(null, options);
return;
}
var prev = this.prev(item1);
if (prev.length) {
if (item2[0] == prev[0]) {
item2.before(item1);
} else {
item1.insertAfter(item2);
item2.insertAfter(prev);
}
} else {
var next = this.next(item1);
if (next.length) {
if (item2[0] == next[0]) {
item2.after(item1);
} else {
item1.insertAfter(item2);
item2.insertBefore(next);
}
} else {
var parent = item1.parent();
item1.insertAfter(item2);
parent.append(item2);
}
}
// update item states
this._updateLevel(item1);
var parent = this.parent(item1);
this._setFirstLast(parent.length ? parent : null, item1);
this._updateHidden(item1);
this._updateLevel(item2);
parent = this.parent(item2);
this._setFirstLast(parent.length ? parent : null, item2);
this._updateHidden(item2);
this._setOddEven(item1.add(item2));
this._trigger(null, 'swapped', options);
this._success(null, options);
} else {
this._fail(null, options);
}
},
// update item level
_updateItemLevel: function(item, fromLevel, toLevel) {
domApi.addRemoveClass(item[0], 'aciTreeLevel' + toLevel, 'aciTreeLevel' + fromLevel);
var line = item[0].firstChild;
line.setAttribute('aria-level', toLevel + 1);
var entry = domApi.childrenByClass(line, 'aciTreeEntry');
if (fromLevel < toLevel) {
line = entry.parentNode;
var branch;
for (var i = fromLevel; i < toLevel; i++) {
branch = window.document.createElement('DIV');
line.appendChild(branch);
branch.className = 'aciTreeBranch aciTreeLevel' + i;
line = branch;
}
line.appendChild(entry);
} else {
var branch = entry;
for (var i = toLevel; i <= fromLevel; i++) {
branch = branch.parentNode;
}
branch.removeChild(branch.firstChild);
branch.appendChild(entry);
}
},
// update child level
_updateChildLevel: function(item, fromLevel, toLevel) {
this.children(item, false, true).each(this.proxy(function(element) {
var item = $(element);
this._updateItemLevel(item, fromLevel, toLevel);
if (this.isInode(item)) {
this._updateChildLevel(item, fromLevel + 1, toLevel + 1);
}
}, true));
},
// update item level
_updateLevel: function(item) {
var level = this.level(item);
var found = window.parseInt(item.attr('class').match(/aciTreeLevel[0-9]+/)[0].match(/[0-9]+/));
if (level != found) {
this._updateItemLevel(item, found, level);
this._updateChildLevel(item, found + 1, level + 1);
}
},
// move item up
moveUp: function(item, options) {
options = this._options(options);
options.index = window.Math.max(this.getIndex(item) - 1, 0);
this.setIndex(item, options);
},
// move item down
moveDown: function(item, options) {
options = this._options(options);
options.index = window.Math.min(this.getIndex(item) + 1, this.siblings(item).length);
this.setIndex(item, options);
},
// move item in first position
moveFirst: function(item, options) {
options = this._options(options);
options.index = 0;
this.setIndex(item, options);
},
// move item in last position
moveLast: function(item, options) {
options = this._options(options);
options.index = this.siblings(item).length;
this.setIndex(item, options);
},
// move item before another (they can't be parent & children)
// `options.before` is the element before which the item will be moved
moveBefore: function(item, options) {
options = this._options(options, null, 'movefail', 'wasbefore', item);
var before = options.before;
if (this.isItem(item) && this.isItem(before) && !this.isChildren(item, before) && (item[0] != before[0])) {
// a way to cancel the operation
if (!this._trigger(item, 'beforemove', options)) {
this._fail(item, options);
return;
}
if (this.prev(before, true)[0] == item[0]) {
this._notify(item, options);
} else {
var parent = this.parent(item);
var prev = this.prev(item, true);
if (!prev.length) {
prev = parent.length ? parent : this.first();
}
item.insertBefore(before);
if (parent.length && !this.hasChildren(parent, true)) {
this.setLeaf(parent);
}
this._updateLevel(item);
// update item states
this._setFirstLast(parent.length ? parent : null);
parent = this.parent(item);
this._setFirstLast(parent.length ? parent : null, item.add(before));
this._updateHidden(item);
this._setOddEven(item.add(before).add(prev));
this._trigger(item, 'moved', options);
this._success(item, options);
}
} else {
this._fail(item, options);
}
},
// move item after another (they can't be parent & children)
// `options.after` is the element after which the item will be moved
moveAfter: function(item, options) {
options = this._options(options, null, 'movefail', 'wasafter', item);
var after = options.after;
if (this.isItem(item) && this.isItem(after) && !this.isChildren(item, after) && (item[0] != after[0])) {
// a way to cancel the operation
if (!this._trigger(item, 'beforemove', options)) {
this._fail(item, options);
return;
}
if (this.next(after, true)[0] == item[0]) {
this._notify(item, options);
} else {
var parent = this.parent(item);
var prev = this.prev(item, true);
if (!prev.length) {
prev = parent.length ? parent : this.first();
}
item.insertAfter(after);
if (parent.length && !this.hasChildren(parent, true)) {
this.setLeaf(parent);
}
this._updateLevel(item);
this._setFirstLast(parent.length ? parent : null);
parent = this.parent(item);
this._setFirstLast(parent.length ? parent : null, item.add(after));
this._updateHidden(item);
this._setOddEven(item.add(after).add(prev));
this._trigger(item, 'moved', options);
this._success(item, options);
}
} else {
this._fail(item, options);
}
},
// move item to be a child of another (they can't be parent & children and the targeted parent item must be empty)
// `options.parent` is the parent element on which the item will be added
asChild: function(item, options) {
options = this._options(options, null, 'childfail', null, item);
var parent = options.parent;
if (this.isItem(item) && this.isItem(parent) && !this.isChildren(item, parent) && !this.hasChildren(parent, true) && (item[0] != parent[0])) {
// a way to cancel the operation
if (!this._trigger(item, 'beforechild', options)) {
this._fail(item, options);
return;
}
var process = function() {
var oldParent = this.parent(item);
var prev = this.prev(item);
if (!prev.length) {
prev = oldParent.length ? oldParent : this.first();
}
var container = this._createContainer(parent);
container.append(item);
if (oldParent.length && !this.hasChildren(oldParent, true)) {
// no more children
this.setLeaf(oldParent);
}
// update item states
this._updateLevel(item);
this._setFirstLast(oldParent.length ? oldParent : null);
this._setFirstLast(parent.length ? parent : null, item);
this._updateHidden(item);
this._setOddEven(item.add(prev));
this._trigger(item, 'childset', options);
this._success(item, options);
};
if (this.isInode(parent)) {
process.apply(this);
} else {
// set as inode first
this.setInode(parent, this._inner(options, {
success: process,
fail: options.fail
}));
}
} else {
this._fail(item, options);
}
},
// search a `path` ID from a parent
_search: function(parent, pathId) {
var items = this.children(parent);
var item, id, length, found, exact = false;
for (var i = 0, size = items.length; i < size; i++) {
item = items.eq(i);
id = window.String(this.getId(item));
length = id.length;
if (length) {
if (id == pathId.substr(0, length)) {
found = item;
exact = pathId.length == length;
break;
}
}
}
if (found) {
if (!exact) {
// try to search children
var child = this._search(found, pathId);
if (child) {
return child;
}
}
return {
item: found,
exact: exact
};
} else {
return null;
}
},
// search items by ID
// `options.id` is the ID to search for
// if `path` is TRUE then the search will be more optimized
// and reduced to the first branch that matches the ID
// but the ID must be set like a path otherwise will not work
// if `load` is TRUE will also try to load nodes (works only when `path` is TRUE)
searchId: function(path, load, options) {
options = this._options(options);
var id = options.id;
if (path) {
if (load) {
var process = this.proxy(function(item) {
var found = this._search(item, id);
if (found) {
if (found.exact) {
this._success(found.item, options);
} else {
if (this.wasLoad(found.item)) {
this._fail(item, options);
} else {
// load the item
this.ajaxLoad(found.item, this._inner(options, {
success: function() {
process(found.item);
},
fail: options.fail
}));
}
}
} else {
this._fail(item, options);
}
});
process();
} else {
var found = this._search(null, id);
if (found && found.exact) {
this._success(found.item, options);
} else {
this._fail(null, options);
}
}
} else {
var found = $();
this._instance.jQuery.find('.aciTreeLi').each(this.proxy(function(element) {
if (id == this.getId($(element))) {
found = $(element);
return false;
}
}, true));
if (found.length) {
this._success(found, options);
} else {
this._fail(null, options);
}
}
},
// search nodes by ID or custom property starting from item
// `options.search` is the value to be searched
// `options.load` if TRUE will try to load nodes
// `options.callback` function (item, search) return TRUE for the custom match
// `options.results` will keep the search results
search: function(item, options) {
var results = [];
options = this._options(options);
var task = new this._task(new this._queue(this, this._instance.options.queue), function(complete) {
// run this at the end
if (results.length) {
options.results = $(results);
this._success($(results[0]), options);
} else {
this._fail(item, options);
}
complete();
});
var children = this.proxy(function(item) {
this.children(item, false, true).each(this.proxy(function(element) {
if (options.callback) {
// custom search
var match = options.callback.call(this, $(element), options.search);
if (match) {
results.push(element);
} else if (match === null) {
// skip childrens
return;
}
} else if (this.getId($(element)) == options.search) {
// default ID match
results.push(element);
}
if (this.isInode($(element))) {
// process children
task.push(function(complete) {
search($(element));
complete();
});
}
}, true));
});
var search = this.proxy(function(item) {
if (this.wasLoad(item)) {
// process children
task.push(function(complete) {
children(item);
complete();
});
} else if (options.load) {
task.push(function(complete) {
// load the item first
this.ajaxLoad(item, {
success: function() {
children(item);
complete();
},
fail: complete
});
});
}
});
// run the search
task.push(function(complete) {
search(item);
complete();
});
},
// search node by a list of IDs starting from item
// `options.path` is a list of IDs to be searched - the path to the node
// `options.load` if TRUE will try to load nodes
searchPath: function(item, options) {
options = this._options(options);
var path = options.path;
var search = this.proxy(function(item, id) {
this.search(item, {
success: function(item) {
if (path.length) {
search(item, path.shift());
} else {
this._success(item, options);
}
},
fail: function() {
this._fail(item, options);
},
search: id,
load: options.load,
callback: function(item, search) {
// prevent drill-down
return (this.getId(item) == search) ? true : null;
}
});
});
search(item, path.shift());
},
// get item path IDs starting from the top parent (ROOT)
// when `reverse` is TRUE returns the IDs in reverse order
pathId: function(item, reverse) {
var path = this.path(item, reverse), id = [];
path.each(this.proxy(function(element) {
id.push(this.getId($(element)));
}, true));
return id;
},
// escape string and return RegExp
_regexp: function(search) {
return new window.RegExp(window.String(search).replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').replace(/\x08/g, '\\x08'), 'i');
},
// filter the tree items based on search criteria
// `options.search` is the keyword
// `options.first` will be the first matched item (if any)
filter: function(item, options) {
options = this._options(options, null, 'filterfail', null, item);
if (!item || this.isItem(item)) {
// a way to cancel the operation
if (!this._trigger(item, 'beforefilter', options)) {
this._fail(item, options);
return;
}
var search = window.String(options.search);
var regexp = this._regexp(search);
var first = null;
this._instance.filter.init();
var task = new this._task(this._instance.filter, function(complete) {
// run this at the end
this._instance.filter.destroy();
options.first = first;
this._setOddEven();
this._trigger(item, 'filtered', options);
this._success(item, options);
complete();
});
// process children
var process = this.proxy(function(parent) {
var children = this.children(parent, false, true);
var found = false;
children.each(this.proxy(function(element) {
var item = $(element);
if (this._instance.options.filterHook.call(this, item, search, regexp)) {
if (!first) {
first = item;
}
found = true;
domApi.removeClass(item[0], 'aciTreeHidden');
} else {
domApi.addRemoveClass(item[0], 'aciTreeHidden', 'aciTreeVisible');
}
if (this.isInode(item)) {
// continue with the children
task.push(function(complete) {
process(item);
complete();
});
}
}, true));
if (found) {
// update item states
if (parent && this.isHidden(parent)) {
this._showHidden(parent);
}
if (!parent || (this.isOpenPath(parent) && this.isOpen(parent))) {
children.not('.aciTreeHidden').addClass('aciTreeVisible');
}
this._setFirstLast(parent, this._getFirstLast(parent));
}
});
task.push(function(complete) {
process(item);
complete();
});
} else {
this._fail(item, options);
}
},
// call the `callback` function (item) for the first item
_firstAll: function(callback) {
callback.call(this, this.first());
},
// call the `callback` function (item) for the last item
// when `load` is TRUE will also try to load nodes
_lastAll: function(item, callback, load) {
if (item) {
if (this.isInode(item)) {
if (this.wasLoad(item)) {
this._lastAll(this.last(item), callback, load);
return;
} else if (load) {
this.ajaxLoad(item, {
success: function() {
this._lastAll(this.last(item), callback, load);
},
fail: function() {
callback.call(this, item);
}
});
return;
}
}
callback.call(this, item);
} else {
callback.call(this, this.last());
}
},
// call the `callback` function (item) for the next item from tree
// when `load` is TRUE will also try to load nodes
_nextAll: function(item, callback, load) {
if (item) {
if (this.isInode(item)) {
if (this.wasLoad(item)) {
callback.call(this, this.first(item));
return;
} else if (load) {
this.ajaxLoad(item, {
success: function() {
callback.call(this, this.first(item));
},
fail: function() {
this._nextAll(item, callback, load);
}
});
return;
}
}
var next = this.next(item);
if (next.length) {
callback.call(this, next);
} else {
// search next by parents
var search = this.proxy(function(item) {
var parent = this.parent(item);
if (parent.length) {
var next = this.next(parent);
if (next.length) {
return next;
} else {
return search(parent);
}
}
return null;
});
callback.call(this, search(item));
}
} else {
callback.call(this, this.first());
}
},
// call the `callback` function (item) for the previous item from tree
// when `load` is TRUE will also try to load nodes
_prevAll: function(item, callback, load) {
if (item) {
var prev = this.prev(item);
if (prev.length) {
if (this.isInode(prev)) {
this._lastAll(prev, callback, load);
} else {
callback.call(this, prev);
}
} else {
var parent = this.parent(item);
callback.call(this, parent.length ? parent : null);
}
} else {
callback.call(this, this.last());
}
},
// call the `callback` function (item) with the previous found item based on search criteria
// `search` is the keyword
prevMatch: function(item, search, callback) {
var regexp = this._regexp(search);
this._instance.filter.init();
var task = new this._task(this._instance.filter, function(complete) {
this._instance.filter.destroy();
complete();
});
var process = function(item) {
task.push(function(complete) {
this._prevAll(item, function(item) {
if (item) {
if (this._instance.options.filterHook.call(this, item, search, regexp)) {
callback.call(this, item);
} else {
process(item);
}
} else {
callback.call(this, null);
}
complete();
});
});
};
process(this.isItem(item) ? item : null);
},
// call the `callback` function (item) with the next found item based on search criteria
// `search` is the keyword
nextMatch: function(item, search, callback) {
var regexp = this._regexp(search);
this._instance.filter.init();
var task = new this._task(this._instance.filter, function(complete) {
this._instance.filter.destroy();
complete();
});
var process = function(item) {
task.push(function(complete) {
this._nextAll(item, function(item) {
if (item) {
if (this._instance.options.filterHook.call(this, item, search, regexp)) {
callback.call(this, item);
} else {
process(item);
}
} else {
callback.call(this, null);
}
complete();
});
});
};
process(this.isItem(item) ? item : null);
}
};
// extend the base aciTree class and add the utils stuff
aciPluginClass.plugins.aciTree = aciPluginClass.plugins.aciTree.extend(aciTree_utils, 'aciTreeUtils');
// add extra default options
aciPluginClass.defaults('aciTree', options);
// for internal access
var domApi = aciPluginClass.plugins.aciTree_dom;
})(jQuery, this);

View File

@ -3,9 +3,8 @@
{% block init_script %}
try {
require(
['pgadmin', 'pgadmin.browser'],
function(pgAdmin, pgBrowser) {
pgBrowser.init();
['sources/generated/app.bundle'],
function() {
},
function() {
/* TODO:: Show proper error dialog */
@ -30,7 +29,13 @@ require.onResourceLoad = function (context, map, depMaps) {
// is not loading anything hide the indicator and exit
setTimeout(function() {
if (panel != null) {
$(panel).remove();
try{
$(panel).remove();
}
catch(e){
panel.outerHTML = "";
delete panel;
}
return;
}
}, 500);
@ -61,6 +66,18 @@ require.onResourceLoad = function (context, map, depMaps) {
}, 400)
}
};
window.onload = function(e){
setTimeout(function() {
var gravatarImg = '<img src="{{ username | gravatar }}" width="18" height="18" alt="Gravatar image for {{ username }}"> {{ username }} <span class="caret"></span>';
//$('#navbar-menu .navbar-right > li > a').html(gravatarImg);
var navbarRight = document.getElementById("navbar-menu").getElementsByClassName("navbar-right")[0];
if (navbarRight) {
var list = navbarRight.getElementsByTagName("LI")[0];
list.getElementsByTagName("a")[0].innerHTML = gravatarImg;
}
}, 1000);
};
{% endblock %}
{% block body %}
<style>
@ -151,9 +168,7 @@ require.onResourceLoad = function (context, map, depMaps) {
{% if config.SERVER_MODE %}
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><img
src="{{ username | gravatar }}" width="18" height="18"
alt="Gravatar image for {{ username }}"> {{ username }} <span class="caret"></span></a>
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"></a>
<ul class="dropdown-menu navbar-inverse">
<li><a href="{{ url_for('security.change_password') }}">{{ _('Change Password') }}</a></li>
<li class="divider"></li>

View File

@ -1,17 +1,16 @@
define(
'pgadmin.browser', [
'sources/gettext', 'sources/url_for', 'require', 'jquery', 'underscore', 'underscore.string',
'bootstrap', 'pgadmin', 'alertify', 'codemirror',
'sources/check_node_visibility', 'codemirror/mode/sql/sql', 'wcdocker',
'bootstrap', 'pgadmin', 'alertify', 'bundled_codemirror',
'sources/check_node_visibility', 'pgadmin.browser.utils', 'wcdocker',
'jquery.contextmenu', 'jquery.aciplugin', 'jquery.acitree',
'pgadmin.alertifyjs', 'pgadmin.browser.messages',
'pgadmin.browser.menu', 'pgadmin.browser.panel',
'pgadmin.browser.error', 'pgadmin.browser.frame',
'pgadmin.browser.node', 'pgadmin.browser.collection',
'codemirror/addon/edit/matchbrackets', 'codemirror/addon/edit/closebrackets'
'pgadmin.browser.node', 'pgadmin.browser.collection'
], function(
gettext, url_for, require, $, _, S, Bootstrap, pgAdmin, Alertify,
CodeMirror, checkNodeVisibility
codemirror, checkNodeVisibility
) {
// Some scripts do export their object in the window only.
@ -19,8 +18,10 @@ define(
var wcDocker = window.wcDocker;
$ = $ || window.jQuery || window.$;
Bootstrap = Bootstrap || window.Bootstrap;
var CodeMirror = codemirror.default;
var pgBrowser = pgAdmin.Browser = pgAdmin.Browser || {};
var select_object_msg = gettext('Please select an object in the tree view.');
var panelEvents = {};
panelEvents[wcDocker.EVENT.VISIBILITY_CHANGED] = function() {
@ -64,7 +65,7 @@ define(
ajaxHook: function(item, settings) {
if (item != null) {
var d = this.itemData(item);
n = b.Nodes[d._type];
var n = b.Nodes[d._type];
if (n)
settings.url = n.generate_url(item, 'children', d, true);
}
@ -121,7 +122,7 @@ define(
isCloseable: false,
isPrivate: true,
elContainer: true,
content: '<div class="obj_properties"><div class="alert alert-info pg-panel-message">{{ _('Please select an object in the tree view.') }}</div></div>',
content: '<div class="obj_properties"><div class="alert alert-info pg-panel-message">' + select_object_msg + '</div></div>',
events: panelEvents,
onCreate: function(myPanel, $container) {
$container.addClass('pg-no-overflow');
@ -135,7 +136,7 @@ define(
width: 500,
isCloseable: false,
isPrivate: true,
content: '<div><div class="alert alert-info pg-panel-message pg-panel-statistics-message">{{ _('Please select an object in the tree view.') }}</div><div class="pg-panel-statistics-container hidden"></div></div>',
content: '<div><div class="alert alert-info pg-panel-message pg-panel-statistics-message">' + select_object_msg + '</div><div class="pg-panel-statistics-container hidden"></div></div>',
events: panelEvents
}),
// Reversed engineered SQL for the object
@ -156,7 +157,7 @@ define(
width: 500,
isCloseable: false,
isPrivate: true,
content: '<div><div class="alert alert-info pg-panel-message pg-panel-depends-message">{{ _('Please select an object in the tree view.') }}</div><div class="pg-panel-depends-container hidden"></div></div>',
content: '<div><div class="alert alert-info pg-panel-message pg-panel-depends-message">' + select_object_msg + '</div><div class="pg-panel-depends-container hidden"></div></div>',
events: panelEvents
}),
// Dependents of the object
@ -167,38 +168,12 @@ define(
width: 500,
isCloseable: false,
isPrivate: true,
content: '<div><div class="alert alert-info pg-panel-message pg-panel-depends-message">{{ _('Please select an object in the tree view.') }}</div><div class="pg-panel-depends-container hidden"></div></div>',
content: '<div><div class="alert alert-info pg-panel-message pg-panel-depends-message">' + select_object_msg + '</div><div class="pg-panel-depends-container hidden"></div></div>',
events: panelEvents
})/* Add hooked-in panels by extensions */{% for panel_item in current_app.panels %}{% if not panel_item.isIframe %},'{{ panel_item.name }}' : new pgAdmin.Browser.Panel({
name: '{{ panel_item.name }}',
title: '{{ panel_item.title }}',
icon: '{{ panel_item.icon }}',
width: {{ panel_item.width }},
height: {{ panel_item.height }},
showTitle: {% if panel_item.showTitle %}true{% else %}false{% endif %},
isCloseable: {% if panel_item.isCloseable %}true{% else %}false{% endif %},
isPrivate: {% if panel_item.isPrivate %}true{% else %}false{% endif %},
content: '{{ panel_item.content }}',
canHide: {% if panel_item.canHide %}true{% else %}false{% endif %}{% if panel_item.limit is not none %},
limit: {{ panel_item.limit }}{% endif %}{% if panel_item.events is not none %},
events: {{ panel_item.events }} {% endif %}
}){% endif %}{% endfor %}
})
},
// We also support showing dashboards, HTML file, external URL
frames: {
/* Add hooked-in frames by extensions */{% for panel_item in current_app.panels %}{% if panel_item.isIframe %}
'{{ panel_item.name }}' : new pgAdmin.Browser.Frame({
name: '{{ panel_item.name }}',
title: '{{ panel_item.title }}',
icon: '{{ panel_item.icon }}',
width: {{ panel_item.width }},
height: {{ panel_item.height }},
showTitle: {% if panel_item.showTitle %}true{% else %}false{% endif %},
isCloseable: {% if panel_item.isCloseable %}true{% else %}false{% endif %},
isPrivate: {% if panel_item.isPrivate %}true{% else %}false{% endif %},
url: '{{ panel_item.content }}'
}),{% endif %}{% endfor %}
},
frames: {},
/* Menus */
// pgAdmin.Browser.MenuItem.add_menus(...) will register all the menus
// in this container
@ -219,10 +194,44 @@ define(
// Help menus
help: {}
},
add_panels: function() {
/* Add hooked-in panels by extensions */
//debugger;
var panels = JSON.parse(pgBrowser.panels_items);
_.each(panels, function(panel) {
if (panel.isIframe) {
pgBrowser.frames[panel.name] = new pgBrowser.Frame({
name: panel.name,
title: panel.title,
icon: panel.icon,
width: panel.width,
height: panel.height,
showTitle: panel.showTitle,
isCloseable: panel.isCloseable,
isPrivate: panel.isPrivate,
url: panel.content
})
} else {
pgBrowser.panels[panel.name] = new pgBrowser.Panel({
name: panel.name,
title: panel.title,
icon: panel.icon,
width: panel.width,
height: panel.height,
showTitle: panel.showTitle,
isCloseable: panel.isCloseable,
isPrivate: panel.isPrivate,
content: (panel.content) ? panel.content : '',
events: (panel.events) ? panel.events : ''
})
}
});
},
menu_categories: {
/* name, label (pair) */
'create': {
label: '{{ _('Create')|safe }}',
label: gettext('Create'),
priority: 1,
/* separator above this menu */
above: false,
@ -300,9 +309,9 @@ define(
)
} else {
// Create a dummy 'no object seleted' menu
create_submenu = pgAdmin.Browser.MenuGroup(
var create_submenu = pgAdmin.Browser.MenuGroup(
obj.menu_categories['create'], [{
$el: $('<li class="menu-item disabled"><a href="#">{{ _("No object selected") }}</a></li>'),
$el: $('<li class="menu-item disabled"><a href="#">' + gettext("No object selected") + '</a></li>'),
priority: 1,
category: 'create',
update: function() {}
@ -312,8 +321,8 @@ define(
},
save_current_layout: function(obj) {
if(obj.docker) {
state = obj.docker.save();
settings = { setting: "Browser/Layout", value: state };
var state = obj.docker.save();
var settings = { setting: "Browser/Layout", value: state };
$.ajax({
type: 'POST',
url: url_for('settings.store_bulk'),
@ -330,7 +339,7 @@ define(
// Cache preferences
obj.cache_preferences();
this.add_panels();
// Initialize the Docker
obj.docker = new wcDocker(
'#dockerContainer', {
@ -350,7 +359,7 @@ define(
});
// Stored layout in database from the previous session
var layout = '{{ layout }}';
var layout = pgBrowser.utils.layout;
// Try to restore the layout if there is one
if (layout != '') {
@ -445,36 +454,6 @@ define(
*
*/
delete obj.scripts[d._type];
setTimeout(function() {
_.each(scripts, function(s) {
if (!s.loaded) {
require([s.name], function(m) {
s.loaded = true;
// Call the initializer (if present)
if (m && m.init && typeof m.init == 'function') {
try {
m.init();
obj.Events.trigger(
'pgadmin:module:' + s.name + ':initialized', m, obj
);
} catch (err) {
console.log("Error running module init script for '" + s.path + "'");
console.log(err);
obj.report_error(
gettext('Error initializing script - ') + s.path, err);
}
}
}, function() {
console.log("Error loading script - " + s.path);
console.log(arguments);
obj.report_error(
gettext('Error loading script - ') + s.path);
}).bind(s);
}
});
}, 1);
}
}
break;
@ -518,45 +497,9 @@ define(
return true;
});
// There are some scripts which needed to be loaded immediately,
// but - not all. We will will need to generate all the menus only
// after they all were loaded completely.
var counter = {total: 0, loaded: 0};
{% for script in current_app.javascripts %}{% if 'when' in script %}
{% if script.when %}/* Registering '{{ script.path }}.js' to be loaded when a node '{{ script.when }}' is loaded */
this.register_script('{{ script.when }}', '{{ script.name }}', '{{ script.path }}.js');{% else %}/* Loading '{{ script.path }}' */
counter.total += 1;
this.load_module('{{ script.name }}', '{{ script.path }}', counter);{% endif %}{% endif %}{% endfor %}
var geneate_menus = function() {
// Generate the menu items only when all the initial scripts
// were loaded completely.
//
// First - register the menus from the other
// modules/extensions.
if (counter.total == counter.loaded) {
{% for key in ('File', 'Edit', 'Object' 'Tools', 'Management', 'Help') %}
obj.add_menus([{% for item in current_app.menu_items['%s_items' % key.lower()] %}{% if loop.index != 1 %}, {% endif %}{
name: "{{ item.name }}",
{% if item.module %}module: {{ item.module }},
{% endif %}{% if item.url %}url: "{{ item.url }}",
{% endif %}{% if item.target %}target: "{{ item.target }}",
{% endif %}{% if item.callback %}callback: "{{ item.callback }}",
{% endif %}{% if item.category %}category: "{{ item.category }}",
{% endif %}{% if item.icon %}icon: '{{ item.icon }}',
{% endif %}{% if item.data %}data: {{ item.data }},
{% endif %}label: '{{ item.label }}', applies: ['{{ key.lower() }}'],
priority: {{ item.priority }},
enable: '{{ item.enable }}'
}{% set hasMenus = True %}{% endfor %}]);
{% endfor %}
obj.create_menus();
} else {
// recall after some time
setTimeout(function() { geneate_menus(); }, 300);
}
};
geneate_menus();
// Register scripts and add menus
pgBrowser.utils.registerScripts(this);
pgBrowser.utils.addMenus(obj);
// Ping the server every 5 minutes
setInterval(function() {
@ -571,27 +514,7 @@ define(
obj.Events.on('pgadmin:browser:tree:update', obj.onUpdateTreeNode, obj);
obj.Events.on('pgadmin:browser:tree:refresh', obj.onRefreshTreeNode, obj);
},
// load the module right now
load_module: function(name, path, c) {
var obj = this;
require([name],function(m) {
try {
// initialze the module (if 'init' function present).
if (m.init && typeof(m.init) == 'function')
m.init();
} catch (e) {
// Log this exception on console to understand the issue properly.
console.log(e);
obj.report_error(gettext('Error loading script - ') + path);
}
if (c)
c.loaded += 1;
}, function() {
// Log the arguments on console to understand the issue properly.
console.log(arguments);
obj.report_error(gettext('Error loading script - ') + path);
});
},
add_menu_category: function(
id, label, priority, icon, above_separator, below_separator, single
) {
@ -644,12 +567,7 @@ define(
menus = pgMenu[a];
}
if (_.has(menus, m.name)) {
console && console.log && console.log(m.name +
' has been ignored!\nIt already exists in the ' +
a +
' list of menus!');
} else {
if (!_.has(menus, m.name)) {
menus[m.name] = new MenuItem({
name: m.name, label: m.label, module: m.module,
category: m.category, callback: m.callback,
@ -704,32 +622,31 @@ define(
showHelp: function(type, url, node, item, label) {
if (type == "object_help") {
// See if we can find an existing panel, if not, create one
pnlSqlHelp = this.docker.findPanels('pnl_sql_help')[0];
var pnlSqlHelp = this.docker.findPanels('pnl_sql_help')[0];
if (pnlSqlHelp == null) {
pnlProperties = this.docker.findPanels('properties')[0];
var pnlProperties = this.docker.findPanels('properties')[0];
this.docker.addPanel('pnl_sql_help', wcDocker.DOCK.STACKED, pnlProperties);
pnlSqlHelp = this.docker.findPanels('pnl_sql_help')[0];
}
// Construct the URL
server = node.getTreeNodeHierarchy(item).server;
baseUrl = '{{ pg_help_path }}'
var server = node.getTreeNodeHierarchy(item).server;
var baseUrl = pgBrowser.utils.pg_help_path;
if (server.server_type == 'ppas') {
baseUrl = '{{ edbas_help_path }}'
baseUrl = pgBrowser.utils.edbas_help_path;
}
major = Math.floor(server.version / 10000)
minor = Math.floor(server.version / 100) - (major * 100)
var major = Math.floor(server.version / 10000),
minor = Math.floor(server.version / 100) - (major * 100);
baseUrl = baseUrl.replace('$VERSION$', major + '.' + minor)
if (!S(baseUrl).endsWith('/')) {
baseUrl = baseUrl + '/'
}
fullUrl = baseUrl+ url;
var fullUrl = baseUrl+ url;
// Update the panel
iframe = $(pnlSqlHelp).data('embeddedFrame');
var iframe = $(pnlSqlHelp).data('embeddedFrame');
pnlSqlHelp.title('Help: '+ label);
pnlSqlHelp.focus();
@ -737,16 +654,16 @@ define(
} else if(type == "dialog_help") {
if(this.docker) {
// See if we can find an existing panel, if not, create one
pnlDialogHelp = this.docker.findPanels('pnl_online_help')[0];
var pnlDialogHelp = this.docker.findPanels('pnl_online_help')[0];
if (pnlDialogHelp == null) {
pnlProperties = this.docker.findPanels('properties')[0];
var pnlProperties = this.docker.findPanels('properties')[0];
this.docker.addPanel('pnl_online_help', wcDocker.DOCK.STACKED, pnlProperties);
pnlDialogHelp = this.docker.findPanels('pnl_online_help')[0];
}
// Update the panel
iframe = $(pnlDialogHelp).data('embeddedFrame');
var iframe = $(pnlDialogHelp).data('embeddedFrame');
pnlDialogHelp.focus();
iframe.openURL(url);
@ -932,7 +849,7 @@ define(
linearSearch = function() {
while (e >= s) {
i = items.eq(s);
d = ctx.t.itemData(i);
var d = ctx.t.itemData(i);
if (
pgAdmin.natural_sort(
d._label, _data._label
@ -957,7 +874,7 @@ define(
// We will try until it's half.
while (e - s > 22) {
i = items.eq(s);
d = ctx.t.itemData(i);
var d = ctx.t.itemData(i);
if (
pgAdmin.natural_sort(
d._label, _data._label
@ -972,7 +889,7 @@ define(
) != 1
)
return true;
m = s + Math.round((e - s) / 2);
var m = s + Math.round((e - s) / 2);
i = items.eq(m);
d = ctx.t.itemData(i);
var res = pgAdmin.natural_sort(d._label, _data._label);
@ -1186,7 +1103,7 @@ define(
if (_item_parent && !_item_grand_parent) {
var parent = null;
// We need to search in all parent siblings (eg: server groups)
parents = this.t.siblings(this.i) || [];
var parents = this.t.siblings(this.i) || [];
parents.push(this.i[0])
_.each(parents, function (p) {
var d = self.t.itemData($(p));
@ -1208,8 +1125,8 @@ define(
this.notFound = errorOut;
var _d = {_id: this.new._pid, _type: self.d._type}
parent = $(parent),
loaded = this.t.wasLoad(parent),
parent = $(parent);
var loaded = this.t.wasLoad(parent),
onLoad = function() {
self.i = parent;
self.d = self.d;
@ -1431,7 +1348,7 @@ define(
linearSearch = function() {
while (e >= s) {
i = items.eq(s);
d = ctx.t.itemData(i);
var d = ctx.t.itemData(i);
if (
pgAdmin.natural_sort(
d._label, _new._label
@ -1450,7 +1367,7 @@ define(
binarySearch = function() {
while (e - s > 22) {
i = items.eq(s);
d = ctx.t.itemData(i);
var d = ctx.t.itemData(i);
if (
pgAdmin.natural_sort(
d._label, _new._label
@ -1465,7 +1382,7 @@ define(
) != 1
)
return true;
m = s + Math.round((e - s) / 2);
var m = s + Math.round((e - s) / 2);
i = items.eq(m);
d = ctx.t.itemData(i);
var res = pgAdmin.natural_sort(d._label, _new._label);
@ -1981,7 +1898,7 @@ define(
for (; idx < size; idx++) {
d = _d.branch[idx];
n = _ctx.b.Nodes[d._type];
var n = _ctx.b.Nodes[d._type];
ctx = {
b: _ctx.b,
t: _ctx.t,
@ -1989,7 +1906,7 @@ define(
i: _ctx.i,
d: d,
select: _ctx.select,
hasId: !n.collection_node,
hasId: n && !n.collection_node,
o: _ctx.o,
load: true
};
@ -2050,10 +1967,10 @@ define(
"Shift-Tab": "indentLess"
},
editor_options: {
tabSize: '{{ editor_tab_size }}',
wrapCode: '{{ editor_wrap_code }}' == 'True',
insert_pair_brackets: '{{ editor_insert_pair_brackets }}' == 'True',
brace_matching: '{{ editor_brace_matching }}' == 'True'
tabSize: pgBrowser.utils.tabSize,
wrapCode: pgBrowser.utils.wrapCode,
insert_pair_brackets: pgBrowser.utils.insertPairBrackets,
brace_matching: pgBrowser.utils.braceMatching
}
});
@ -2066,13 +1983,13 @@ define(
delete CodeMirror.keyMap.emacsy["Ctrl-V"];
// Use spaces instead of tab
if ('{{ editor_use_spaces }}' == 'True') {
if (pgBrowser.utils.useSpaces == 'True') {
pgAdmin.Browser.editor_shortcut_keys.Tab = "insertSoftTab";
}
window.onbeforeunload = function(ev) {
var e = ev || window.event,
msg = '{{ _('Are you sure you wish to close the %(appname)s browser?', appname=config.APP_NAME) }}';
msg = S(gettext('Are you sure you wish to close the %s browser?')).sprintf(pgBrowser.utils.app_name).value();
// For IE and Firefox prior to version 4
if (e) {

View File

@ -1,8 +1,8 @@
define([
'sources/gettext', 'jquery', 'underscore', 'underscore.string', 'pgadmin',
'backbone', 'alertify', 'backform', 'pgadmin.backform', 'pgadmin.backgrid',
'backbone', 'alertify', 'backform', 'backgrid', 'pgadmin.backform', 'pgadmin.backgrid',
'pgadmin.browser.node'
], function(gettext, $, _, S, pgAdmin, Backbone, Alertify, Backform) {
], function(gettext, $, _, S, pgAdmin, Backbone, Alertify, Backform, Backgrid) {
var pgBrowser = pgAdmin.Browser = pgAdmin.Browser || {};
@ -113,25 +113,27 @@ define([
j.append(content);
// Fetch Data
collection.fetch({reset: true})
.error(function(xhr, error, message) {
pgBrowser.Events.trigger(
'pgadmin:collection:retrieval:error', 'properties', xhr, error, message, item, that
);
if (
!Alertify.pgHandleItemError(xhr, error, message, {item: item, info: info})
) {
Alertify.pgNotifier(
error, xhr,
S(
gettext("Error retrieving properties - %s.")
).sprintf(message || that.label).value(),
function() {
console.log(arguments);
}
collection.fetch({
reset: true,
error: function(xhr, error, message) {
pgBrowser.Events.trigger(
'pgadmin:collection:retrieval:error', 'properties', xhr, error, message, item, that
);
if (
!Alertify.pgHandleItemError(xhr, error, message, {item: item, info: info})
) {
Alertify.pgNotifier(
error, xhr,
S(
gettext("Error retrieving properties - %s.")
).sprintf(message || that.label).value(),
function() {
console.log(arguments);
}
);
}
}
});
})
},
generate_url: function(item, type, d) {
var url = pgAdmin.Browser.URL + '{TYPE}/{REDIRECT}{REF}',

View File

@ -1,17 +1,16 @@
define(
['underscore', 'alertify', 'pgadmin'],
function(_, alertify, pgAdmin) {
['sources/gettext', 'underscore', 'alertify', 'pgadmin'],
function(gettext, _, alertify, pgAdmin) {
pgAdmin.Browser = pgAdmin.Browser || {};
_.extend(pgAdmin.Browser, {
report_error: function(title, message, info) {
text = '<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">\
var text = '<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">\
<div class="panel panel-default">\
<div class="panel-heading" role="tab" id="headingOne">\
<h4 class="panel-title">\
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne" aria-expanded="true" aria-controls="collapseOne">\
{{ _('Error message') }}\
</a>\
' + gettext("Error message") + '</a>\
</h4>\
</div>\
<div id="collapseOne" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne">\
@ -24,7 +23,7 @@ function(_, alertify, pgAdmin) {
<div class="panel-heading" role="tab" id="headingTwo">\
<h4 class="panel-title">\
<a class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">\
{{ _('Additional info') }}</a>\
' + gettext("Additional info") + '</a>\
</h4>\
</div>\
<div id="collapseTwo" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingTwo">\

View File

@ -1,7 +1,7 @@
define(
'pgadmin.browser.messages',
['sources/gettext', 'underscore', 'underscore.string', 'pgadmin'],
function(gettext, S, _, pgAdmin) {
['sources/gettext', 'pgadmin'],
function(gettext, pgAdmin) {
var pgBrowser = pgAdmin.Browser = pgAdmin.Browser || {};

View File

@ -1,11 +1,9 @@
define([
'sources/gettext', 'jquery', 'underscore', 'underscore.string', 'pgadmin',
'pgadmin.browser.menu', 'backbone', 'alertify', 'pgadmin.browser.datamodel',
'backform',
'sources/alerts/alertify_wrapper',
'pgadmin.backform', 'wcdocker', 'pgadmin.alertifyjs'
], function(gettext, $, _, S, pgAdmin, Menu, Backbone, Alertify, pgBrowser, Backform, AlertifyWrapper) {
define(
'pgadmin.browser.node', [
'sources/gettext', 'jquery', 'underscore', 'underscore.string', 'pgadmin',
'pgadmin.browser.menu', 'backbone', 'alertify', 'pgadmin.browser.datamodel',
'backform', 'pgadmin.browser.utils', 'pgadmin.backform', 'pgadmin.alertifyjs'
], function(gettext, $, _, S, pgAdmin, Menu, Backbone, Alertify, pgBrowser, Backform) {
var wcDocker = window.wcDocker,
keyCode = {
@ -71,7 +69,7 @@ define([
sqlCreateHelp: '',
dialogHelp: '',
title: function(d) {
title: function(o, d) {
return o.label + (d ? (' - ' + d.label) : '');
},
hasId: true,
@ -128,7 +126,7 @@ define([
}
// show query tool only in context menu of supported nodes.
if (pgAdmin.DataGrid && pgAdmin.unsupported_nodes) {
if (true) {
if (_.indexOf(pgAdmin.unsupported_nodes, self.type) == -1) {
pgAdmin.Browser.add_menus([{
name: 'show_query_tool', node: self.type, module: self,
@ -154,7 +152,7 @@ define([
_.each(self.hasScriptTypes, function(stype) {
var type_label = S(
"{{ _("%s Script") }}"
gettext("%s Script")
).sprintf(stype.toUpperCase()).value(),
stype = stype.toLowerCase();
@ -329,45 +327,46 @@ define([
}
}, 1000, ctx);
newModel.fetch()
.success(function(res, msg, xhr) {
// clear timeout and remove message
clearTimeout(timer);
$msgDiv.addClass('hidden');
newModel.fetch({
success: function(res, msg, xhr) {
// clear timeout and remove message
clearTimeout(timer);
$msgDiv.addClass('hidden');
// We got the latest attributes of the
// object. Render the view now.
view.render();
setFocusOnEl();
newModel.startNewSession();
})
.error(function(xhr, error, message) {
var _label = that && item ?
that.getTreeNodeHierarchy(
item
)[that.type].label : '';
pgBrowser.Events.trigger(
'pgadmin:node:retrieval:error', 'properties',
xhr, error, message, item
);
if (
!Alertify.pgHandleItemError(
xhr, error, message, {item: item, info: info}
)
) {
Alertify.pgNotifier(
error, xhr,
S(
gettext("Error retrieving properties - %s")
).sprintf(message || _label).value(),
function() {
console.log(arguments);
}
// We got the latest attributes of the
// object. Render the view now.
view.render();
setFocusOnEl();
newModel.startNewSession();
},
error: function(xhr, error, message) {
var _label = that && item ?
that.getTreeNodeHierarchy(
item
)[that.type].label : '';
pgBrowser.Events.trigger(
'pgadmin:node:retrieval:error', 'properties',
xhr, error, message, item
);
}
// Close the panel (if could not fetch properties)
if (cancelFunc) {
cancelFunc();
if (
!Alertify.pgHandleItemError(
xhr, error, message, {item: item, info: info}
)
) {
Alertify.pgNotifier(
error, xhr,
S(
gettext("Error retrieving properties - %s")
).sprintf(message || _label).value(),
function() {
console.log(arguments);
}
);
}
// Close the panel (if could not fetch properties)
if (cancelFunc) {
cancelFunc();
}
}
});
} else {
@ -410,7 +409,7 @@ define([
isCloseable: true,
isPrivate: true,
elContainer: true,
content: '<div class="obj_properties"><div class="alert alert-info pg-panel-message">{{ _('Please wait while we fetch information about the node from the server!') }}</div></div>',
content: '<div class="obj_properties"><div class="alert alert-info pg-panel-message">' + gettext('Please wait while we fetch information about the node from the server!') + '</div></div>',
onCreate: function(myPanel, $container) {
$container.addClass('pg-no-overflow');
},
@ -464,7 +463,7 @@ define([
show_obj_properties: function(args, item) {
var t = pgBrowser.tree,
i = args.item || item || t.selected(),
d = i && i.length == 1 ? t.itemData(i) : undefined
d = i && i.length == 1 ? t.itemData(i) : undefined,
o = this,
l = o.title.apply(this, [d]);
@ -490,19 +489,19 @@ define([
d.body.insertBefore(el, d.body.firstChild);
var pW = screen.width < 800 ? '95%' : '500px',
pH = screen.height < 600 ? '95%' : '550px';
pH = screen.height < 600 ? '95%' : '550px',
w = pgAdmin.toPx(el, self.width || pW, 'width', true),
h = pgAdmin.toPx(el, self.height|| pH, 'height', true),
x = (b.offsetWidth - w) / 2,
y = (b.offsetHeight - h) / 2;
p = pgBrowser.docker.addPanel(
var p = pgBrowser.docker.addPanel(
'node_props', wcDocker.DOCK.FLOAT, undefined,
{w: w + 'px', h: h + 'px', x: x + 'px', y: y + 'px'}
);
b.removeChild(el);
delete(el);
// delete(el);
return p;
};
@ -525,7 +524,7 @@ define([
// And, actual parent of a table is schema, not Tables.
while (i && t.hasParent(i)) {
i = t.parent(i);
pd = t.itemData(i);
var pd = t.itemData(i);
if (isParent(pd)) {
// Assign the data, this is my actual parent.
@ -559,7 +558,7 @@ define([
} else {
if (pgBrowser.Node.panels && pgBrowser.Node.panels[d.id] &&
pgBrowser.Node.panels[d.id].$container) {
p = pgBrowser.Node.panels[d.id];
var p = pgBrowser.Node.panels[d.id];
/** TODO ::
* Run in edit mode (if asked) only when it is
* not already been running edit mode
@ -697,7 +696,8 @@ define([
* Make sure - we're using the correct version of node
*/
obj = pgBrowser.Nodes[d._type];
var objName = d.label;
var objName = d.label,
sql_url;
// URL for script type
if(scriptType == 'insert') {
@ -996,7 +996,7 @@ define([
// Release the view
view.remove({data: true, internal: true, silent: true});
// Deallocate the view
delete view;
// delete view;
view = null;
// Reset the data object
j.data('obj-view', null);
@ -1052,26 +1052,26 @@ define([
onSqlHelp = function() {
var panel = this;
// See if we can find an existing panel, if not, create one
pnlSqlHelp = pgBrowser.docker.findPanels('pnl_sql_help')[0];
var pnlSqlHelp = pgBrowser.docker.findPanels('pnl_sql_help')[0];
if (pnlSqlHelp == null) {
pnlProperties = pgBrowser.docker.findPanels('properties')[0];
var pnlProperties = pgBrowser.docker.findPanels('properties')[0];
pgBrowser.docker.addPanel('pnl_sql_help', wcDocker.DOCK.STACKED, pnlProperties);
pnlSqlHelp = pgBrowser.docker.findPanels('pnl_sql_help')[0];
}
// Construct the URL
server = that.getTreeNodeHierarchy(item).server;
var server = that.getTreeNodeHierarchy(item).server;
url = '{{ pg_help_path }}'
var url = pgBrowser.utils.pg_help_path;
if (server.server_type == 'ppas') {
url = '{{ edbas_help_path }}'
url = pgBrowser.utils.edbas_help_path;
}
major = Math.floor(server.version / 10000)
minor = Math.floor(server.version / 100) - (major * 100)
var major = Math.floor(server.version / 10000),
minor = Math.floor(server.version / 100) - (major * 100);
url = url.replace('$VERSION$', major + '.' + minor)
url = url.replace('$VERSION$', major + '.' + minor);
if (!S(url).endsWith('/')) {
url = url + '/'
}
@ -1088,7 +1088,7 @@ define([
}
// Update the panel
iframe = $(pnlSqlHelp).data('embeddedFrame');
var iframe = $(pnlSqlHelp).data('embeddedFrame');
pnlSqlHelp.title('SQL: ' + that.label);
pnlSqlHelp.focus();
@ -1098,16 +1098,16 @@ define([
onDialogHelp = function() {
var panel = this;
// See if we can find an existing panel, if not, create one
pnlDialogHelp = pgBrowser.docker.findPanels('pnl_online_help')[0];
var pnlDialogHelp = pgBrowser.docker.findPanels('pnl_online_help')[0];
if (pnlDialogHelp == null) {
pnlProperties = pgBrowser.docker.findPanels('properties')[0];
var pnlProperties = pgBrowser.docker.findPanels('properties')[0];
pgBrowser.docker.addPanel('pnl_online_help', wcDocker.DOCK.STACKED, pnlProperties);
pnlDialogHelp = pgBrowser.docker.findPanels('pnl_online_help')[0];
}
// Update the panel
iframe = $(pnlDialogHelp).data('embeddedFrame');
var iframe = $(pnlDialogHelp).data('embeddedFrame');
pnlDialogHelp.focus();
iframe.openURL(that.dialogHelp);
@ -1180,7 +1180,6 @@ define([
// Release the view
view.remove({data: true, internal: true, silent: true});
// Deallocate the view
delete view;
view = null;
// Reset the data object
j.data('obj-view', null);
@ -1495,7 +1494,8 @@ define([
getTreeNodeHierarchy: function(i) {
var idx = 0,
res = {},
t = pgBrowser.tree;
t = pgBrowser.tree,
d;
do {
d = t.itemData(i);
if (d._type in pgBrowser.Nodes && pgBrowser.Nodes[d._type].hasId) {

View File

@ -62,7 +62,7 @@ class DashboardModule(PgAdminModule):
isPrivate=False,
limit=1,
isIframe=False,
canHide=True)
canHide=True).__dict__
]
def register_preferences(self):
@ -114,6 +114,41 @@ class DashboardModule(PgAdminModule):
help_str=gettext('The number of seconds between graph samples.')
)
def get_exposed_url_endpoints(self):
"""
Returns:
list: a list of url endpoints exposed to the client.
"""
return [
'dashboard.index', 'dashboard.get_by_sever_id',
'dashboard.get_by_database_id',
'dashboard.session_stats',
'dashboard.get_session_stats_by_sever_id',
'dashboard.get_session_stats_by_database_id',
'dashboard.tps_stats',
'dashboard.tps_stats_by_server_id',
'dashboard.tps_stats_by_database_id',
'dashboard.ti_stats',
'dashboard.ti_stats_by_server_id',
'dashboard.ti_stats_by_database_id',
'dashboard.to_stats',
'dashboard.to_stats_by_server_id',
'dashboard.to_stats_by_database_id',
'dashboard.bio_stats',
'dashboard.bio_stats_by_server_id',
'dashboard.bio_stats_by_database_id',
'dashboard.activity',
'dashboard.get_activity_by_server_id',
'dashboard.get_activity_by_database_id',
'dashboard.locks',
'dashboard.get_locks_by_server_id',
'dashboard.get_locks_by_database_id',
'dashboard.prepared',
'dashboard.get_prepared_by_server_id',
'dashboard.get_prepared_by_database_id',
'dashboard.config',
'dashboard.get_config_by_server_id',
]
blueprint = DashboardModule(MODULE_NAME, __name__)
@ -200,9 +235,9 @@ def script():
mimetype="application/javascript")
@blueprint.route('/')
@blueprint.route('/<int:sid>')
@blueprint.route('/<int:sid>/<int:did>')
@blueprint.route('/', endpoint='index')
@blueprint.route('/<int:sid>', endpoint='get_by_sever_id')
@blueprint.route('/<int:sid>/<int:did>', endpoint='get_by_database_id')
@login_required
def index(sid=None, did=None):
"""
@ -286,9 +321,13 @@ def get_data(sid, did, template):
)
@blueprint.route('/session_stats/')
@blueprint.route('/session_stats/<int:sid>')
@blueprint.route('/session_stats/<int:sid>/<int:did>')
@blueprint.route('/session_stats/', endpoint='session_stats')
@blueprint.route(
'/session_stats/<int:sid>', endpoint='get_session_stats_by_sever_id')
@blueprint.route(
'/session_stats/<int:sid>/<int:did>',
endpoint='get_session_stats_by_database_id'
)
@login_required
@check_precondition
def session_stats(sid=None, did=None):
@ -300,9 +339,11 @@ def session_stats(sid=None, did=None):
return get_data(sid, did, 'session_stats.sql')
@blueprint.route('/tps_stats/')
@blueprint.route('/tps_stats/<int:sid>')
@blueprint.route('/tps_stats/<int:sid>/<int:did>')
@blueprint.route('/tps_stats/', endpoint='tps_stats')
@blueprint.route('/tps_stats/<int:sid>', endpoint='tps_stats_by_server_id')
@blueprint.route(
'/tps_stats/<int:sid>/<int:did>', endpoint='tps_stats_by_database_id'
)
@login_required
@check_precondition
def tps_stats(sid=None, did=None):
@ -314,9 +355,10 @@ def tps_stats(sid=None, did=None):
return get_data(sid, did, 'tps_stats.sql')
@blueprint.route('/ti_stats/')
@blueprint.route('/ti_stats/<int:sid>')
@blueprint.route('/ti_stats/<int:sid>/<int:did>')
@blueprint.route('/ti_stats/', endpoint='ti_stats')
@blueprint.route('/ti_stats/<int:sid>', endpoint='ti_stats_by_server_id')
@blueprint.route(
'/ti_stats/<int:sid>/<int:did>', endpoint='ti_stats_by_database_id')
@login_required
@check_precondition
def ti_stats(sid=None, did=None):
@ -328,9 +370,10 @@ def ti_stats(sid=None, did=None):
return get_data(sid, did, 'ti_stats.sql')
@blueprint.route('/to_stats/')
@blueprint.route('/to_stats/<int:sid>')
@blueprint.route('/to_stats/<int:sid>/<int:did>')
@blueprint.route('/to_stats/', endpoint='to_stats')
@blueprint.route('/to_stats/<int:sid>', endpoint='to_stats_by_server_id')
@blueprint.route(
'/to_stats/<int:sid>/<int:did>', endpoint='to_stats_by_database_id')
@login_required
@check_precondition
def to_stats(sid=None, did=None):
@ -342,9 +385,10 @@ def to_stats(sid=None, did=None):
return get_data(sid, did, 'to_stats.sql')
@blueprint.route('/bio_stats/')
@blueprint.route('/bio_stats/<int:sid>')
@blueprint.route('/bio_stats/<int:sid>/<int:did>')
@blueprint.route('/bio_stats/', endpoint='bio_stats')
@blueprint.route('/bio_stats/<int:sid>', endpoint='bio_stats_by_server_id')
@blueprint.route(
'/bio_stats/<int:sid>/<int:did>', endpoint='bio_stats_by_database_id')
@login_required
@check_precondition
def bio_stats(sid=None, did=None):
@ -356,9 +400,10 @@ def bio_stats(sid=None, did=None):
return get_data(sid, did, 'bio_stats.sql')
@blueprint.route('/activity/')
@blueprint.route('/activity/<int:sid>')
@blueprint.route('/activity/<int:sid>/<int:did>')
@blueprint.route('/activity/', endpoint='activity')
@blueprint.route('/activity/<int:sid>', endpoint='get_activity_by_server_id')
@blueprint.route(
'/activity/<int:sid>/<int:did>', endpoint='get_activity_by_database_id')
@login_required
@check_precondition
def activity(sid=None, did=None):
@ -370,9 +415,10 @@ def activity(sid=None, did=None):
return get_data(sid, did, 'activity.sql')
@blueprint.route('/locks/')
@blueprint.route('/locks/<int:sid>')
@blueprint.route('/locks/<int:sid>/<int:did>')
@blueprint.route('/locks/', endpoint='locks')
@blueprint.route('/locks/<int:sid>', endpoint='get_locks_by_server_id')
@blueprint.route(
'/locks/<int:sid>/<int:did>', endpoint='get_locks_by_database_id')
@login_required
@check_precondition
def locks(sid=None, did=None):
@ -384,9 +430,10 @@ def locks(sid=None, did=None):
return get_data(sid, did, 'locks.sql')
@blueprint.route('/prepared/')
@blueprint.route('/prepared/<int:sid>')
@blueprint.route('/prepared/<int:sid>/<int:did>')
@blueprint.route('/prepared/', endpoint='prepared')
@blueprint.route('/prepared/<int:sid>', endpoint='get_prepared_by_server_id')
@blueprint.route(
'/prepared/<int:sid>/<int:did>', endpoint='get_prepared_by_database_id')
@login_required
@check_precondition
def prepared(sid=None, did=None):
@ -398,8 +445,8 @@ def prepared(sid=None, did=None):
return get_data(sid, did, 'prepared.sql')
@blueprint.route('/config/')
@blueprint.route('/config/<int:sid>')
@blueprint.route('/config/', endpoint='config')
@blueprint.route('/config/<int:sid>', endpoint='get_config_by_server_id')
@login_required
@check_precondition
def config(sid=None):

View File

@ -1,8 +1,9 @@
define([
'require', 'jquery', 'pgadmin', 'underscore', 'backbone', 'sources/gettext', 'flotr2', 'wcdocker',
'pgadmin.browser', 'bootstrap'
define('pgadmin.dashboard', [
'sources/url_for', 'sources/gettext', 'require', 'jquery', 'underscore',
'pgadmin', 'backbone', 'backgrid', 'flotr2', 'backgrid.filter',
'pgadmin.browser', 'bootstrap', 'wcdocker'
],
function(r, $, pgAdmin, _, Backbone, gettext) {
function(url_for, gettext, r, $, _, pgAdmin, Backbone, Backgrid, Flotr) {
var wcDocker = window.wcDocker,
pgBrowser = pgAdmin.Browser;
@ -31,7 +32,7 @@ function(r, $, pgAdmin, _, Backbone, gettext) {
pgBrowser.Events.on('pgadmin:server:disconnect', disconnected);
// Load the default welcome dashboard
url = '{{ url_for('dashboard.index') }}';
var url = url_for('dashboard.index');
var dashboardPanel = pgBrowser.panels['dashboard'].panel;
if (dashboardPanel) {
@ -68,7 +69,7 @@ function(r, $, pgAdmin, _, Backbone, gettext) {
object_selected: function(item, itemData, node) {
if (itemData && itemData._type && dashboardVisible) {
var treeHierarchy = node.getTreeNodeHierarchy(item),
url = '{{ url_for('dashboard.index') }}',
url = url_for('dashboard.index'),
sid = -1, did = -1, b = pgAdmin.Browser,
m = b && b.Nodes[itemData._type];
@ -150,7 +151,7 @@ function(r, $, pgAdmin, _, Backbone, gettext) {
if (!dashboardVisible)
return;
y = 0;
var y = 0;
if (dataset.length == 0) {
if (counter == true)
{
@ -185,7 +186,7 @@ function(r, $, pgAdmin, _, Backbone, gettext) {
}
// Reset the time index to get a proper scrolling display
for (z = 0; z < dataset[y]['data'].length; z++) {
for (var z = 0; z < dataset[y]['data'].length; z++) {
dataset[y]['data'][z][0] = z;
}
@ -215,11 +216,10 @@ function(r, $, pgAdmin, _, Backbone, gettext) {
// Animate
var setTimeoutFunc = function () {
path = url + sid;
var path = url + sid;
if (did != -1) {
path += '/' + did;
}
$.ajax({
url: path,
type: "GET",
@ -231,7 +231,8 @@ function(r, $, pgAdmin, _, Backbone, gettext) {
},
error: function (xhr, status, msg) {
var err = $.parseJSON(xhr.responseText),
msg = err.errormsg
msg = err.errormsg,
cls;
// If we get a 428, it means the server isn't connected
if (xhr.status == 428) {
if (_.isUndefined(msg) || _.isNull(msg)) {
@ -287,7 +288,7 @@ function(r, $, pgAdmin, _, Backbone, gettext) {
render_grid: function(container, sid, did, url, columns) {
var Datum = Backbone.Model.extend({});
path = url + sid;
var path = url + sid;
if (did != -1) {
path += '/' + did;
}
@ -330,9 +331,9 @@ function(r, $, pgAdmin, _, Backbone, gettext) {
// Render the data in a grid
render_grid_data: function(container) {
data = $(container).data('data');
grid = $(container).data('grid');
filter = $(container).data('filter');
var data = $(container).data('data'),
grid = $(container).data('grid'),
filter = $(container).data('filter');
if(_.isUndefined(data)){
return null;
@ -353,7 +354,8 @@ function(r, $, pgAdmin, _, Backbone, gettext) {
},
error: function(model, xhr, options) {
var err = $.parseJSON(xhr.responseText),
msg = err.errormsg
msg = err.errormsg,
cls;
// If we get a 428, it means the server isn't connected
if (xhr.status == 428) {
if (_.isUndefined(msg) || _.isNull(msg)) {
@ -406,7 +408,7 @@ function(r, $, pgAdmin, _, Backbone, gettext) {
var data_bio = [];
// Fake DB ID
did = -1;
var did = -1;
var options_line = {
parseFloat: false,
@ -606,17 +608,17 @@ function(r, $, pgAdmin, _, Backbone, gettext) {
}];
// Render the graphs
pgAdmin.Dashboard.render_chart(div_sessions, data_sessions, dataset_sessions, sid, did, '{{ url_for('dashboard.session_stats') }}', options_line, false, session_stats_refresh);
pgAdmin.Dashboard.render_chart(div_tps, data_tps, dataset_tps, sid, did, '{{ url_for('dashboard.tps_stats') }}', options_line, true, tps_stats_refresh);
pgAdmin.Dashboard.render_chart(div_ti, data_ti, dataset_ti, sid, did, '{{ url_for('dashboard.ti_stats') }}', options_line, true, ti_stats_refresh);
pgAdmin.Dashboard.render_chart(div_to, data_to, dataset_to, sid, did, '{{ url_for('dashboard.to_stats') }}', options_line, true, to_stats_refresh);
pgAdmin.Dashboard.render_chart(div_bio, data_bio, dataset_bio, sid, did, '{{ url_for('dashboard.bio_stats') }}', options_line, true, bio_stats_refresh);
pgAdmin.Dashboard.render_chart(div_sessions, data_sessions, dataset_sessions, sid, did, url_for('dashboard.session_stats'), options_line, false, session_stats_refresh);
pgAdmin.Dashboard.render_chart(div_tps, data_tps, dataset_tps, sid, did, url_for('dashboard.tps_stats'), options_line, true, tps_stats_refresh);
pgAdmin.Dashboard.render_chart(div_ti, data_ti, dataset_ti, sid, did, url_for('dashboard.ti_stats'), options_line, true, ti_stats_refresh);
pgAdmin.Dashboard.render_chart(div_to, data_to, dataset_to, sid, did, url_for('dashboard.to_stats'), options_line, true, to_stats_refresh);
pgAdmin.Dashboard.render_chart(div_bio, data_bio, dataset_bio, sid, did, url_for('dashboard.bio_stats'), options_line, true, bio_stats_refresh);
// Render the tabs, but only get data for the activity tab for now
pgAdmin.Dashboard.render_grid(div_server_activity, sid, did, '{{ url_for('dashboard.activity') }}', server_activity_columns);
pgAdmin.Dashboard.render_grid(div_server_locks, sid, did, '{{ url_for('dashboard.locks') }}', server_locks_columns);
pgAdmin.Dashboard.render_grid(div_server_prepared, sid, did, '{{ url_for('dashboard.prepared') }}', server_prepared_columns);
pgAdmin.Dashboard.render_grid(div_server_config, sid, did, '{{ url_for('dashboard.config') }}', server_config_columns);
pgAdmin.Dashboard.render_grid(div_server_activity, sid, did, url_for('dashboard.activity'), server_activity_columns);
pgAdmin.Dashboard.render_grid(div_server_locks, sid, did, url_for('dashboard.locks'), server_locks_columns);
pgAdmin.Dashboard.render_grid(div_server_prepared, sid, did, url_for('dashboard.prepared'), server_prepared_columns);
pgAdmin.Dashboard.render_grid(div_server_config, sid, did, url_for('dashboard.config'), server_config_columns);
pgAdmin.Dashboard.render_grid_data(div_server_activity);
@ -841,16 +843,16 @@ function(r, $, pgAdmin, _, Backbone, gettext) {
}];
// Render the graphs
pgAdmin.Dashboard.render_chart(div_sessions, data_sessions, dataset_sessions, sid, did, '{{ url_for('dashboard.session_stats') }}', options_line, false, session_stats_refresh);
pgAdmin.Dashboard.render_chart(div_tps, data_tps, dataset_tps, sid, did, '{{ url_for('dashboard.tps_stats') }}', options_line, true, tps_stats_refresh);
pgAdmin.Dashboard.render_chart(div_ti, data_ti, dataset_ti, sid, did, '{{ url_for('dashboard.ti_stats') }}', options_line, true, ti_stats_refresh);
pgAdmin.Dashboard.render_chart(div_to, data_to, dataset_to, sid, did, '{{ url_for('dashboard.to_stats') }}', options_line, true, to_stats_refresh);
pgAdmin.Dashboard.render_chart(div_bio, data_bio, dataset_bio, sid, did, '{{ url_for('dashboard.bio_stats') }}', options_line, true, bio_stats_refresh);
pgAdmin.Dashboard.render_chart(div_sessions, data_sessions, dataset_sessions, sid, did, url_for('dashboard.session_stats'), options_line, false, session_stats_refresh);
pgAdmin.Dashboard.render_chart(div_tps, data_tps, dataset_tps, sid, did, url_for('dashboard.tps_stats'), options_line, true, tps_stats_refresh);
pgAdmin.Dashboard.render_chart(div_ti, data_ti, dataset_ti, sid, did, url_for('dashboard.ti_stats'), options_line, true, ti_stats_refresh);
pgAdmin.Dashboard.render_chart(div_to, data_to, dataset_to, sid, did, url_for('dashboard.to_stats'), options_line, true, to_stats_refresh);
pgAdmin.Dashboard.render_chart(div_bio, data_bio, dataset_bio, sid, did, url_for('dashboard.bio_stats'), options_line, true, bio_stats_refresh);
// Render the tabs, but only get data for the activity tab for now
pgAdmin.Dashboard.render_grid(div_database_activity, sid, did, '{{ url_for('dashboard.activity') }}', database_activity_columns);
pgAdmin.Dashboard.render_grid(div_database_locks, sid, did, '{{ url_for('dashboard.locks') }}', database_locks_columns);
pgAdmin.Dashboard.render_grid(div_database_prepared, sid, did, '{{ url_for('dashboard.prepared') }}', database_prepared_columns);
pgAdmin.Dashboard.render_grid(div_database_activity, sid, did, url_for('dashboard.activity'), database_activity_columns);
pgAdmin.Dashboard.render_grid(div_database_locks, sid, did, url_for('dashboard.locks'), database_locks_columns);
pgAdmin.Dashboard.render_grid(div_database_prepared, sid, did, url_for('dashboard.prepared'), database_prepared_columns);
pgAdmin.Dashboard.render_grid_data(div_database_activity);

View File

@ -183,6 +183,7 @@ SELECT generate_series(1, {}) as id""".format(
config.ON_DEMAND_RECORD_COUNT * ON_DEMAND_CHUNKS)
wait = WebDriverWait(self.page.driver, 10)
time.sleep(1)
self.page.fill_codemirror_area_with(query)
self.page.find_by_id("btn-flash").click()
@ -194,16 +195,15 @@ SELECT generate_series(1, {}) as id""".format(
# scroll to bottom to fetch next chunk of result set.
self.driver.execute_script(
"$('.slick-viewport').scrollTop($('.grid-canvas').height());"
"pgAdmin.SqlEditor.jquery('.slick-viewport').scrollTop(pgAdmin.SqlEditor.jquery('.grid-canvas').height());"
)
# wait for ajax to complete.
time.sleep(1)
# again scroll to bottom to bring last row of next chunk in
# viewport.
self.driver.execute_script(
"$('.slick-viewport').scrollTop($('.grid-canvas').height());"
"pgAdmin.SqlEditor.jquery('.slick-viewport').scrollTop(pgAdmin.SqlEditor.jquery('.grid-canvas').height());"
)
row_id_to_find = config.ON_DEMAND_RECORD_COUNT * ON_DEMAND_CHUNKS
@ -234,7 +234,7 @@ SELECT generate_series(1, {}) as id""".format(
# scroll to bottom to bring last row of next chunk in
# viewport.
self.driver.execute_script(
"$('.slick-viewport').scrollTop($('.grid-canvas').height());"
"pgAdmin.SqlEditor.jquery('.slick-viewport').scrollTop(pgAdmin.SqlEditor.jquery('.grid-canvas').height());"
)
canvas = wait.until(EC.presence_of_element_located(
@ -274,7 +274,7 @@ SELECT generate_series(1, {}) as id1, 'dummy' as id2""".format(
# scroll to bottom to bring last row of next chunk in
# viewport.
self.driver.execute_script(
"$('.slick-viewport').scrollTop($('.grid-canvas').height());"
"pgAdmin.SqlEditor.jquery('.slick-viewport').scrollTop(pgAdmin.SqlEditor.jquery('.grid-canvas').height());"
)
canvas = wait.until(EC.presence_of_element_located(

View File

@ -152,6 +152,7 @@ class CheckForXssFeatureTest(BaseFeatureTest):
def _check_xss_in_query_tool(self):
self.page.driver.find_element_by_link_text("Tools").click()
self.page.find_by_partial_link_text("Query Tool").click()
self.page.click_tab('Query -')
self.page.fill_codemirror_area_with("select '<img src=\"x\" onerror=\"console.log(1)\">'")
time.sleep(1)
self.page.find_by_id("btn-flash").click()

View File

@ -52,28 +52,28 @@ class HelpModule(PgAdminModule):
priority=100,
isPrivate=True,
title=gettext('Online Help'),
icon='fa fa-question'),
icon='fa fa-question').__dict__,
Panel(
name='pnl_pgadmin_website',
priority=200,
title=gettext('pgAdmin Website'),
icon='fa fa-external-link',
content='https://www.pgadmin.org/'),
content='https://www.pgadmin.org/').__dict__,
Panel(
name='pnl_postgresql_website',
priority=300,
title=gettext('PostgreSQL Website'),
icon='fa fa-external-link',
content='http://www.postgresql.org/'),
content='http://www.postgresql.org/').__dict__,
Panel(
name='pnl_sql_help',
priority=400,
isPrivate=True,
icon='fa fa-info',
title=gettext('SQL Help'))]
title=gettext('SQL Help')).__dict__]
def register_preferences(self):
"""

View File

@ -66,7 +66,7 @@ class MiscModule(PgAdminModule):
Returns:
list: a list of url endpoints exposed to the client.
"""
return ['misc.ping']
return ['misc.ping', 'misc.index']
# Initialise the module
@ -76,7 +76,7 @@ blueprint = MiscModule(MODULE_NAME, __name__)
##########################################################################
# A special URL used to "ping" the server
##########################################################################
@blueprint.route("/")
@blueprint.route("/", endpoint='index')
def index():
return ''

View File

@ -1,4 +1,4 @@
define([
define('misc.bgprocess', [
'pgadmin', 'sources/gettext', 'sources/url_for', 'underscore',
'underscore.string', 'jquery', 'pgadmin.browser', 'alertify',
'pgadmin.browser.messages'
@ -135,12 +135,14 @@ define([
!self.details && !_.isNull(self.exit_code)
);
var io = ie = 0, res = [],
escapeEl = document.createElement('textarea'),
escapeHTML = function(html) {
escapeEl.textContent = html;
return escapeEl.innerHTML;
};
var io = 0,
ie = 0,
res = [],
escapeEl = document.createElement('textarea'),
escapeHTML = function(html) {
escapeEl.textContent = html;
return escapeEl.innerHTML;
};
while (io < out.length && ie < err.length) {
if (pgAdmin.natural_sort(out[io][0], err[ie][0]) <= 0){
@ -452,7 +454,7 @@ define([
if (!res || !_.isArray(res)) {
return;
}
for (idx in res) {
for (var idx in res) {
var process = res[idx];
if ('id' in process) {
if (!(process.id in observer.bgprocesses)) {

View File

@ -1,4 +1,4 @@
define([
define('misc.depends', [
'sources/gettext', 'underscore', 'underscore.string', 'jquery', 'pgadmin.browser',
'alertify', 'pgadmin.alertifyjs'
], function(gettext, _, S, $, pgBrowser, Alertify) {
@ -6,6 +6,8 @@ define([
if (pgBrowser.ShowNodeDepends)
return pgBrowser.ShowNodeDepends;
var wcDocker = window.wcDocker;
pgBrowser.ShowNodeDepends = pgBrowser.ShowNodeDepends || {};
_.extend(pgBrowser.ShowNodeDepends, {
@ -192,7 +194,7 @@ define([
var msg = messages[0],
$container = panel[0].layout().scene().find('.pg-panel-content'),
$msgContainer = $container.find('.pg-panel-depends-message'),
$gridContainer = $container.find('.pg-panel-depends-container');
$gridContainer = $container.find('.pg-panel-depends-container'),
treeHierarchy = node.getTreeNodeHierarchy(item),
n_value = -1,
n_type = type;

View File

@ -144,6 +144,19 @@ class FileManagerModule(PgAdminModule):
'file_items': []
}
def get_exposed_url_endpoints(self):
"""
Returns:
list: a list of url endpoints exposed to the client.
"""
return [
'file_manager.filemanager',
'file_manager.index',
'file_manager.get_trans_id',
'file_manager.delete_trans_id',
'file_manager.save_last_dir'
]
def get_file_size_preference(self):
return self.file_upload_size
@ -165,7 +178,7 @@ class FileManagerModule(PgAdminModule):
blueprint = FileManagerModule(MODULE_NAME, __name__)
@blueprint.route("/")
@blueprint.route("/", endpoint='index')
@login_required
def index():
"""Render the preferences dialog."""
@ -226,7 +239,9 @@ def file_manager_config(trans_id):
mimetype="application/json")
@blueprint.route("/get_trans_id", methods=["GET", "POST"])
@blueprint.route(
"/get_trans_id", methods=["GET", "POST"], endpoint='get_trans_id'
)
@login_required
def get_trans_id():
if len(req.data) != 0:
@ -239,7 +254,10 @@ def get_trans_id():
)
@blueprint.route("/del_trans_id/<int:trans_id>", methods=["GET", "POST"])
@blueprint.route(
"/del_trans_id/<int:trans_id>",
methods=["GET", "POST"], endpoint='delete_trans_id'
)
@login_required
def delete_trans_id(trans_id):
Filemanager.release_transaction(trans_id)
@ -248,7 +266,9 @@ def delete_trans_id(trans_id):
)
@blueprint.route("/save_last_dir/<int:trans_id>", methods=["POST"])
@blueprint.route(
"/save_last_dir/<int:trans_id>", methods=["POST"], endpoint='save_last_dir'
)
@login_required
def save_last_directory_visited(trans_id):
blueprint.last_directory_visited.set(req.json['path'])
@ -1126,7 +1146,10 @@ class Filemanager(object):
return res
@blueprint.route("/filemanager/<int:trans_id>/", methods=["GET", "POST"])
@blueprint.route(
"/filemanager/<int:trans_id>/",
methods=["GET", "POST"], endpoint='filemanager'
)
@login_required
def file_manager(trans_id):
"""

View File

@ -221,7 +221,7 @@ div.clip {
background: -webkit-linear-gradient(top, rgba(44, 118, 180, 0.71) 0%,rgba(44, 118, 180, 0.98) 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, rgba(44, 118, 180, 0.71) 0%,rgba(44, 118, 180, 0.98) 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, rgba(44, 118, 180, 0.71) 0%,rgba(44, 118, 180, 0.98) 100%); /* IE10+ */
background: linear-gradient(to bottom, rgba(44, 118, 180, 0.71) 0%,rgba(44, 118, 180, 0.98) 100%)
background: linear-gradient(to bottom, rgba(44, 118, 180, 0.71) 0%,rgba(44, 118, 180, 0.98) 100%);
border-bottom: 1px solid #ccc;
display: inline-block;
width: 100%;
@ -470,14 +470,18 @@ button.list span {
}
.file_manager .upload_file #multiple-uploads {
background: black;
color: white;
padding: 0px !important;
height: calc(100% - 20px);
background: #000;
color: #fff;
padding: 0px !important;
overflow: auto;
width: 100%;
}
.file_manager .upload_file #multiple-uploads .dz-message {
text-align: center;
}
.fileinfo .prompt-info {
text-align: center;
color: #fff;
@ -591,8 +595,9 @@ button.list span {
}
.file_upload_main .dz-progress {
float: left;
width: 100%;
height: 21px !important;
top: 83px !important;
border: 1px solid #8a6d3b;
border-radius: 0 !important;
-moz-border-radius: 0 !important;
@ -606,6 +611,8 @@ button.list span {
.file_upload_main .dz-progress .dz-upload.success {
background: green !important;
float: left;
width: 100%;
}
a.dz-remove {

View File

@ -1,7 +1,6 @@
<html>
<head>
<script type="text/javascript" src="{{ url_for('static', filename='vendor/jquery.dropzone/dropzone.js') }}"></script>
<script type="text/javascript" src="{{ url_for('file_manager.index') }}utility.js"></script>
<link type="text/css" rel="stylesheet" href="{{ url_for('file_manager.static', filename='css/file_manager.css')}}"/>
</head>
<body>
<div class="file_manager">
@ -55,6 +54,11 @@
</div>
</div>
<script>
require(['sources/generated/file_utils'], function() {
pgAdmin.FileUtils.init();
});
</script>
</div>
</body>
</html>

View File

@ -1,8 +1,7 @@
// This defines File Manager dialog
define([
'sources/gettext', 'jquery', 'underscore', 'alertify',
'sources/alerts/alertify_wrapper',
], function(gettext, $, _, alertify, AlertifyWrapper) {
define('misc.file_manager', [
'sources/gettext', 'sources/url_for', 'jquery', 'underscore', 'alertify',
'sources/alerts/alertify_wrapper'
], function(gettext, url_for, $, _, alertify, AlertifyWrapper) {
pgAdmin = pgAdmin || window.pgAdmin || {};
/*
@ -21,45 +20,43 @@ define([
this.initialized = true;
var module_url = "{{ url_for('file_manager.index') }}",
fileConnector = module_url + "filemanager/";
// send a request to get transaction id
var getTransId = function(configs) {
return $.ajax({
data: configs,
type: "POST",
async: false,
url: url_for('file_manager.get_trans_id'),
dataType: "json",
contentType: "application/json; charset=utf-8",
});
};
// send a request to get transaction id
var getTransId = function(configs) {
return $.ajax({
data: configs,
type: "POST",
async: false,
url: module_url + "get_trans_id",
dataType: "json",
contentType: "application/json; charset=utf-8",
});
};
// Function to remove trans id from session
var removeTransId = function(trans_id) {
return $.ajax({
type: "GET",
async: false,
url: url_for('file_manager.delete_trans_id', {'trans_id': trans_id}),
dataType: "json",
contentType: "application/json; charset=utf-8",
});
};
// Function to remove trans id from session
var removeTransId = function(trans_id) {
return $.ajax({
type: "GET",
async: false,
url: module_url + "del_trans_id/" + trans_id,
dataType: "json",
contentType: "application/json; charset=utf-8",
});
};
var set_last_traversed_dir = function(path, trans_id) {
return $.ajax({
url: "{{ url_for('file_manager.index') }}save_last_dir/" + trans_id,
type: 'POST',
data: JSON.stringify(path),
contentType: 'application/json'
});
};
var set_last_traversed_dir = function(path, trans_id) {
return $.ajax({
url: url_for('file_manager.save_last_dir', {'trans_id': trans_id}),
type: 'POST',
data: JSON.stringify(path),
contentType: 'application/json'
});
};
// Declare the Storage dialog
alertify.dialog('storageManagerDlg', function() {
var controls = [], // Keep tracking of all the backform controls
// Dialog containter
$container = $("<div class='storage_dialog'></div>");
$container = $("<div class='storage_dialog'></div>"),
trans_id;
/*
* Function: renderStoragePanel
@ -73,12 +70,11 @@ define([
*/
var content = $container.find('.storage_content');
content.empty();
$.get("{{ url_for('file_manager.index') }}", function(data) {
$.get(url_for('file_manager.index'), function(data) {
content.append(data);
});
transId = getTransId(params);
var transId = getTransId(params);
var t_res;
if (transId.readyState == 4) {
t_res = JSON.parse(transId.responseText);
@ -181,6 +177,7 @@ define([
var controls = [], // Keep tracking of all the backform controls
// Dialog containter
$container = $("<div class='storage_dialog file_selection_dlg'></div>");
var trans_id;
// send a request to get transaction id
/*
@ -196,11 +193,11 @@ define([
var content = $container.find('.storage_content');
content.empty();
$.get("{{ url_for('file_manager.index') }}", function(data) {
$.get(url_for('file_manager.index'), function(data) {
content.append(data);
});
transId = getTransId(configs);
var transId = getTransId(configs);
var t_res;
if (transId.readyState == 4) {
t_res = JSON.parse(transId.responseText);
@ -305,7 +302,8 @@ define([
alertify.dialog('folderSelectionDlg', function() {
var controls = [], // Keep tracking of all the backform controls
// Dialog containter
$container = $("<div class='storage_dialog folder_selection_dlg'></div>");
$container = $("<div class='storage_dialog folder_selection_dlg'></div>"),
trans_id;
// send a request to get transaction id
/*
@ -321,11 +319,11 @@ define([
var content = $container.find('.storage_content');
content.empty();
$.get("{{ url_for('file_manager.index') }}", function(data) {
$.get(url_for('file_manager.index'), function(data) {
content.append(data);
});
transId = getTransId(params);
var transId = getTransId(params);
var t_res;
if (transId.readyState == 4) {
t_res = JSON.parse(transId.responseText);
@ -428,7 +426,8 @@ define([
alertify.dialog('createModeDlg', function() {
var controls = [], // Keep tracking of all the backform controls
// Dialog containter
$container = $("<div class='storage_dialog create_mode_dlg'></div>");
$container = $("<div class='storage_dialog create_mode_dlg'></div>"),
trans_id;
/*
* Function: renderStoragePanel
@ -443,11 +442,11 @@ define([
var content = $container.find('.storage_content');
content.empty();
$.get("{{ url_for('file_manager.index') }}", function(data) {
$.get(url_for('file_manager.index'), function(data) {
content.append(data);
});
transId = getTransId(params);
var transId = getTransId(params);
var t_res;
if (transId.readyState == 4) {
t_res = JSON.parse(transId.responseText);
@ -561,12 +560,12 @@ define([
$.ajax({
type: 'POST',
data: JSON.stringify(file_data),
url: fileConnector + trans_id+'/',
url: url_for('file_manager.filemanager', {'trans_id': trans_id}),
dataType: 'json',
contentType: "application/x-download; charset=utf-8",
async: false,
success: function(resp) {
data = resp.data.result;
var data = resp.data.result;
if(data['Code'] === 1) {
is_exist = true;
} else {
@ -586,7 +585,7 @@ define([
$.ajax({
type: 'POST',
data: JSON.stringify(post_data),
url: fileConnector + trans_id+'/',
url: url_for('file_manager.filemanager', {'trans_id': trans_id}),
dataType: 'json',
contentType: "application/json; charset=utf-8",
async: false,

View File

@ -1,4 +1,4 @@
define([
define('misc.sql', [
'sources/gettext', 'underscore', 'underscore.string', 'jquery', 'pgadmin.browser',
'alertify', 'pgadmin.alertifyjs'
], function(gettext, _, S, $, pgBrowser, Alertify) {
@ -8,6 +8,7 @@ define([
if (pgBrowser.ShowNodeSQL.initialized) {
return pgBrowser.ShowNodeSQL;
}
var wcDocker = window.wcDocker;
_.extend(pgBrowser.ShowNodeSQL, {
init: function() {
@ -17,6 +18,7 @@ define([
this.initialized = true;
_.bindAll(this, 'showSQL', 'sqlPanelVisibilityChanged');
var sqlPanels;
this.sqlPanels = sqlPanels = pgBrowser.docker.findPanels('sql');
// We will listend to the visibility change of the SQL panel
@ -64,6 +66,7 @@ define([
**/
this.timeout && clearTimeout(this.timeout);
var that = this;
this.timeout = setTimeout(
function() {
var sql = '';
@ -75,11 +78,11 @@ define([
treeHierarchy = node.getTreeNodeHierarchy(item);
// Avoid unnecessary reloads
if (_.isEqual($(this.sqlPanels[0]).data('node-prop'), treeHierarchy)) {
if (_.isEqual($(that.sqlPanels[0]).data('node-prop'), treeHierarchy)) {
return;
}
// Cache the current IDs for next time
$(this.sqlPanels[0]).data('node-prop', treeHierarchy);
$(that.sqlPanels[0]).data('node-prop', treeHierarchy);
if (node.hasSQL) {

View File

@ -1,5 +1,6 @@
define([
'sources/gettext', 'underscore', 'underscore.string', 'jquery', 'pgadmin.browser', 'backgrid',
define('misc.statistics', [
'sources/gettext', 'underscore', 'underscore.string', 'jquery',
'pgadmin.browser', 'backgrid',
'alertify', 'sources/size_prettify'
], function(gettext, _, S, $, pgBrowser, Backgrid, Alertify, sizePrettify) {
@ -350,7 +351,7 @@ define([
__createSingleLineStatistics: function(data, prettifyFields) {
var row = data['rows'][0],
columns = data['columns']
columns = data['columns'],
res = [];
this.columns = this.statistic_columns;

View File

@ -1,7 +1,7 @@
define (
'pgadmin.misc.explain',
['jquery', 'underscore', 'underscore.string', 'pgadmin', 'backbone', 'snap.svg'],
function($, _, S, pgAdmin, Backbone, Snap) {
['sources/url_for', 'jquery', 'underscore', 'underscore.string', 'pgadmin', 'backbone', 'snapsvg'],
function(url_for, $, _, S, pgAdmin, Backbone, Snap) {
pgAdmin = pgAdmin || window.pgAdmin || {};
var pgExplain = pgAdmin.Explain;
@ -86,7 +86,7 @@ if (pgAdmin.Explain)
var pgExplain = pgAdmin.Explain = {
// Prefix path where images are stored
prefix: '{{ url_for('misc.static', filename='explain/img') }}/'
prefix: url_for('misc.index') + 'static/explain/img/'
};
/*
@ -198,8 +198,10 @@ var imageMapper = {
}
// Some predefined constants used to calculate image location and its border
var pWIDTH = pHEIGHT = 100.
IMAGE_WIDTH = IMAGE_HEIGHT = 50;
var pWIDTH =100.;
var pHEIGHT = 100.;
var IMAGE_WIDTH =50;
var IMAGE_HEIGHT = 50;
var offsetX = 200,
offsetY = 60;
var ARROW_WIDTH = 10,
@ -214,7 +216,7 @@ var xMargin = 25,
var MIN_ZOOM_FACTOR = 0.01,
MAX_ZOOM_FACTOR = 2,
INIT_ZOOM_FACTOR = 1;
ZOOM_RATIO = 0.05;
var ZOOM_RATIO = 0.05;
// Backbone model for each plan property of input JSON object
@ -589,7 +591,7 @@ _.extend(
}).appendTo(zoomArea).append(
$('<i></i>',{
class: 'fa fa-arrows-alt'
}))
})),
zoomOutBtn = $('<button></button>', {
class: 'btn pg-explain-zoom-btn badge',
title: 'Zoom out'

View File

@ -1,4 +1,4 @@
define([
define('pgadmin.preferences', [
'sources/gettext', 'sources/url_for', 'jquery', 'underscore', 'alertify',
'pgadmin', 'backform', 'pgadmin.browser', 'pgadmin.backform'
], function(gettext, url_for, $, _, alertify, pgAdmin, Backform, pgBrowser) {

View File

@ -1,4 +1,4 @@
define(
define('pgadmin.settings',
[
'jquery', 'alertify', 'pgadmin', 'underscore', 'backform',
'sources/gettext', 'sources/url_for', 'pgadmin.backform'

View File

@ -1,9 +0,0 @@
import React from 'react';
import {render} from 'react-dom';
import QueryHistory from '../jsx/history/query_history';
export {
render,
React,
QueryHistory,
};

View File

@ -1,6 +1,4 @@
import 'slickgrid/slick.grid.css';
import 'slickgrid/slick-default-theme.css';
import 'slickgrid/css/smoothness/jquery-ui-1.11.3.custom.css';
import 'slickgrid/lib/jquery.event.drag-2.3.0';
import 'slickgrid/slick.core';
import 'slickgrid/slick.grid';
import 'slickgrid/slick.dataview';
@ -9,6 +7,5 @@ import 'slickgrid/slick.formatters';
import 'slickgrid/plugins/slick.autotooltips';
import 'slickgrid/plugins/slick.cellrangedecorator';
import 'slickgrid/plugins/slick.cellrangeselector';
import 'slickgrid/lib/jquery.event.drag-2.3.0';
export default window.Slick;

View File

@ -1321,3 +1321,17 @@ body {
.pg-panel-depends-container table {
font-size: 12px !important;
}
.backgrid tr th button {
background: none;
border: none;
color: #fff;
padding: 0;
}
/* Latest backgrid adds column name like `label` to td element, override color*/
.backgrid td.label {
color: #333;
font-size: 14px;
font-weight: normal;
}

View File

@ -68,4 +68,8 @@
width: 100%;
padding-left: 5px;
position: absolute;
}
.CodeMirror-gutters {
z-index: 2;
}

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