From 9935136f4d6085f3cb6a371c3298fbf3a087ffa0 Mon Sep 17 00:00:00 2001 From: Sam Hemelryk Date: Fri, 28 Jun 2013 12:39:18 +1200 Subject: [PATCH] MDL-40368 tool_capability: overall improvements made * Can now compare multiple capabilities at the same time. * Capability search now persists between requests. * Upgraded to use renderers. * Upgraded module.js to YUI shifted module. * Converted deprecated calls. * Converted forms to Moodleforms. * Implemented backend functionality to overview at different context levels. Not possible presently as there are no front end hooks. --- .../tool/capability/classes/settings_form.php | 62 +++++ admin/tool/capability/index.php | 236 ++++-------------- admin/tool/capability/locallib.php | 95 +++++++ admin/tool/capability/module.js | 75 ------ admin/tool/capability/renderer.php | 136 ++++++++++ admin/tool/capability/styles.css | 32 +++ .../moodle-tool_capability-search-debug.js | 151 +++++++++++ .../moodle-tool_capability-search-min.js | 1 + .../moodle-tool_capability-search.js | 151 +++++++++++ .../tool/capability/yui/src/search/build.json | 10 + .../capability/yui/src/search/js/search.js | 147 +++++++++++ .../yui/src/search/meta/search.json | 8 + 12 files changed, 845 insertions(+), 259 deletions(-) create mode 100644 admin/tool/capability/classes/settings_form.php create mode 100644 admin/tool/capability/locallib.php delete mode 100644 admin/tool/capability/module.js create mode 100644 admin/tool/capability/renderer.php create mode 100644 admin/tool/capability/styles.css create mode 100644 admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-debug.js create mode 100644 admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-min.js create mode 100644 admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search.js create mode 100644 admin/tool/capability/yui/src/search/build.json create mode 100644 admin/tool/capability/yui/src/search/js/search.js create mode 100644 admin/tool/capability/yui/src/search/meta/search.json diff --git a/admin/tool/capability/classes/settings_form.php b/admin/tool/capability/classes/settings_form.php new file mode 100644 index 00000000000..9de1f90b525 --- /dev/null +++ b/admin/tool/capability/classes/settings_form.php @@ -0,0 +1,62 @@ +. + +/** + * Capability tool settings form. + * + * Do no include this file, it is automatically loaded by the class loader! + * + * @package tool_capability + * @copyright 2013 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once($CFG->libdir.'/formslib.php'); + +/** + * Class tool_capability_settings_form + * + * The settings form for the comparison of roles/capabilities. + * + * @copyright 2013 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class tool_capability_settings_form extends moodleform { + + /** + * The form definition. + */ + public function definition() { + $form = $this->_form; + // Set the form ID. + $form->setAttributes(array('id' => 'capability-overview-form') + $form->getAttributes()); + + $form->addElement('header', 'reportsettings', get_string('reportsettings', 'tool_capability')); + $form->addElement('html', html_writer::tag('p', get_string('intro', 'tool_capability'), array('id' => 'intro'))); + + $form->addElement('hidden', 'search'); + $form->setType('search', PARAM_TEXT); + + $form->addElement('select', 'capability', get_string('capabilitylabel', 'tool_capability'), $this->_customdata['capabilities'], array('multiple' => 'multiple', 'size' => 10, 'data-search' => 'capability')); + $form->setType('capability', PARAM_CAPABILITY); + + $form->addElement('select', 'roles', get_string('roleslabel', 'tool_capability'), $this->_customdata['roles'], array('multiple' => 'multiple', 'size' => 10)); + $form->setType('roles', PARAM_TEXT); + + $form->addElement('submit', 'submitbutton', get_string('getreport', 'tool_capability')); + } + +} \ No newline at end of file diff --git a/admin/tool/capability/index.php b/admin/tool/capability/index.php index 3f9c58edd0c..68574c4c1a7 100644 --- a/admin/tool/capability/index.php +++ b/admin/tool/capability/index.php @@ -18,215 +18,83 @@ * For a given capability, show what permission it has for every role, and * everywhere that it is overridden. * - * @package tool - * @subpackage capability + * @package tool_capability * @copyright 2008 Tim Hunt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once(dirname(__FILE__) . '/../../../config.php'); +require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/capability/locallib.php'); require_once($CFG->libdir.'/adminlib.php'); -// Check permissions. -require_login(); -$systemcontext = context_system::instance(); -require_capability('moodle/role:manage', $systemcontext); - // Get URL parameters. -$capability = optional_param('capability', '', PARAM_CAPABILITY); -$roleids = optional_param_array('roles', array('0'), PARAM_INT); +$systemcontext = context_system::instance(); +$contextid = optional_param('context', $systemcontext->id, PARAM_INT); -// Clean the passed in list of role ids. If 'All' selected as an option, or -// if none were selected, do all roles. -$allroles = role_fix_names(get_all_roles()); -$cleanedroleids = array(); -foreach ($roleids as $roleid) { - if ($roleid == 0) { - $cleanedroleids = array_keys($allroles); - break; - } - if (array_key_exists($roleid, $allroles)) { - $cleanedroleids[] = $roleid; - } -} -if (empty($cleanedroleids)) { - $cleanedroleids = array_keys($allroles); -} - -// Include the required JavaScript. -$PAGE->requires->js_init_call('M.tool_capability.init', array(get_string('search'))); - -// Log. -add_to_log(SITEID, "admin", "tool capability", "tool/capability/index.php?capability=$capability", $capability); +// Check permissions. +list($context, $course, $cm) = get_context_info_array($contextid); +require_login($course, false, $cm); +require_capability('moodle/role:manage', $context); // Print the header. admin_externalpage_setup('toolcapability'); -echo $OUTPUT->header(); -// Prepare the list of capabilities to choose from -$allcapabilities = fetch_context_capabilities($systemcontext); +// Prepare the list of capabilities to choose from. $capabilitychoices = array(); -foreach ($allcapabilities as $cap) { +foreach ($context->get_capabilities() as $cap) { $capabilitychoices[$cap->name] = $cap->name . ': ' . get_capability_string($cap->name); } -// Prepare the list of roles to choose from +$allroles = role_fix_names(get_all_roles($context)); +// Prepare the list of roles to choose from. $rolechoices = array('0' => get_string('all')); foreach ($allroles as $role) { $rolechoices[$role->id] = $role->localname; } -if (count($cleanedroleids) == count($allroles)) { - // Select 'All', rather than each role individually. - $selectedroleids = array('0'); -} else { - $selectedroleids = $cleanedroleids; + +$form = new tool_capability_settings_form(null, array( + 'capabilities' => $capabilitychoices, + 'roles' => $rolechoices +)); +$PAGE->requires->yui_module('moodle-tool_capability-search', 'M.tool_capability.init_capability_search', array(array('strsearch' => get_string('search')))); + +// Log. +$capabilities = array(); +$rolestoshow = array(); +$roleids = array('0'); +$cleanedroleids = array(); +if ($data = $form->get_data()) { + $capabilities = $data->capability; + $allrolesids = array_keys($allroles); + + $roleids = $data->roles; + if (in_array('0', $roleids)) { + $rolestoshow = $allroles; + } else { + $cleanedroleids = array_intersect($allrolesids, $roleids); + if (count($cleanedroleids) === 0) { + $rolestoshow = $allroles; + } else { + foreach ($cleanedroleids as $id) { + $rolestoshow[$id] = $allroles[$id]; + } + } + } } -// Print the settings form. -echo $OUTPUT->box_start('generalbox boxwidthwide boxaligncenter'); -echo '
'; -echo $OUTPUT->heading(get_string('reportsettings', 'tool_capability')); -echo '

', get_string('intro', 'tool_capability') , '

'; -echo '

'; -echo html_writer::select($capabilitychoices, 'capability', $capability, array(''=>'choose'), array('size'=>10)); -echo '

'; -echo html_writer::select($rolechoices, 'roles[]', $selectedroleids, false, array('size'=>10, 'multiple'=>'multiple')); -echo '

'; -echo '
'; -echo $OUTPUT->box_end(); +add_to_log(SITEID, "admin", "tool capability", "tool/capability/index.php", count($capabilities)); + +$renderer = $PAGE->get_renderer('tool_capability'); + +echo $OUTPUT->header(); + +$form->display(); // If we have a capability, generate the report. -if ($capability) { - - // Work out the bits needed for the SQL WHERE clauses. - $params = array($capability); - $sqlroletest = ''; - if (count($cleanedroleids) != count($allroles)) { - list($sqlroletest, $roleparams) = $DB->get_in_or_equal($cleanedroleids); - $params = array_merge($params, $roleparams); - $sqlroletest = 'AND roleid ' . $sqlroletest; - } - - // Get all the role_capabilities rows for this capability - that is, all - // role definitions, and all role overrides. - $rolecaps = $DB->get_records_sql(" - SELECT id, roleid, contextid, permission - FROM {role_capabilities} - WHERE capability = ? $sqlroletest", $params); - - // In order to display a nice tree of contexts, we need to get all the - // ancestors of all the contexts in the query we just did. - $relevantpaths = $DB->get_records_sql_menu(" - SELECT DISTINCT con.path, 1 - FROM {context} con JOIN {role_capabilities} rc ON rc.contextid = con.id - WHERE capability = ? $sqlroletest", $params); - $requiredcontexts = array($systemcontext->id); - foreach ($relevantpaths as $path => $notused) { - $requiredcontexts = array_merge($requiredcontexts, explode('/', trim($path, '/'))); - } - $requiredcontexts = array_unique($requiredcontexts); - - // Now load those contexts. - list($sqlcontexttest, $contextparams) = $DB->get_in_or_equal($requiredcontexts); - $contexts = get_sorted_contexts('ctx.id ' . $sqlcontexttest, $contextparams); - - // Prepare some empty arrays to hold the data we are about to compute. - foreach ($contexts as $conid => $con) { - $contexts[$conid]->children = array(); - $contexts[$conid]->rolecapabilities = array(); - } - - // Put the contexts into a tree structure. - foreach ($contexts as $conid => $con) { - $context = context::instance_by_id($conid); - $parentcontextid = get_parent_contextid($context); - if ($parentcontextid) { - $contexts[$parentcontextid]->children[] = $conid; - } - } - - // Put the role capabilities into the context tree. - foreach ($rolecaps as $rolecap) { - $contexts[$rolecap->contextid]->rolecapabilities[$rolecap->roleid] = $rolecap->permission; - } - - // Fill in any missing rolecaps for the system context. - foreach ($cleanedroleids as $roleid) { - if (!isset($contexts[$systemcontext->id]->rolecapabilities[$roleid])) { - $contexts[$systemcontext->id]->rolecapabilities[$roleid] = CAP_INHERIT; - } - } - - // Print the report heading. - echo $OUTPUT->heading(get_string('reportforcapability', 'tool_capability', get_capability_string($capability)), 2, 'main', 'report'); - if (count($cleanedroleids) != count($allroles)) { - $rolenames = array(); - foreach ($cleanedroleids as $roleid) { - $rolenames[] = $allroles[$roleid]->localname; - } - echo '

', get_string('forroles', 'tool_capability', implode(', ', $rolenames)), '

'; - } - - // Now, recursively print the contexts, and the role information. - print_report_tree($systemcontext->id, $contexts, $allroles); +if (count($capabilities) && count($rolestoshow)) { + /** @var tool_capability_renderer $renderer */ + echo $renderer->capability_comparison_table($capabilities, $context->id, $rolestoshow); } // Footer. -echo $OUTPUT->footer(); - -function print_report_tree($contextid, $contexts, $allroles) { - global $CFG; - - // Array for holding lang strings. - static $strpermissions = null; - if (is_null($strpermissions)) { - $strpermissions = array( - CAP_INHERIT => get_string('notset','role'), - CAP_ALLOW => get_string('allow','role'), - CAP_PREVENT => get_string('prevent','role'), - CAP_PROHIBIT => get_string('prohibit','role') - ); - } - - // Start the list item, and print the context name as a link to the place to - // make changes. - if ($contextid == get_system_context()->id) { - $url = "$CFG->wwwroot/$CFG->admin/roles/manage.php"; - $title = get_string('changeroles', 'tool_capability'); - } else { - $url = "$CFG->wwwroot/$CFG->admin/roles/override.php?contextid=$contextid"; - $title = get_string('changeoverrides', 'tool_capability'); - } - $context = context::instance_by_id($contextid); - echo '

', $context->get_context_name(), '

'; - - // If there are any role overrides here, print them. - if (!empty($contexts[$contextid]->rolecapabilities)) { - $rowcounter = 0; - echo ''; - foreach ($allroles as $role) { - if (isset($contexts[$contextid]->rolecapabilities[$role->id])) { - $permission = $contexts[$contextid]->rolecapabilities[$role->id]; - echo ''; - $rowcounter++; - } - } - echo '
', $role->localname, - '' . $strpermissions[$permission] . '
'; - } - - // After we have done the site context, change the string for CAP_INHERIT - // from 'notset' to 'inherit'. - $strpermissions[CAP_INHERIT] = get_string('inherit','role'); - - // If there are any child contexts, print them recursively. - if (!empty($contexts[$contextid]->children)) { - echo ''; - } -} +echo $OUTPUT->footer(); \ No newline at end of file diff --git a/admin/tool/capability/locallib.php b/admin/tool/capability/locallib.php new file mode 100644 index 00000000000..a54c047b1b1 --- /dev/null +++ b/admin/tool/capability/locallib.php @@ -0,0 +1,95 @@ +. + +/** + * Functions used by the capability tool. + * + * @package tool_capability + * @copyright 2013 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * Calculates capability data organised by context for the given roles. + * + * @param string $capability The capability to get data for. + * @param array $roles An array of roles to get data for. + * @return context[] An array of contexts. + */ +function tool_capability_calculate_role_data($capability, array $roles) { + global $DB; + + $systemcontext = context_system::instance(); + $roleids = array_keys($roles); + + // Work out the bits needed for the SQL WHERE clauses. + $params = array($capability); + list($sqlroletest, $roleparams) = $DB->get_in_or_equal($roleids); + $params = array_merge($params, $roleparams); + $sqlroletest = 'AND roleid ' . $sqlroletest; + + // Get all the role_capabilities rows for this capability - that is, all + // role definitions, and all role overrides. + $rolecaps = $DB->get_records_sql(" + SELECT id, roleid, contextid, permission + FROM {role_capabilities} + WHERE capability = ? $sqlroletest", $params); + + // In order to display a nice tree of contexts, we need to get all the + // ancestors of all the contexts in the query we just did. + $relevantpaths = $DB->get_records_sql_menu(" + SELECT DISTINCT con.path, 1 + FROM {context} con JOIN {role_capabilities} rc ON rc.contextid = con.id + WHERE capability = ? $sqlroletest", $params); + $requiredcontexts = array($systemcontext->id); + foreach ($relevantpaths as $path => $notused) { + $requiredcontexts = array_merge($requiredcontexts, explode('/', trim($path, '/'))); + } + $requiredcontexts = array_unique($requiredcontexts); + + // Now load those contexts. + list($sqlcontexttest, $contextparams) = $DB->get_in_or_equal($requiredcontexts); + $contexts = get_sorted_contexts('ctx.id ' . $sqlcontexttest, $contextparams); + + // Prepare some empty arrays to hold the data we are about to compute. + foreach ($contexts as $conid => $con) { + $contexts[$conid]->children = array(); + $contexts[$conid]->rolecapabilities = array(); + } + + // Put the contexts into a tree structure. + foreach ($contexts as $conid => $con) { + $context = context::instance_by_id($conid); + $parentcontextid = get_parent_contextid($context); + if ($parentcontextid) { + $contexts[$parentcontextid]->children[] = $conid; + } + } + + // Put the role capabilities into the context tree. + foreach ($rolecaps as $rolecap) { + $contexts[$rolecap->contextid]->rolecapabilities[$rolecap->roleid] = $rolecap->permission; + } + + // Fill in any missing rolecaps for the system context. + foreach ($roleids as $roleid) { + if (!isset($contexts[$systemcontext->id]->rolecapabilities[$roleid])) { + $contexts[$systemcontext->id]->rolecapabilities[$roleid] = CAP_INHERIT; + } + } + + return $contexts; +} \ No newline at end of file diff --git a/admin/tool/capability/module.js b/admin/tool/capability/module.js deleted file mode 100644 index 254f1947a9f..00000000000 --- a/admin/tool/capability/module.js +++ /dev/null @@ -1,75 +0,0 @@ - -M.tool_capability = { - select: null, - input: null, - button: null, - - init: function(Y, strsearch) { - var context = M.tool_capability; - - // Find the form controls. - context.select = document.getElementById('menucapability'); - context.button = document.getElementById('settingssubmit'); - - // Create a div to hold the search UI. - var div = document.createElement('div'); - div.id = 'capabilitysearchui'; - - // Find the capability search input. - var input = document.createElement('input'); - input.type = 'text'; - input.id = 'capabilitysearch'; - context.input = input; - - // Create a label for the search input. - var label = document.createElement('label'); - label.htmlFor = input.id; - label.appendChild(document.createTextNode(strsearch + ' ')); - - // Tie it all together - div.appendChild(label); - div.appendChild(input); - context.select.parentNode.insertBefore(div, context.select); - Y.on('keyup', context.typed, input); - Y.on('change', context.validate, context.select); - context.select.options[0].style.display = 'none'; - context.validate(); - }, - - typed: function() { - var context = M.tool_capability; - - var filtertext = context.input.value; - var options = context.select.options; - var onlycapability = -1; - for (var i = 1; i < options.length; i++) { - if (options[i].text.indexOf(filtertext) >= 0) { - options[i].disabled = false; - options[i].style.display = 'block'; - if (onlycapability == -1) { - onlycapability = i; - } else { - onlycapability = -2; - } - } else { - options[i].disabled = true; - options[i].selected = false; - options[i].style.display = 'none'; - } - } - if (onlycapability >= 0) { - options[onlycapability].selected = true; - } - if (onlycapability == -1) { - context.input.className = "error"; - } else { - context.input.className = ""; - } - context.validate(); - }, - - validate: function() { - var context = M.tool_capability; - context.button.disabled = (context.select.value == ''); - } -} \ No newline at end of file diff --git a/admin/tool/capability/renderer.php b/admin/tool/capability/renderer.php new file mode 100644 index 00000000000..18d558c86eb --- /dev/null +++ b/admin/tool/capability/renderer.php @@ -0,0 +1,136 @@ +. + +/** + * Capability tool renderer. + * + * @package tool_capability + * @copyright 2013 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * The primary renderer for the capability tool. + * + * @copyright 2013 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class tool_capability_renderer extends plugin_renderer_base { + + /** + * Returns an array of permission strings. + * + * @return lang_string[] + */ + protected function get_permission_strings() { + static $strpermissions; + if (!$strpermissions) { + $strpermissions = array( + CAP_INHERIT => new lang_string('inherit','role'), + CAP_ALLOW => new lang_string('allow','role'), + CAP_PREVENT => new lang_string('prevent','role'), + CAP_PROHIBIT => new lang_string('prohibit','role') + ); + } + return $strpermissions; + } + + /** + * Returns an array of permission CSS classes. + * + * @return string[] + */ + protected function get_permission_classes() { + static $permissionclasses; + if (!$permissionclasses) { + $permissionclasses = array( + CAP_INHERIT => 'inherit', + CAP_ALLOW => 'allow', + CAP_PREVENT => 'prevent', + CAP_PROHIBIT => 'prohibit', + ); + } + return $permissionclasses; + } + + /** + * Produces a table to visually compare roles and capabilities. + * + * @param array $capabilities An array of capabilities to show comparison for. + * @param int $contextid The context we are displaying for. + * @param array $roles An array of roles to show comparison for. + * @return string + */ + public function capability_comparison_table(array $capabilities, $contextid, array $roles) { + + $strpermissions = $this->get_permission_strings(); + $permissionclasses = $this->get_permission_classes(); + + if ($contextid === context_system::instance()->id) { + $strpermissions[CAP_INHERIT] = new lang_string('notset', 'role'); + } + + $table = new html_table(); + $table->attributes['class'] = 'comparisontable'; + $table->head = array(' '); + foreach ($roles as $role) { + $url = new moodle_url('/admin/roles/override.php', array('contextid' => $contextid, 'roleid' => $role->id)); + $table->head[] = html_writer::div(html_writer::link($url, $role->localname)); + } + $table->data = array(); + + foreach ($capabilities as $capability) { + $contexts = tool_capability_calculate_role_data($capability, $roles); + $captitle = new html_table_cell(get_capability_string($capability) . html_writer::span($capability)); + $captitle->header = true; + + $row = new html_table_row(array($captitle)); + + foreach ($roles as $role) { + if (isset($contexts[$contextid]->rolecapabilities[$role->id])) { + $permission = $contexts[$contextid]->rolecapabilities[$role->id]; + } else { + $permission = CAP_INHERIT; + } + $cell = new html_table_cell($strpermissions[$permission]); + $cell->attributes['class'] = $permissionclasses[$permission]; + $row->cells[] = $cell; + } + + $table->data[] = $row; + } + + // Start the list item, and print the context name as a link to the place to make changes. + if ($contextid == context_system::instance()->id) { + $url = new moodle_url('/admin/roles/manage.php'); + $title = get_string('changeroles', 'tool_capability'); + } else { + $url = new moodle_url('/admin/roles/override.php', array('contextid' => $contextid)); + $title = get_string('changeoverrides', 'tool_capability'); + } + $context = context::instance_by_id($contextid); + $html = $this->output->heading(html_writer::link($url, $context->get_context_name(), array('title' => $title)), 3); + $html .= html_writer::table($table); + // If there are any child contexts, print them recursively. + if (!empty($contexts[$contextid]->children)) { + foreach ($contexts[$contextid]->children as $childcontextid) { + $html .= $this->capability_comparison_table($capabilities, $childcontextid, $roles, true); + } + } + return $html; + } + +} \ No newline at end of file diff --git a/admin/tool/capability/styles.css b/admin/tool/capability/styles.css new file mode 100644 index 00000000000..757066ef146 --- /dev/null +++ b/admin/tool/capability/styles.css @@ -0,0 +1,32 @@ +.path-admin-tool-capability .comparisontable {margin-top:150px;} +.path-admin-tool-capability .comparisontable th, +.path-admin-tool-capability .comparisontable td {vertical-align:middle;padding:0.4em 0.5em 0.3em;} +.path-admin-tool-capability .comparisontable thead th {vertical-align:bottom;background:none;} +.path-admin-tool-capability .comparisontable thead th div {position:relative;} +.path-admin-tool-capability .comparisontable thead th div > a { + position:absolute; + top:-1.75em; + left:1em; + width:150px; + text-align:left; + margin-bottom:1em; + text-indent:-1.45em; + + -webkit-transform-origin: top left; + -moz-transform-origin: top left; + -ms-transform-origin: top left; + -o-transform-origin: top left; + + -webkit-transform: rotate(315deg); + -moz-transform: rotate(315deg); + -ms-transform: rotate(315deg); + -o-transform: rotate(315deg); +} +.path-admin-tool-capability .comparisontable tbody th {background-color:#EEE;text-align:right;border:1px solid #DFDFDF;} +.path-admin-tool-capability .comparisontable tbody th span {display:block;color:#666;font-size:80%;} +.path-admin-tool-capability .comparisontable tbody td {border:1px solid #DFDFDF;} + +.path-admin-tool-capability .comparisontable .inherit {color:#666;} +.path-admin-tool-capability .comparisontable .allow {color:#006600;font-weight:bold;} +.path-admin-tool-capability .comparisontable .prevent {color:#ad6704;font-weight:bold;} +.path-admin-tool-capability .comparisontable .prohibit {color:#880000;font-weight:bold;} \ No newline at end of file diff --git a/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-debug.js b/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-debug.js new file mode 100644 index 00000000000..e1d43566ac2 --- /dev/null +++ b/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-debug.js @@ -0,0 +1,151 @@ +YUI.add('moodle-tool_capability-search', function (Y, NAME) { + +/** + * This file contains the capability overview search functionality. + * + * @module moodle-tool_capability-search + */ + +/** + * Constructs a new capability search manager. + * + * @namespace M.tool_capability.search + * @class Search + * @constructor + * @extends Y.Base + */ +var SEARCH = function() { + SEARCH.superclass.constructor.apply(this, arguments); +}; +SEARCH.prototype = { + /** + * The search form. + * @property form + * @type Node + * @protected + */ + form : null, + /** + * The capability select node. + * @property select + * @type Node + * @protected + */ + select: null, + /** + * The search input field. + * @property input + * @type Node + * @protected + */ + input: null, + /** + * The submit button for the form. + * @property button + * @type Node + * @protected + */ + button: null, + /** + * The last search node if there is one. + * If there is a last search node then the last search term will be persisted between requests. + * @property lastsearch + * @type Node + * @protected + */ + lastsearch : null, + /** + * Constructs the search manager. + * @method initializer + */ + initializer : function() { + this.form = Y.one('#capability-overview-form'); + this.select = this.form.one('select[data-search=capability]'); + this.button = this.form.all('input[type=submit]'); + this.lastsearch = this.form.one('input[name=search]'); + + var div = Y.Node.create('
'), + label = Y.Node.create(''); + this.input = Y.Node.create(''); + + div.append(label).append(this.input); + + this.select.insert(div, 'before'); + this.select.one('option').setStyle('display', 'none'); + + this.input.on('keyup', this.typed, this); + this.select.on('change', this.validate, this); + + if (this.lastsearch) { + this.input.set('value', this.lastsearch.get('value')); + this.typed(); + this.select.set('scrollTop', this.select.one('option[selected]').get('getX')); + } + + this.validate(); + }, + /** + * Disables the submit button if there are no capabilities selected. + * @method validate + */ + validate : function() { + this.button.set('disabled', (this.select.get('value') === '')); + }, + /** + * Called when ever the user types into the search field. + * This method hides any capabilities that don't match the search term. + * @method typed + */ + typed : function() { + var search = this.input.get('value'), + options = this.select.get('options'), + matching = 0, + last = null; + if (this.lastsearch) { + this.lastsearch.set('value', search); + } + options.each(function(option){ + if (option.get('text').indexOf(search) >= 0) { + matching++; + last = option; + option.set('disabled', false).setStyle('display', 'block'); + } else { + option.set('disabled', true).set('selected', false).setStyle('display', 'none'); + } + }, this); + if (matching === 0) { + this.input.addClass("error"); + } else { + this.input.removeClass("error"); + if (matching === 1) { + last.set('selected', true); + } + } + this.validate(); + } +}; +Y.extend(SEARCH, Y.Base, SEARCH.prototype, { + NAME : 'tool_capability-search', + ATTRS : { + strsearch : {} + } +}); + +/** + * Core namespace. + * @static + * @class tool_capability + */ +M.tool_capability = M.tool_capability || {}; + +/** + * Initialises capability search functionality. + * @static + * @method init_capability_search + * @param {Object} options + */ +M.tool_capability.init_capability_search = function(options) { + new SEARCH(options); +}; + +}, '@VERSION@', {"requires": ["base", "node"]}); diff --git a/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-min.js b/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-min.js new file mode 100644 index 00000000000..c876f74b99d --- /dev/null +++ b/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-min.js @@ -0,0 +1 @@ +YUI.add("moodle-tool_capability-search",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)};n.prototype={form:null,select:null,input:null,button:null,lastsearch:null,initializer:function(){this.form=e.one("#capability-overview-form"),this.select=this.form.one("select[data-search=capability]"),this.button=this.form.all("input[type=submit]"),this.lastsearch=this.form.one("input[name=search]");var t=e.Node.create('
'),n=e.Node.create('");this.input=e.Node.create(''),t.append(n).append(this.input),this.select.insert(t,"before"),this.select.one("option").setStyle("display","none"),this.input.on("keyup",this.typed,this),this.select.on("change",this.validate,this),this.lastsearch&&(this.input.set("value",this.lastsearch.get("value")),this.typed(),this.select.set("scrollTop",this.select.one("option[selected]").get("getX"))),this.validate()},validate:function(){this.button.set("disabled",this.select.get("value")==="")},typed:function(){var e=this.input.get("value"),t=this.select.get("options"),n=0,r=null;this.lastsearch&&this.lastsearch.set("value",e),t.each(function(t){t.get("text").indexOf(e)>=0?(n++,r=t,t.set("disabled",!1).setStyle("display","block")):t.set("disabled",!0).set("selected",!1).setStyle("display","none")},this),n===0?this.input.addClass("error"):(this.input.removeClass("error"),n===1&&r.set("selected",!0)),this.validate()}},e.extend(n,e.Base,n.prototype,{NAME:"tool_capability-search",ATTRS:{strsearch:{}}}),M.tool_capability=M.tool_capability||{},M.tool_capability.init_capability_search=function(e){new n(e)}},"@VERSION@",{requires:["base","node"]}); diff --git a/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search.js b/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search.js new file mode 100644 index 00000000000..e1d43566ac2 --- /dev/null +++ b/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search.js @@ -0,0 +1,151 @@ +YUI.add('moodle-tool_capability-search', function (Y, NAME) { + +/** + * This file contains the capability overview search functionality. + * + * @module moodle-tool_capability-search + */ + +/** + * Constructs a new capability search manager. + * + * @namespace M.tool_capability.search + * @class Search + * @constructor + * @extends Y.Base + */ +var SEARCH = function() { + SEARCH.superclass.constructor.apply(this, arguments); +}; +SEARCH.prototype = { + /** + * The search form. + * @property form + * @type Node + * @protected + */ + form : null, + /** + * The capability select node. + * @property select + * @type Node + * @protected + */ + select: null, + /** + * The search input field. + * @property input + * @type Node + * @protected + */ + input: null, + /** + * The submit button for the form. + * @property button + * @type Node + * @protected + */ + button: null, + /** + * The last search node if there is one. + * If there is a last search node then the last search term will be persisted between requests. + * @property lastsearch + * @type Node + * @protected + */ + lastsearch : null, + /** + * Constructs the search manager. + * @method initializer + */ + initializer : function() { + this.form = Y.one('#capability-overview-form'); + this.select = this.form.one('select[data-search=capability]'); + this.button = this.form.all('input[type=submit]'); + this.lastsearch = this.form.one('input[name=search]'); + + var div = Y.Node.create('
'), + label = Y.Node.create(''); + this.input = Y.Node.create(''); + + div.append(label).append(this.input); + + this.select.insert(div, 'before'); + this.select.one('option').setStyle('display', 'none'); + + this.input.on('keyup', this.typed, this); + this.select.on('change', this.validate, this); + + if (this.lastsearch) { + this.input.set('value', this.lastsearch.get('value')); + this.typed(); + this.select.set('scrollTop', this.select.one('option[selected]').get('getX')); + } + + this.validate(); + }, + /** + * Disables the submit button if there are no capabilities selected. + * @method validate + */ + validate : function() { + this.button.set('disabled', (this.select.get('value') === '')); + }, + /** + * Called when ever the user types into the search field. + * This method hides any capabilities that don't match the search term. + * @method typed + */ + typed : function() { + var search = this.input.get('value'), + options = this.select.get('options'), + matching = 0, + last = null; + if (this.lastsearch) { + this.lastsearch.set('value', search); + } + options.each(function(option){ + if (option.get('text').indexOf(search) >= 0) { + matching++; + last = option; + option.set('disabled', false).setStyle('display', 'block'); + } else { + option.set('disabled', true).set('selected', false).setStyle('display', 'none'); + } + }, this); + if (matching === 0) { + this.input.addClass("error"); + } else { + this.input.removeClass("error"); + if (matching === 1) { + last.set('selected', true); + } + } + this.validate(); + } +}; +Y.extend(SEARCH, Y.Base, SEARCH.prototype, { + NAME : 'tool_capability-search', + ATTRS : { + strsearch : {} + } +}); + +/** + * Core namespace. + * @static + * @class tool_capability + */ +M.tool_capability = M.tool_capability || {}; + +/** + * Initialises capability search functionality. + * @static + * @method init_capability_search + * @param {Object} options + */ +M.tool_capability.init_capability_search = function(options) { + new SEARCH(options); +}; + +}, '@VERSION@', {"requires": ["base", "node"]}); diff --git a/admin/tool/capability/yui/src/search/build.json b/admin/tool/capability/yui/src/search/build.json new file mode 100644 index 00000000000..21578891565 --- /dev/null +++ b/admin/tool/capability/yui/src/search/build.json @@ -0,0 +1,10 @@ +{ + "name": "moodle-tool_capability-search", + "builds": { + "moodle-tool_capability-search": { + "jsfiles": [ + "search.js" + ] + } + } +} diff --git a/admin/tool/capability/yui/src/search/js/search.js b/admin/tool/capability/yui/src/search/js/search.js new file mode 100644 index 00000000000..3799b6c3568 --- /dev/null +++ b/admin/tool/capability/yui/src/search/js/search.js @@ -0,0 +1,147 @@ +/** + * This file contains the capability overview search functionality. + * + * @module moodle-tool_capability-search + */ + +/** + * Constructs a new capability search manager. + * + * @namespace M.tool_capability.search + * @class Search + * @constructor + * @extends Y.Base + */ +var SEARCH = function() { + SEARCH.superclass.constructor.apply(this, arguments); +}; +SEARCH.prototype = { + /** + * The search form. + * @property form + * @type Node + * @protected + */ + form : null, + /** + * The capability select node. + * @property select + * @type Node + * @protected + */ + select: null, + /** + * The search input field. + * @property input + * @type Node + * @protected + */ + input: null, + /** + * The submit button for the form. + * @property button + * @type Node + * @protected + */ + button: null, + /** + * The last search node if there is one. + * If there is a last search node then the last search term will be persisted between requests. + * @property lastsearch + * @type Node + * @protected + */ + lastsearch : null, + /** + * Constructs the search manager. + * @method initializer + */ + initializer : function() { + this.form = Y.one('#capability-overview-form'); + this.select = this.form.one('select[data-search=capability]'); + this.button = this.form.all('input[type=submit]'); + this.lastsearch = this.form.one('input[name=search]'); + + var div = Y.Node.create('
'), + label = Y.Node.create(''); + this.input = Y.Node.create(''); + + div.append(label).append(this.input); + + this.select.insert(div, 'before'); + this.select.one('option').setStyle('display', 'none'); + + this.input.on('keyup', this.typed, this); + this.select.on('change', this.validate, this); + + if (this.lastsearch) { + this.input.set('value', this.lastsearch.get('value')); + this.typed(); + this.select.set('scrollTop', this.select.one('option[selected]').get('getX')); + } + + this.validate(); + }, + /** + * Disables the submit button if there are no capabilities selected. + * @method validate + */ + validate : function() { + this.button.set('disabled', (this.select.get('value') === '')); + }, + /** + * Called when ever the user types into the search field. + * This method hides any capabilities that don't match the search term. + * @method typed + */ + typed : function() { + var search = this.input.get('value'), + options = this.select.get('options'), + matching = 0, + last = null; + if (this.lastsearch) { + this.lastsearch.set('value', search); + } + options.each(function(option){ + if (option.get('text').indexOf(search) >= 0) { + matching++; + last = option; + option.set('disabled', false).setStyle('display', 'block'); + } else { + option.set('disabled', true).set('selected', false).setStyle('display', 'none'); + } + }, this); + if (matching === 0) { + this.input.addClass("error"); + } else { + this.input.removeClass("error"); + if (matching === 1) { + last.set('selected', true); + } + } + this.validate(); + } +}; +Y.extend(SEARCH, Y.Base, SEARCH.prototype, { + NAME : 'tool_capability-search', + ATTRS : { + strsearch : {} + } +}); + +/** + * Core namespace. + * @static + * @class tool_capability + */ +M.tool_capability = M.tool_capability || {}; + +/** + * Initialises capability search functionality. + * @static + * @method init_capability_search + * @param {Object} options + */ +M.tool_capability.init_capability_search = function(options) { + new SEARCH(options); +}; \ No newline at end of file diff --git a/admin/tool/capability/yui/src/search/meta/search.json b/admin/tool/capability/yui/src/search/meta/search.json new file mode 100644 index 00000000000..720e20bf310 --- /dev/null +++ b/admin/tool/capability/yui/src/search/meta/search.json @@ -0,0 +1,8 @@ +{ + "moodle-tool_capability-search": { + "requires": [ + "base", + "node" + ] + } +}