--- a/src/pyams_skin/resources/js/myams.js Sun Nov 26 10:09:52 2017 +0100
+++ b/src/pyams_skin/resources/js/myams.js Sun Nov 26 10:14:21 2017 +0100
@@ -2,7 +2,7 @@
* MyAMS
* « My Application Management Skin »
*
- * $Tag$ (rev. 1)
+ * $Tag: 0.1.11 $ (rev. 1)
* A bootstrap based application/administration skin
*
* Custom administration and application skin tools
@@ -3205,6 +3205,69 @@
},
/**
+ * Treeview plug-in
+ */
+ treeview: function(element) {
+ var treeviews = $('.treeview', element);
+ if (treeviews.length > 0) {
+ ams.ajax.check($.fn.treview,
+ ams.baseURL + 'ext/bootstrap-treeview' + ams.devext + '.js',
+ function(first_load) {
+ if (first_load) {
+ ams.getCSS(ams.baseURL + '../css/ext/bootstrap-treeview' + ams.devext + '.css', 'bootstrap-treeview');
+ }
+ treeviews.each(function() {
+ var treeview = $(this);
+ var data = treeview.data();
+ var dataOptions = {
+ data: data.amsTreeviewData,
+ levels: data.amsTreeviewLevels,
+ injectStyle: data.amsTreeviewInjectStyle,
+ expandIcon: data.amsTreeviewExpandIcon || 'fa fa-fw fa-plus-square-o',
+ collapseIcon: data.amsTreeviewCollaspeIcon || 'fa fa-fw fa-minus-square-o',
+ emptyIcon: data.amsTreeviewEmptyIcon || 'fa fa-fw',
+ nodeIcon: data.amsTreeviewNodeIcon,
+ selectedIcon: data.amsTreeviewSelectedIcon,
+ checkedIcon: data.amsTreeviewCheckedIcon || 'fa fa-fw fa-check-square-o',
+ uncheckedIcon: data.amsTreeviewUncheckedIcon || 'fa fa-fw fa-square-o',
+ color: data.amsTreeviewColor,
+ backColor: data.amsTreeviewBackColor,
+ borderColor: data.amsTreeviewBorderColor,
+ onHoverColor: data.amsTreeviewHoverColor,
+ selectedColor: data.amsTreeviewSelectedColor,
+ selectedBackColor: data.amsTreeviewSelectedBackColor,
+ unselectableColor: data.amsTreeviewUnselectableColor || 'rgba(1,1,1,0.25)',
+ unselectableBackColor: data.amsTreeviewUnselectableBackColor || 'rgba(1,1,1,0.25)',
+ enableLinks: data.amsTreeviewEnableLinks,
+ highlightSelected: data.amsTreeviewHighlightSelected,
+ highlightSearchResults: data.amsTreeviewhighlightSearchResults,
+ showBorder: data.amsTreeviewShowBorder,
+ showIcon: data.amsTreeviewShowIcon,
+ showCheckbox: data.amsTreeviewShowCheckbox,
+ showTags: data.amsTreeviewShowTags,
+ toggleUnselectable: data.amsTreeviewToggleUnselectable,
+ multiSelect: data.amsTreeviewMultiSelect,
+ onNodeChecked: ams.getFunctionByName(data.amsTreeviewNodeChecked),
+ onNodeCollapsed: ams.getFunctionByName(data.amsTreeviewNodeCollapsed),
+ onNodeDisabled: ams.getFunctionByName(data.amsTreeviewNodeDisabled),
+ onNodeEnabled: ams.getFunctionByName(data.amsTreeviewNodeEnabled),
+ onNodeExpanded: ams.getFunctionByName(data.amsTreeviewNodeExpanded),
+ onNodeSelected: ams.getFunctionByName(data.amsTreeviewNodeSelected),
+ onNodeUnchecked: ams.getFunctionByName(data.amsTreeviewNodeUnchecked),
+ onNodeUnselected: ams.getFunctionByName(data.amsTreeviewNodeUnselected),
+ onSearchComplete: ams.getFunctionByName(data.amsTreeviewSearchComplete),
+ onSearchCleared: ams.getFunctionByName(data.amsTreeviewSearchCleared)
+ };
+ var settings = $.extend({}, dataOptions, data.amsTreeviewOptions);
+ settings = ams.executeFunctionByName(data.amsTreeviewInitcallback, treeview, settings) || settings;
+ var plugin = treeview.treeview(settings);
+ ams.executeFunctionByName(data.amsTreeviewAfterInitCallback, treeview, plugin, settings);
+ });
+ });
+ }
+ },
+
+ /**
* Select2 plug-in
*/
select2: function(element) {
@@ -3970,29 +4033,32 @@
if (target) {
// Disable row click handler
$(row).data('ams-disabled-handlers', 'click');
- var rows = [];
- $(dnd_table.rows).each(function() {
- var rowId = $(this).data('ams-element-name');
- if (rowId) {
- rows.push(rowId);
+ try {
+ var rows = [];
+ $(dnd_table.rows).each(function() {
+ var rowId = $(this).data('ams-element-name');
+ if (rowId) {
+ rows.push(rowId);
+ }
+ });
+ var localTarget = ams.getFunctionByName(target);
+ if (typeof(localTarget) === 'function') {
+ localTarget.call(table, dnd_table, rows);
+ } else {
+ if (!target.startsWith(window.location.protocol)) {
+ var location = data.amsLocation;
+ if (location) {
+ target = location + '/' + target;
+ }
+ }
+ ams.ajax.post(target, {names: JSON.stringify(rows)});
}
- });
- var localTarget = ams.getFunctionByName(target);
- if (typeof(localTarget) === 'function') {
- localTarget.call(table, dnd_table, rows);
- } else {
- if (!target.startsWith(window.location.protocol)) {
- var location = data.amsLocation;
- if (location) {
- target = location + '/' + target;
- }
- }
- ams.ajax.post(target, {names: JSON.stringify(rows)});
+ } finally {
+ // Restore row click handler
+ setTimeout(function() {
+ $(row).removeData('ams-disabled-handlers');
+ }, 50);
}
- // Restore row click handler
- setTimeout(function() {
- $(row).removeData('ams-disabled-handlers');
- }, 50);
}
return false;
}
@@ -4552,9 +4618,9 @@
buttons: ams.i18n.BTN_OK_CANCEL
}, function(button) {
if (button === ams.i18n.BTN_OK) {
- var table = link.parents('table').first();
- var location = table.data('ams-location') || '';
var tr = link.parents('tr').first();
+ var table = tr.parents('table').first();
+ var location = tr.data('ams-location') || table.data('ams-location') || '';
var deleteTarget = tr.data('ams-delete-target') || table.data('ams-delete-target') || 'delete-element.json';
var objectName = tr.data('ams-element-name');
MyAMS.ajax.post(location + '/' + deleteTarget, {'object_name': objectName}, function(result, status) {
@@ -4579,6 +4645,226 @@
/**
+ * Tree management
+ */
+ MyAMS.tree = {
+
+ /**
+ * Open close tree node inside a table
+ */
+ switchTableNode: function() {
+
+ function removeChildNodes(node_id) {
+ $('tr[data-ams-tree-node-parent-id="' + node_id + '"]').each(function() {
+ var row = $(this);
+ removeChildNodes(row.data('ams-tree-node-id'));
+ row.remove();
+ })
+ }
+
+ var node = $(this);
+ var switcher = $('i.switch', node);
+ var tr = node.parents('tr').first();
+ var table = tr.parents('table').first();
+ if (switcher.hasClass('fa-minus-square-o')) {
+ removeChildNodes(tr.data('ams-tree-node-id'));
+ switcher.removeClass('fa-minus-square-o')
+ .addClass('fa-plus-square-o');
+ } else {
+ var location = tr.data('ams-location') || table.data('ams-location') || '';
+ var treeNodesTarget = tr.data('ams-tree-nodes-target') || table.data('ams-tree-nodes-target') || 'get-tree-nodes.json';
+ var sourceName = tr.data('ams-element-name');
+ switcher.removeClass('fa-plus-square-o')
+ .addClass('fa-cog fa-spin');
+ MyAMS.ajax.post(location + '/' + sourceName + '/' + treeNodesTarget, {
+ can_sort: !$('td.sorter', tr).is(':empty')
+ }, function(result, status) {
+ if (result.length > 0) {
+ var old_row = tr;
+ for (var index = 0; index < result.length; index++) {
+ var new_row = $(result[index]);
+ new_row.insertAfter(old_row)
+ .addClass('no-drag-handle');
+ ams.initContent(new_row);
+ old_row = new_row;
+ }
+ if (table.hasClass('table-dnd')) {
+ table.tableDnDUpdate();
+ }
+ }
+ switcher.removeClass('fa-cog fa-spin')
+ .addClass('fa-minus-square-o');
+ });
+ }
+ },
+
+ /**
+ * Open close all tree nodes
+ */
+ switchTree: function() {
+ var th = $(this);
+ var switcher = $('i.switch', th);
+ var table = $(this).parents('table').first();
+ var tableID = table.data('ams-tree-node-id');
+ if (switcher.hasClass('fa-minus-square-o')) {
+ $('tr[data-ams-tree-node-parent-id]').filter('tr[data-ams-tree-node-parent-id!="' + tableID + '"]').remove();
+ $('i.switch', table).removeClass('fa-minus-square-o')
+ .addClass('fa-plus-square-o');
+ } else {
+ var tr = $('tbody tr', table).first();
+ var location = table.data('ams-location') || '';
+ var target = table.data('ams-tree-nodes-target') || 'get-tree.json';
+ switcher.removeClass('fa-plus-square-o')
+ .addClass('fa-cog fa-spin');
+ MyAMS.ajax.post(location + '/' + target, {
+ can_sort: !$('td.sorter', tr).is(':empty')
+ }, function(result, status) {
+ $('tr[data-ams-tree-node-id]', table).remove();
+ var old_row = null;
+ for (var index = 0; index < result.length; index++) {
+ var new_row = $(result[index]);
+ if (old_row === null) {
+ new_row.appendTo($('tbody', table));
+ } else {
+ new_row.insertAfter(old_row);
+ }
+ new_row.addClass('no-drag-handle');
+ ams.initContent(new_row);
+ old_row = new_row;
+ }
+ if (table.hasClass('table-dnd')) {
+ table.tableDnDUpdate();
+ }
+ $('i.switch', table).removeClass('fa-plus-square-o')
+ .addClass('fa-minus-square-o');
+ switcher.removeClass('fa-cog fa-spin')
+ .addClass('fa-minus-square-o');
+ });
+ }
+ },
+
+ /**
+ * Sort and re-parent tree elements
+ */
+ sortTree: function(dnd_table, row) {
+ var data = $(dnd_table).data();
+ var target = data.amsTabledndDropTarget;
+ if (target) {
+ // Disable row click handler
+ row = $(row);
+ row.data('ams-disabled-handlers', 'click');
+ try {
+ // Get root ID
+ var tableID = row.parents('table').first().data('ams-tree-node-id');
+ // Get moved row ID
+ var rowID = row.data('ams-tree-node-id');
+ var rowParentID = row.data('ams-tree-node-parent-id');
+ // Get new parent ID
+ var parent = row.prev('tr');
+ if (parent.exists()) {
+ // Move below an existing row
+ var parentID = parent.data('ams-tree-node-id');
+ // Check switcher state
+ var switcher = $('.switch', parent);
+ if (switcher.hasClass('fa-minus-square-o')) {
+ // Opened folder: move as child
+ if (rowParentID === parentID) {
+ // Don't change parent
+ var action = 'reorder';
+ } else {
+ // Change parent
+ action = 'reparent';
+ }
+ } else {
+ // Closed folder or simple item: move as sibling
+ parentID = parent.data('ams-tree-node-parent-id');
+ if (rowParentID === parentID) {
+ // Don't change parent
+ action = 'reorder';
+ } else {
+ // Change parent
+ action = 'reparent';
+ }
+ }
+ } else {
+ // Move to site root
+ parentID = tableID;
+ switcher = null;
+ if (rowParentID === parentID) {
+ // Already child of site root
+ action = 'reorder';
+ } else {
+ // Move from inner folder to site root
+ action = 'reparent';
+ }
+ }
+ // Call ordering target
+ var localTarget = ams.getFunctionByName(target);
+ if (typeof(localTarget) === 'function') {
+ localTarget.call(table, dnd_table, post_data);
+ } else {
+ if (!target.startsWith(window.location.protocol)) {
+ var location = data.amsLocation;
+ if (location) {
+ target = location + '/' + target;
+ }
+ }
+ var post_data = {
+ action: action,
+ child: rowID,
+ parent: parentID,
+ order: JSON.stringify($('tr[data-ams-tree-node-id]').listattr('data-ams-tree-node-id')),
+ can_sort: !$('td.sorter', row).is(':empty')
+ };
+ ams.ajax.post(target, post_data, function(result) {
+
+ function removeChildRows(rowID) {
+ var childs = $('tr[data-ams-tree-node-parent-id="' + rowID + '"]');
+ childs.each(function() {
+ var childRow = $(this);
+ var childID = childRow.attr('data-ams-tree-node-id');
+ removeChildRows(childID);
+ childRow.remove();
+ });
+ }
+
+ // Remove moved row childrens
+ var body = $(row).parents('tbody').first();
+ removeChildRows(rowID);
+ if (post_data.action === 'reparent') {
+ // Remove new parent childrens
+ removeChildRows(parentID);
+ row.remove();
+ var old_row = $('tr[data-ams-tree-node-id="' + parentID + '"]');
+ for (var index = 0; index < result.length; index++) {
+ var new_row = $(result[index]);
+ if (old_row.exists()) {
+ new_row.insertAfter(old_row)
+ .addClass('no-drag-handle');
+ } else {
+ new_row.prependTo(body)
+ .addClass('no-drag-handle');
+ }
+ ams.initContent(new_row);
+ old_row = new_row;
+ }
+ }
+ $('tr').parents('table').tableDnDUpdate();
+ });
+ }
+ } finally {
+ // Restore row click handler
+ setTimeout(function() {
+ $(row).removeData('ams-disabled-handlers');
+ }, 50);
+ }
+ }
+ return false;
+ }
+ };
+
+
+ /**
* Generic skin features
*/
MyAMS.skin = {
@@ -4651,6 +4937,57 @@
},
/**
+ * Replace given form with new content
+ */
+ refreshContent: function(changes) {
+ var target = $('[id="' + changes.object_id + '"]');
+ target.replaceWith($(changes.content));
+ target = $('[id="' + changes.object_id + '"]');
+ MyAMS.initContent(target);
+ return target;
+ },
+
+ /**
+ * Replace given table with new content
+ */
+ refreshTable: function(changes) {
+ var widget = $('[id="' + changes.object_id + '"]').parent('.ams-widget');
+ widget.replaceWith($(changes.table));
+ widget = $('[id="' + changes.object_id + '"]').parent('.ams-widget');
+ MyAMS.initContent(widget);
+ return widget;
+ },
+ /**
+ * Replace given row with new content
+ */
+ refreshRow: function(changes) {
+ var tr = $('tr[id="' + changes.object_id + '"]');
+ var table = tr.parents('table').first();
+ tr = tr.replaceWith($(changes.row));
+ MyAMS.initContent(tr);
+ if (table.hasClass('table-dnd')) {
+ table.tableDnDUpdate();
+ }
+ return tr;
+ },
+
+ /**
+ * Replace given row cell with new content
+ */
+ refreshRowCell: function(changes) {
+ var tr = $('tr[id="' + changes.object_id + '"]');
+ var table = tr.parents('table').first();
+ var headRow = $('tr', $('thead', table));
+ var headCell = $('th[data-ams-column-name="' + changes.col_name + '"]', headRow);
+ var index = $('th', headRow).index(headCell);
+ if (index > -1) {
+ var cell = $($('td', tr).get(index));
+ cell.html(changes.cell);
+ MyAMS.initContent(cell);
+ }
+ },
+
+ /**
* Initialize desktop and mobile widgets
*/
_initDesktopWidgets: function(element) {
@@ -5527,6 +5864,11 @@
});
});
+ // Enable custom MyAMS refresh events
+ $(document).on('myams.refresh', function(event, settings) {
+ MyAMS.executeFunctionByName(settings.handler || MyAMS.skin.refreshContent, event.target, settings);
+ });
+
// Init page content
ams.initContent(document);
if (ams.ajaxNav && nav.exists()) {