enrolments MDL-24317 Permission filter now remembers what you type into it.
This commit is contained in:
+2
-1
@@ -85,7 +85,8 @@ abstract class capability_table_base {
|
||||
public function display() {
|
||||
if (count($this->capabilities) > capability_table_base::NUM_CAPS_FOR_SEARCH) {
|
||||
global $PAGE;
|
||||
$PAGE->requires->js_init_call('M.core_role.init_cap_table_filter', array($this->id, get_string('filter'), get_string('clear')));
|
||||
$PAGE->requires->strings_for_js(array('filter','clear'),'moodle');
|
||||
$PAGE->requires->js_init_call('M.core_role.init_cap_table_filter', array($this->id, $this->context->id));
|
||||
}
|
||||
echo '<table class="' . implode(' ', $this->classes) . '" id="' . $this->id . '">' . "\n<thead>\n";
|
||||
echo '<tr><th class="name" align="left" scope="col">' . get_string('capability','role') . '</th>';
|
||||
|
||||
+146
-98
@@ -1,118 +1,166 @@
|
||||
/* This class filters the rows of a table like the one on the define or
|
||||
override roles pages. It adds a search box just above the table, and if
|
||||
content is typed into that box, it hides any rows in the table where the
|
||||
capability name does not contain that text. */
|
||||
/**
|
||||
* This class filters the rows of a table like the one on the define or
|
||||
* override roles pages. It adds a search box just above the table, and if
|
||||
* content is typed into that box, it hides any rows in the table where the
|
||||
* capability name does not contain that text.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Role namespace
|
||||
*/
|
||||
M.core_role = {};
|
||||
|
||||
M.core_role.init_cap_table_filter = function(Y, tableid, strsearch, strclear) {
|
||||
var CapTableFilter = function(tableid, strsearch, strclear) {
|
||||
this.delayhandle = -1,
|
||||
this.searchdelay = 100, // milliseconds
|
||||
/**
|
||||
* @param {YUI} Y
|
||||
* @param {string} tableid
|
||||
* @param {int} contextid
|
||||
*/
|
||||
M.core_role.init_cap_table_filter = function(Y, tableid, contextid) {
|
||||
|
||||
// Find the form controls.
|
||||
this.table = document.getElementById(tableid);
|
||||
|
||||
// Create a div to hold the search UI.
|
||||
this.div = document.createElement('div');
|
||||
this.div.className = 'capabilitysearchui';
|
||||
this.div.style.width = this.table.offsetWidth + 'px';
|
||||
|
||||
// Create the capability search input.
|
||||
this.input = document.createElement('input');
|
||||
this.input.type = 'text';
|
||||
this.input.id = tableid + 'capabilitysearch';
|
||||
|
||||
// Create a label for the search input.
|
||||
this.label = document.createElement('label');
|
||||
this.label.htmlFor = this.input.id;
|
||||
this.label.appendChild(document.createTextNode(strsearch + ' '));
|
||||
|
||||
// Create a clear button to clear the input.
|
||||
this.button = document.createElement('input');
|
||||
this.button.value = strclear;
|
||||
this.button.type = 'button';
|
||||
this.button.disabled = true;
|
||||
|
||||
// Tie it all together
|
||||
this.div.appendChild(this.label);
|
||||
this.div.appendChild(this.input);
|
||||
this.div.appendChild(this.button);
|
||||
this.table.parentNode.insertBefore(this.div, this.table);
|
||||
Y.on('keyup', this.change, this.input, this);
|
||||
Y.on('click', this.clear, this.button, this);
|
||||
|
||||
// Horrible hack!
|
||||
var hidden = document.createElement('input');
|
||||
hidden.type = 'hidden';
|
||||
hidden.disabled = true;
|
||||
this.div.appendChild(hidden);
|
||||
hidden = document.createElement('input');
|
||||
hidden.type = 'hidden';
|
||||
hidden.disabled = true;
|
||||
this.div.appendChild(hidden);
|
||||
var CapTableFilter = function(tableid) {
|
||||
this.tableid = tableid;
|
||||
this.context = contextid;
|
||||
this.initializer();
|
||||
};
|
||||
CapTableFilter.prototype = {
|
||||
tableid : null, // ID of the cap table
|
||||
context : null, // Context ID associated with what ever we are looking at
|
||||
delayhandle : -1,
|
||||
searchdelay : 100, // milliseconds
|
||||
table : null,
|
||||
div : null,
|
||||
input : null,
|
||||
label : null,
|
||||
button : null,
|
||||
/**
|
||||
* Initialises the CapTableFilter object.
|
||||
* This is called initializer so that a move to convert this to a proper
|
||||
* YUI module will be easier.
|
||||
*/
|
||||
initializer : function() {
|
||||
// Get any existing filter value
|
||||
var filtervalue = this.getFilterCookieValue();
|
||||
|
||||
CapTableFilter.prototype.clear = function () {
|
||||
this.input.value = '';
|
||||
if (this.delayhandle != -1) {
|
||||
clearTimeout(this.delayhandle);
|
||||
this.delayhandle = -1;
|
||||
}
|
||||
this.filter();
|
||||
};
|
||||
// Find the form controls.
|
||||
this.table = Y.one('#'+this.tableid);
|
||||
|
||||
CapTableFilter.prototype.change = function() {
|
||||
var self = this;
|
||||
var handle = setTimeout(function(){self.filter();}, this.searchdelay);
|
||||
if (this.delayhandle != -1) {
|
||||
clearTimeout(this.delayhandle);
|
||||
}
|
||||
this.delayhandle = handle;
|
||||
};
|
||||
// Create a div to hold the search UI.
|
||||
this.div = Y.Node.create('<div class="capabilitysearchui"></div>').setStyle('width', this.table.get('offsetWidth'));
|
||||
// Create the capability search input.
|
||||
this.input = Y.Node.create('<input type="text" id="'+this.table.get('id')+'capabilitysearch" value="'+filtervalue+'" />');
|
||||
// Create a label for the search input.
|
||||
this.label = Y.Node.create('<label for="'+this.input.get('id')+'">'+M.str.moodle.filter+' </label>');
|
||||
// Create a clear button to clear the input.
|
||||
this.button = Y.Node.create('<input type="button" value="'+M.str.moodle.clear+'" />').set('disabled', filtervalue=='');
|
||||
|
||||
CapTableFilter.prototype.set_visible = function(row, visible) {
|
||||
if (visible) {
|
||||
Y.one(row).removeClass('hiddenrow');
|
||||
} else {
|
||||
Y.one(row).addClass('hiddenrow');
|
||||
}
|
||||
};
|
||||
// Tie it all together
|
||||
this.div.append(this.label).append(this.input).append(this.button);
|
||||
|
||||
CapTableFilter.prototype.filter = function() {
|
||||
var filtertext = this.input.value.toLowerCase();
|
||||
this.button.disabled = (filtertext == '');
|
||||
var lastheading = null;
|
||||
var capssincelastheading = 0;
|
||||
// Insert it into the div
|
||||
this.table.ancestor().insert(this.div, this.table);
|
||||
|
||||
Y.all('#'+this.table.id+' tr').each(function(row, index, list) {
|
||||
if (row.hasClass('rolecapheading')) {
|
||||
if (lastheading) {
|
||||
this.set_visible(lastheading, capssincelastheading > 0);
|
||||
}
|
||||
lastheading = row;
|
||||
capssincelastheading = 0;
|
||||
// Wire the events so it actually does something
|
||||
this.input.on('keyup', this.change, this);
|
||||
this.button.on('click', this.clear, this);
|
||||
|
||||
if (filtervalue != '') {
|
||||
this.filter();
|
||||
}
|
||||
if (row.hasClass('rolecap')) {
|
||||
var capname = row.one('.cap-name').get('text') + '|' + row.one('.cap-desc a').get('text').toLowerCase();
|
||||
if (capname.indexOf(filtertext) >= 0) {
|
||||
this.set_visible(row, true);
|
||||
capssincelastheading += 1;
|
||||
} else {
|
||||
this.set_visible(row, false);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Sets a cookie that describes the filter value.
|
||||
* The cookie stores the context, and the time it was created and upon
|
||||
* retrieval is checked to ensure that the cookie is for the correct
|
||||
* context and is no more than an hour old.
|
||||
*/
|
||||
setFilterCookieValue : function(value) {
|
||||
var cookie = {
|
||||
fltcontext : this.context,
|
||||
flttime : new Date().getTime(),
|
||||
fltvalue : value
|
||||
}
|
||||
}, this);
|
||||
Y.Cookie.setSubs("captblflt", cookie);
|
||||
},
|
||||
/**
|
||||
* Gets the existing filter value if there is one.
|
||||
* The cookie stores the context, and the time it was created and upon
|
||||
* retrieval is checked to ensure that the cookie is for the correct
|
||||
* context and is no more than an hour old.
|
||||
*/
|
||||
getFilterCookieValue : function() {
|
||||
var cookie = Y.Cookie.getSubs('captblflt');
|
||||
if (cookie.fltcontext && cookie.fltcontext == this.context && parseInt(cookie.flttime) > new Date().getTime()-(60*60*1000)) {
|
||||
return cookie.fltvalue;
|
||||
}
|
||||
return '';
|
||||
},
|
||||
/**
|
||||
* Clears the filter value.
|
||||
*/
|
||||
clear : function() {
|
||||
this.input.set('value', '');
|
||||
if (this.delayhandle != -1) {
|
||||
clearTimeout(this.delayhandle);
|
||||
this.delayhandle = -1;
|
||||
}
|
||||
this.filter();
|
||||
},
|
||||
/**
|
||||
* Event callback for when the filter value changes
|
||||
*/
|
||||
change : function() {
|
||||
var self = this;
|
||||
var handle = setTimeout(function(){self.filter();}, this.searchdelay);
|
||||
if (this.delayhandle != -1) {
|
||||
clearTimeout(this.delayhandle);
|
||||
}
|
||||
this.delayhandle = handle;
|
||||
},
|
||||
/**
|
||||
* Marks a row as visible or hidden
|
||||
*/
|
||||
setVisible : function(row, visible) {
|
||||
if (visible) {
|
||||
row.removeClass('hiddenrow');
|
||||
} else {
|
||||
row.addClass('hiddenrow');
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Filters the capability table
|
||||
*/
|
||||
filter : function() {
|
||||
var filtertext = this.input.get('value').toLowerCase(),
|
||||
lastheading = null;
|
||||
|
||||
if (lastheading) {
|
||||
this.set_visible(lastheading, capssincelastheading > 0);
|
||||
this.setFilterCookieValue(filtertext);
|
||||
|
||||
this.button.set('disabled', (filtertext == ''));
|
||||
|
||||
this.table.all('tr').each(function(row){
|
||||
if (row.hasClass('rolecapheading')) {
|
||||
this.setVisible(row, false);
|
||||
lastheading = row;
|
||||
}
|
||||
if (row.hasClass('rolecap')) {
|
||||
var capname = row.one('.cap-name').get('text') + '|' + row.one('.cap-desc a').get('text').toLowerCase();
|
||||
if (capname.indexOf(filtertext) >= 0) {
|
||||
this.setVisible(row, true);
|
||||
if (lastheading) {
|
||||
this.setVisible(lastheading, true);
|
||||
lastheading = null;
|
||||
}
|
||||
} else {
|
||||
this.setVisible(row, false);
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
new CapTableFilter(tableid, strsearch, strclear);
|
||||
new CapTableFilter(tableid);
|
||||
};
|
||||
|
||||
|
||||
M.core_role.init_add_assign_page = function(Y) {
|
||||
var add = Y.one('#add');
|
||||
var addselect = M.core_user.get_user_selector('addselect');
|
||||
|
||||
@@ -418,7 +418,8 @@ class page_requirements_manager {
|
||||
break;
|
||||
case 'core_role':
|
||||
$module = array('name' => 'core_role',
|
||||
'fullpath' => '/admin/roles/module.js');
|
||||
'fullpath' => '/admin/roles/module.js',
|
||||
'requires' => array('node', 'cookie'));
|
||||
break;
|
||||
case 'core_completion':
|
||||
$module = array('name' => 'core_completion',
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#page-admin-uploaduser table#uuresults {font-size: 0.9em;}
|
||||
#page-admin-auth_config .required {background-color:#DDDDDD;}
|
||||
#page-admin-report-unittest-index .sep {color:#AAAAAA;}
|
||||
.path-admin-roles .capabilitysearchui {text-align:center;margin:0.5em;}
|
||||
|
||||
.path-admin .rolecap .cap-name,
|
||||
.path-admin .rolecap .note {color: #888;font-size: 0.75em;}
|
||||
|
||||
Reference in New Issue
Block a user