Skip to content

Commit

Permalink
Add support for multi-selection
Browse files Browse the repository at this point in the history
Add classes to handle multi-row selection using the CTRL-Key and to
create the link for the selected query.

refs #3788
  • Loading branch information
majentsch committed Oct 17, 2013
1 parent da5f1bb commit 308a22f
Show file tree
Hide file tree
Showing 3 changed files with 353 additions and 8 deletions.
54 changes: 46 additions & 8 deletions public/js/icinga/components/mainDetailGrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,17 @@
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}}
define(['components/app/container', 'jquery', 'logging', 'URIjs/URI', 'URIjs/URITemplate'],
function(Container, $, logger, URI) {
define(
[
'components/app/container',
'jquery',
'logging',
'icinga/selection/selectable',
'icinga/selection/multiSelection',
'URIjs/URI',
'URIjs/URITemplate'
],
function(Container, $, logger, Selectable, TableMultiSelection, URI) {
"use strict";

/**
Expand Down Expand Up @@ -65,6 +74,13 @@ function(Container, $, logger, URI) {
*/
var controlForms;

/**
* Handles multi-selection
*
* @type {TableMultiSelection}
*/
var selection;

/**
* Detect and select control forms for this table and return them
*
Expand Down Expand Up @@ -131,7 +147,7 @@ function(Container, $, logger, URI) {

if (a.length) {
// test if the URL is on the current server, if not open it directly
if (true || Container.isExternalLink(a.attr('href'))) {
if (Container.isExternalLink(a.attr('href'))) {
return true;
}
} else if ($.inArray('input', nodeNames) > -1 || $.inArray('button', nodeNames) > -1) {
Expand All @@ -141,17 +157,35 @@ function(Container, $, logger, URI) {
}
}

Container.getDetailContainer().replaceDomFromUrl($('a', this).attr('href'));
if (!ev.ctrlKey && !ev.metaKey) {
$('tr', $(this).parent()).removeClass('active');
var selectable = new Selectable(this);
if (ev.ctrlKey || ev.metaKey) {
selection.toggle(selectable);
} else if (ev.shiftKey) {
// select range ?
selection.add(selectable);
} else {
selection.clear();
selection.add(selectable);
}

$(this).addClass('active');
// TODO: Detail target
var url = URI($('a', this).attr('href'));
var segments = url.segment();
if (selection.size() === 0) {
// don't open anything
url.search('?');
} else if (selection.size() > 1 && segments.length > 3) {
// open detail view for multiple objects
segments[2] = 'multi';
url.pathname(segments.join('/'));
url.search('?');
url.setSearch(selection.toQuery());
}
Container.getDetailContainer().replaceDomFromUrl(url);
return false;
});
};


/**
* Register submit handler for the form controls (sorting, filtering, etc). Reloading happens in the
* current container
Expand Down Expand Up @@ -214,6 +248,10 @@ function(Container, $, logger, URI) {
this.container.removeDefaultLoadIndicator();
controlForms = determineControlForms();
contentNode = determineContentTable();
selection = new TableMultiSelection(
contentNode,
Container.getDetailContainer().getContainerHref()
);
this.registerControls();
this.registerTableLinks();
this.registerHistoryChanges();
Expand Down
224 changes: 224 additions & 0 deletions public/js/icinga/selection/multiSelection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga 2 Web.
*
* Icinga 2 Web - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}}
define(
['jquery', 'URIjs/URI', 'icinga/selection/selectable'],
function($, URI, Selectable) {
"use strict";

/**
* Handle the multi-selection of table rows and generate the query string
* that can be used to open the selected items.
*
* NOTE: After each site reload, the state (the current selection) of this object will be
* restored automatically. The selectable items are determined by finding all TR elements
* in the targeted table. The active selection is determined by checking the query elements
* of the given url.
*
* @param {HtmlElement} The table that contains the selectable rows.
*
* @param {Object} The query that contains the selected rows.
*/
return function MultiSelection(table, detailUrl) {
var self = this;
/**
* Contains all selected selectables
*
* @type {Object}
*/
var selection = {};

/**
* If the selectable was already added, remove it, otherwise add it.
*
* @param {Selectable} The selectable to use.
*/
this.toggle = function(selectable) {
if (selection[selectable.getId()]) {
self.remove(selectable);
} else {
self.add(selectable);
}
};

/**
* Add the selectable to the current selection.
*
* @param {Selectable} The selectable to use.
*/
this.add = function(selectable) {
selectable.setActive(true);
selection[selectable.getId()] = selectable;
};

/**
* Remove the selectable from the current selection.
*
* @param {Selectable} The selectable to use.
*/
this.remove = function(selectable) {
selectable.setActive(false);
delete selection[selectable.getId()];
};

/**
* Clear the current selection
*/
this.clear = function() {
$.each(selection, function(index, selectable){
selectable.setActive(false);
});
selection = {};
};

/**
* Convert the current selection to its query-representation.
*
* @returns {String} The query
*/
this.toQuery = function() {
var query = {};
var i = 0;
$.each(selection, function(id, selectable) {
$.each(selectable.getQuery(), function(key, value) {
query[key + '[' + i + ']'] = value;
});
i++;
});
return query;
};

this.size = function() {
var size = 0;
$.each(selection, function(){ size++; });
return size;
};

/**
* Fetch the selections from a query containing multiple selections
*/
var selectionFromMultiQuery = function(query) {
var i = 0;
var selections = [];
alert('query ' + JSON.stringify(query));
$.each(query, function(key, value) {
// Fetch the index from the key
var id = key.match(/\[([0-9]+)\]/);
alert(id);
if (id) {
alert('extracted id ' + id[1]);
// Remove the index from the key
key = key.replace(/\[[0-9]+\]/,'');
key = encodeURIComponent(key);
value = encodeURIComponent(value);
// Add it to the array representing this index
if (id[1] !== i) {
// begin a new index
selections[i] = [ key + '=' + value ];
i = id[1];
} else {
selections[i].push(key + '=' + value);
}
}
});
return selections;
};

/**
* Fetch the selections from a default query.
*/
var selectionFromQuery = function(query) {
var selection = [];
$.each(query, function(key, value){
key = encodeURIComponent(key);
value = encodeURIComponent(value);
selection.push(key + '=' + value);
});
return [ selection ];
};

/**
* Restore the selected ids from the given URL.
*
* @param {URI} The used URL
*
* @returns {Array} The selected ids
*/
var restoreSelectionStateUrl = function(url) {
if (!url) {
return [];
}
if (!url.query) {
url = new URI(url);
}
var segments = url.segment();
var parts;
if (segments.length > 2 && segments[1] === 'Multi') {
alert('from multiselection');
parts = selectionFromMultiQuery(url.query(true));
} else {
parts = selectionFromQuery(url.query(true));
}
return $.map(parts, function(part) {
part.sort(function(a, b){
a = a.toUpperCase();
b = b.toUpperCase();
return (a < b ? -1 : (a > b) ? 1 : 0);
});
return part.join('&');
});
};

/**
* Create the selectables from the given table-Html
*/
var createSelectables = function(table) {
var selectables = {};
$(table).find('tr').each(function(i, row) {
var selectable = new Selectable(row);
selectables[selectable.getId()] = selectable;
});
return selectables;
};

/**
* Restore the selectables from the given table and the given url
*/
var restoreSelection = function() {
var selectables = createSelectables(table);
var selected = restoreSelectionStateUrl(detailUrl);
var selection = {};
$.each(selected, function(i, selectionId) {
if (selectables[selectionId]) {
selection[selectionId] = selectables[selectionId];
}
});
return selection;
};

selection = restoreSelection();
};
});
Loading

0 comments on commit 308a22f

Please sign in to comment.