Merge branch '44155-27' of git://github.com/samhemelryk/moodle
authorEloy Lafuente (stronk7) <stronk7@moodle.org>
Mon, 17 Feb 2014 23:54:28 +0000 (00:54 +0100)
committerEloy Lafuente (stronk7) <stronk7@moodle.org>
Mon, 17 Feb 2014 23:54:28 +0000 (00:54 +0100)
227 files changed:
admin/settings/appearance.php
backup/moodle2/backup_stepslib.php
backup/moodle2/restore_stepslib.php
blocks/course_overview/renderer.php
cohort/locallib.php
course/format/formatlegacy.php
course/format/lib.php
course/format/topics/lib.php
course/format/upgrade.txt
course/format/weeks/lib.php
course/lib.php
course/renderer.php
course/view.php
course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes-debug.js
course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes-min.js
course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes.js
course/yui/src/toolboxes/js/resource.js
grade/grading/form/rubric/tests/behat/behat_gradingform_rubric.php [new file with mode: 0644]
grade/grading/form/rubric/tests/behat/edit_rubric.feature [new file with mode: 0644]
grade/grading/form/rubric/tests/behat/publish_rubric_templates.feature [new file with mode: 0644]
grade/grading/form/rubric/tests/behat/reuse_own_rubrics.feature [new file with mode: 0644]
grade/grading/tests/behat/behat_grading.php [new file with mode: 0644]
grade/import/csv/index.php
group/index.php
lang/en/admin.php
lib/ajax/ajaxlib.php
lib/behat/classes/behat_selectors.php
lib/db/install.xml
lib/db/upgrade.php
lib/deprecatedlib.php
lib/setuplib.php
lib/tablelib.php
lib/tests/tablelib_test.php
lib/upgrade.txt
lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop-debug.js
lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop-min.js
lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop.js
lib/yui/build/moodle-core-notification-ajaxexception/moodle-core-notification-ajaxexception-debug.js
lib/yui/build/moodle-core-notification-ajaxexception/moodle-core-notification-ajaxexception-min.js
lib/yui/build/moodle-core-notification-ajaxexception/moodle-core-notification-ajaxexception.js
lib/yui/build/moodle-core-notification-alert/moodle-core-notification-alert-debug.js
lib/yui/build/moodle-core-notification-alert/moodle-core-notification-alert-min.js
lib/yui/build/moodle-core-notification-alert/moodle-core-notification-alert.js
lib/yui/build/moodle-core-notification-confirm/moodle-core-notification-confirm-debug.js
lib/yui/build/moodle-core-notification-confirm/moodle-core-notification-confirm-min.js
lib/yui/build/moodle-core-notification-confirm/moodle-core-notification-confirm.js
lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-debug.js
lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-min.js
lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue.js
lib/yui/build/moodle-core-notification-exception/moodle-core-notification-exception-debug.js
lib/yui/build/moodle-core-notification-exception/moodle-core-notification-exception-min.js
lib/yui/build/moodle-core-notification-exception/moodle-core-notification-exception.js
lib/yui/build/moodle-core-tooltip/moodle-core-tooltip-debug.js
lib/yui/build/moodle-core-tooltip/moodle-core-tooltip-min.js
lib/yui/build/moodle-core-tooltip/moodle-core-tooltip.js
lib/yui/src/dragdrop/js/dragdrop.js
lib/yui/src/notification/build.json
lib/yui/src/notification/js/ajaxexception.js
lib/yui/src/notification/js/alert.js
lib/yui/src/notification/js/confirm.js
lib/yui/src/notification/js/dialogue.js
lib/yui/src/notification/js/exception.js
lib/yui/src/notification/js/info.js [new file with mode: 0644]
lib/yui/src/tooltip/js/tooltip.js
lib/yuilib/3.13.0/widget-modality/widget-modality-coverage.js
lib/yuilib/3.13.0/widget-modality/widget-modality-debug.js
lib/yuilib/3.13.0/widget-modality/widget-modality-min.js
lib/yuilib/3.13.0/widget-modality/widget-modality.js
mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-debug.js
mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-min.js
mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor.js
mod/assign/feedback/editpdf/yui/src/editor/js/editor.js
mod/data/classes/event/course_module_instance_list_viewed.php [new file with mode: 0644]
mod/data/classes/event/course_module_viewed.php [new file with mode: 0644]
mod/data/classes/event/field_created.php [new file with mode: 0644]
mod/data/classes/event/field_deleted.php [new file with mode: 0644]
mod/data/classes/event/field_updated.php [new file with mode: 0644]
mod/data/classes/event/record_created.php [new file with mode: 0644]
mod/data/classes/event/record_deleted.php [new file with mode: 0644]
mod/data/classes/event/record_updated.php [new file with mode: 0644]
mod/data/classes/event/template_updated.php [new file with mode: 0644]
mod/data/classes/event/template_viewed.php [new file with mode: 0644]
mod/data/edit.php
mod/data/field.php
mod/data/index.php
mod/data/lang/en/data.php
mod/data/lib.php
mod/data/templates.php
mod/data/tests/events_test.php [new file with mode: 0644]
mod/data/view.php
mod/feedback/edit.php
mod/folder/backup/moodle1/lib.php
mod/folder/backup/moodle2/backup_folder_activity_task.class.php
mod/folder/backup/moodle2/backup_folder_stepslib.php
mod/folder/backup/moodle2/restore_folder_activity_task.class.php
mod/folder/backup/moodle2/restore_folder_stepslib.php
mod/folder/db/install.php
mod/folder/db/upgrade.php
mod/folder/edit.php
mod/folder/edit_form.php
mod/folder/index.php
mod/folder/lang/en/folder.php
mod/folder/lib.php
mod/folder/locallib.php
mod/folder/mod_form.php
mod/folder/renderer.php
mod/folder/settings.php
mod/folder/version.php
mod/folder/view.php
mod/forum/backup/moodle1/lib.php
mod/forum/backup/moodle2/backup_forum_activity_task.class.php
mod/forum/backup/moodle2/backup_forum_settingslib.php
mod/forum/backup/moodle2/backup_forum_stepslib.php
mod/forum/backup/moodle2/restore_forum_activity_task.class.php
mod/forum/backup/moodle2/restore_forum_stepslib.php
mod/forum/classes/event/course_module_instance_list_viewed.php [new file with mode: 0644]
mod/forum/classes/event/course_searched.php [new file with mode: 0644]
mod/forum/classes/event/discussion_created.php [new file with mode: 0644]
mod/forum/classes/event/discussion_deleted.php [new file with mode: 0644]
mod/forum/classes/event/discussion_moved.php [new file with mode: 0644]
mod/forum/classes/event/discussion_updated.php [new file with mode: 0644]
mod/forum/classes/event/discussion_viewed.php [new file with mode: 0644]
mod/forum/classes/event/forum_viewed.php [new file with mode: 0644]
mod/forum/classes/event/post_created.php [new file with mode: 0644]
mod/forum/classes/event/post_deleted.php [new file with mode: 0644]
mod/forum/classes/event/post_updated.php [new file with mode: 0644]
mod/forum/classes/event/readtracking_disabled.php [new file with mode: 0644]
mod/forum/classes/event/readtracking_enabled.php [new file with mode: 0644]
mod/forum/classes/event/subscribers_viewed.php [new file with mode: 0644]
mod/forum/classes/event/subscription_created.php [new file with mode: 0644]
mod/forum/classes/event/subscription_deleted.php [new file with mode: 0644]
mod/forum/classes/event/userreport_viewed.php [new file with mode: 0644]
mod/forum/db/messages.php
mod/forum/db/upgrade.php
mod/forum/discuss.php
mod/forum/index.php
mod/forum/lang/en/forum.php
mod/forum/lib.php
mod/forum/locallib.php
mod/forum/markposts.php
mod/forum/mod_form.php
mod/forum/post.php
mod/forum/renderer.php
mod/forum/rsslib.php
mod/forum/search.php
mod/forum/settings.php
mod/forum/settracking.php
mod/forum/subscribe.php
mod/forum/subscribers.php
mod/forum/tests/events_test.php [new file with mode: 0644]
mod/forum/unsubscribeall.php
mod/forum/user.php
mod/forum/version.php
mod/forum/view.php
mod/glossary/backup/moodle1/lib.php
mod/glossary/backup/moodle2/backup_glossary_stepslib.php
mod/glossary/backup/moodle2/restore_glossary_activity_task.class.php
mod/glossary/backup/moodle2/restore_glossary_stepslib.php
mod/glossary/lang/en/glossary.php
mod/glossary/lib.php
mod/glossary/locallib.php
mod/glossary/version.php
mod/quiz/lib.php
mod/quiz/report/statistics/lang/en/quiz_statistics.php
mod/quiz/report/statistics/report.php
mod/quiz/report/statistics/statistics_table.php
mod/quiz/report/statistics/tests/fixtures/responsecounts00.csv [new file with mode: 0644]
mod/quiz/report/statistics/tests/stats_from_steps_walkthrough_test.php
mod/resource/backup/moodle1/lib.php
mod/resource/backup/moodle2/backup_resource_stepslib.php
mod/resource/backup/moodle2/restore_resource_activity_task.class.php
mod/resource/backup/moodle2/restore_resource_stepslib.php
mod/resource/db/upgrade.php
mod/resource/index.php
mod/resource/lang/en/resource.php
mod/resource/lib.php
mod/resource/locallib.php
mod/resource/mod_form.php
mod/resource/settings.php
mod/resource/tests/generator/lib.php
mod/resource/tests/generator_test.php
mod/resource/version.php
mod/resource/view.php
mod/url/backup/moodle1/lib.php
mod/url/backup/moodle2/backup_url_stepslib.php
mod/url/backup/moodle2/restore_url_activity_task.class.php
mod/url/backup/moodle2/restore_url_stepslib.php
mod/url/db/install.php
mod/url/db/upgrade.php
mod/url/index.php
mod/url/lang/en/url.php
mod/url/lib.php
mod/url/locallib.php
mod/url/mod_form.php
mod/url/settings.php
mod/url/version.php
mod/url/view.php
question/classes/statistics/questions/all_calculated_for_qubaid_condition.php
question/classes/statistics/questions/calculated.php
question/classes/statistics/responses/analyser.php
question/classes/statistics/responses/analysis_for_actual_response.php
question/classes/statistics/responses/analysis_for_class.php
question/classes/statistics/responses/analysis_for_question.php
question/classes/statistics/responses/analysis_for_subpart.php
question/format.php
question/format/xml/format.php
question/format/xml/tests/xmlformat_test.php
question/type/match/renderer.php
question/type/randomsamatch/backup/moodle1/lib.php [new file with mode: 0644]
question/type/randomsamatch/backup/moodle2/backup_qtype_randomsamatch_plugin.class.php
question/type/randomsamatch/backup/moodle2/restore_qtype_randomsamatch_plugin.class.php
question/type/randomsamatch/db/install.xml
question/type/randomsamatch/db/upgrade.php [new file with mode: 0644]
question/type/randomsamatch/db/upgradelib.php [new file with mode: 0644]
question/type/randomsamatch/edit_randomsamatch_form.php
question/type/randomsamatch/lang/en/qtype_randomsamatch.php
question/type/randomsamatch/lib.php [new file with mode: 0644]
question/type/randomsamatch/question.php [new file with mode: 0644]
question/type/randomsamatch/questiontype.php
question/type/randomsamatch/renderer.php [new file with mode: 0644]
question/type/randomsamatch/tests/helper.php [new file with mode: 0644]
question/type/randomsamatch/tests/question_test.php [new file with mode: 0644]
question/type/randomsamatch/tests/upgradelibnewqe_test.php [new file with mode: 0644]
question/type/randomsamatch/tests/walkthrough_test.php [new file with mode: 0644]
question/type/randomsamatch/version.php
rating/lib.php
version.php

index 2cf6f0f..1df0a09 100644 (file)
@@ -191,6 +191,9 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) { // sp
     // "documentation" settingpage
     $temp = new admin_settingpage('documentation', new lang_string('moodledocs'));
     $temp->add(new admin_setting_configtext('docroot', new lang_string('docroot', 'admin'), new lang_string('configdocroot', 'admin'), 'http://docs.moodle.org', PARAM_URL));
+    $ltemp = array('' => get_string('forceno'));
+    $ltemp += get_string_manager()->get_list_of_translations(true);
+    $temp->add(new admin_setting_configselect('doclang', get_string('doclang', 'admin'), get_string('configdoclang', 'admin'), '', $ltemp));
     $temp->add(new admin_setting_configcheckbox('doctonewwindow', new lang_string('doctonewwindow', 'admin'), new lang_string('configdoctonewwindow', 'admin'), 0));
     $ADMIN->add('appearance', $temp);
 
@@ -217,7 +220,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) { // sp
     $ADMIN->add('appearance', $temp);
 
     $temp = new admin_settingpage('ajax', new lang_string('ajaxuse'));
-    $temp->add(new admin_setting_configcheckbox('enableajax', new lang_string('enableajax', 'admin'), new lang_string('configenableajax', 'admin'), 1));
     $temp->add(new admin_setting_configcheckbox('useexternalyui', new lang_string('useexternalyui', 'admin'), new lang_string('configuseexternalyui', 'admin'), 0));
     $temp->add(new admin_setting_configcheckbox('yuicomboloading', new lang_string('yuicomboloading', 'admin'), new lang_string('configyuicomboloading', 'admin'), 1));
     $setting = new admin_setting_configcheckbox('cachejs', new lang_string('cachejs', 'admin'), new lang_string('cachejs_help', 'admin'), 1);
index 4e79cc5..5ec6bad 100644 (file)
@@ -216,7 +216,7 @@ abstract class backup_questions_activity_structure_step extends backup_activity_
 
         $qas = new backup_nested_element($nameprefix . 'question_attempts');
         $qa = new backup_nested_element($nameprefix . 'question_attempt', array('id'), array(
-                'slot', 'behaviour', 'questionid', 'maxmark', 'minfraction', 'maxfraction',
+                'slot', 'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'maxfraction',
                 'flagged', 'questionsummary', 'rightanswer', 'responsesummary',
                 'timemodified'));
 
index 1045d94..68c24d6 100644 (file)
@@ -4069,6 +4069,9 @@ abstract class restore_questions_activity_structure_step extends restore_activit
 
         $data->questionusageid = $this->get_new_parentid($nameprefix . 'question_usage');
         $data->questionid      = $question->newitemid;
+        if (!property_exists($data, 'variant')) {
+            $data->variant = 1;
+        }
         $data->timemodified    = $this->apply_date_offset($data->timemodified);
 
         if (!property_exists($data, 'maxfraction')) {
index fcde4f4..3efcd95 100644 (file)
@@ -48,10 +48,7 @@ class block_course_overview_renderer extends plugin_renderer_base {
         // Intialise string/icon etc if user is editing and courses > 1
         if ($this->page->user_is_editing() && (count($courses) > 1)) {
             $userediting = true;
-            // If ajaxenabled then include DND JS and replace link with move image.
-            if (ajaxenabled()) {
-                $this->page->requires->js_init_call('M.block_course_overview.add_handles');
-            }
+            $this->page->requires->js_init_call('M.block_course_overview.add_handles');
 
             // Check if course is moving
             $ismovingcourse = optional_param('movecourse', FALSE, PARAM_BOOL);
index 23fa8a6..62dcfdf 100644 (file)
@@ -126,7 +126,7 @@ class cohort_existing_selector extends user_selector_base {
 
         if (!$this->is_validating()) {
             $potentialmemberscount = $DB->count_records_sql($countfields . $sql, $params);
-            if ($potentialmemberscount > 100) {
+            if ($potentialmemberscount > $this->maxusersperpage) {
                 return $this->too_many_results($search, $potentialmemberscount);
             }
         }
index f353a4b..665f583 100644 (file)
@@ -147,7 +147,6 @@ class format_legacy extends format_base {
      *
      * The returned object's property (boolean)capable indicates that
      * the course format supports Moodle course ajax features.
-     * The property (array)testedbrowsers can be used as a parameter for {@link ajaxenabled()}.
      *
      * @return stdClass
      */
@@ -162,9 +161,6 @@ class format_legacy extends format_base {
             if (isset($formatsupport->capable)) {
                 $ajaxsupport->capable = $formatsupport->capable;
             }
-            if (is_array($formatsupport->testedbrowsers)) {
-                $ajaxsupport->testedbrowsers = $formatsupport->testedbrowsers;
-            }
         }
         return $ajaxsupport;
     }
@@ -360,4 +356,4 @@ class format_legacy extends format_base {
         }
         return $this->update_format_options($data);
     }
-}
\ No newline at end of file
+}
index a68ce5a..af2a6c6 100644 (file)
@@ -353,7 +353,6 @@ abstract class format_base {
      *
      * The returned object's property (boolean)capable indicates that
      * the course format supports Moodle course ajax features.
-     * The property (array)testedbrowsers can be used as a parameter for {@link ajaxenabled()}.
      *
      * @return stdClass
      */
@@ -361,7 +360,6 @@ abstract class format_base {
         // no support by default
         $ajaxsupport = new stdClass();
         $ajaxsupport->capable = false;
-        $ajaxsupport->testedbrowsers = array();
         return $ajaxsupport;
     }
 
index 71a0452..7c1ee6e 100644 (file)
@@ -115,14 +115,12 @@ class format_topics extends format_base {
      *
      * The returned object's property (boolean)capable indicates that
      * the course format supports Moodle course ajax features.
-     * The property (array)testedbrowsers can be used as a parameter for {@link ajaxenabled()}.
      *
      * @return stdClass
      */
     public function supports_ajax() {
         $ajaxsupport = new stdClass();
         $ajaxsupport->capable = true;
-        $ajaxsupport->testedbrowsers = array('MSIE' => 6.0, 'Gecko' => 20061111, 'Safari' => 531, 'Chrome' => 6.0);
         return $ajaxsupport;
     }
 
index f29a06e..3bc37ed 100644 (file)
@@ -2,6 +2,9 @@ This files describes API changes for course formats
 
 Overview of this plugin type at http://docs.moodle.org/dev/Course_formats
 
+=== 2.7 ===
+* The ->testedbrowsers array no longer needs to be defined in supports_ajax().
+
 === 2.6 ===
 
 * core_course_renderer::course_section_cm_edit_actions has two new optional arguments and now uses and action_menu component.
index ded5ef0..e361def 100644 (file)
@@ -122,14 +122,12 @@ class format_weeks extends format_base {
      *
      * The returned object's property (boolean)capable indicates that
      * the course format supports Moodle course ajax features.
-     * The property (array)testedbrowsers can be used as a parameter for {@link ajaxenabled()}.
      *
      * @return stdClass
      */
     public function supports_ajax() {
         $ajaxsupport = new stdClass();
         $ajaxsupport->capable = true;
-        $ajaxsupport->testedbrowsers = array('MSIE' => 6.0, 'Gecko' => 20061111, 'Safari' => 531, 'Chrome' => 6.0);
         return $ajaxsupport;
     }
 
index 1ae3e94..1110236 100644 (file)
@@ -2333,7 +2333,6 @@ function course_format_uses_sections($format) {
  *
  * The returned object's property (boolean)capable indicates that
  * the course format supports Moodle course ajax features.
- * The property (array)testedbrowsers can be used as a parameter for {@see ajaxenabled()}.
  *
  * @param string $format
  * @return stdClass
@@ -3119,11 +3118,6 @@ function course_page_type_list($pagetype, $parentcontext, $currentcontext) {
 function course_ajax_enabled($course) {
     global $CFG, $PAGE, $SITE;
 
-    // Ajax must be enabled globally
-    if (!$CFG->enableajax) {
-        return false;
-    }
-
     // The user must be editing for AJAX to be included
     if (!$PAGE->user_is_editing()) {
         return false;
index eb6ab4a..aab4174 100644 (file)
@@ -1503,7 +1503,7 @@ class core_course_renderer extends plugin_renderer_base {
     protected function coursecat_include_js() {
         global $CFG;
         static $jsloaded = false;
-        if (!$jsloaded && $CFG->enableajax) {
+        if (!$jsloaded) {
             // We must only load this module once.
             $this->page->requires->yui_module('moodle-course-categoryexpander',
                     'Y.Moodle.course.categoryexpander.init');
@@ -1583,8 +1583,6 @@ class core_course_renderer extends plugin_renderer_base {
                 $classes[] = 'with_children';
                 $classes[] = 'collapsed';
             }
-            // Make sure JS file to expand category content is included.
-            $this->coursecat_include_js();
         } else {
             // load category content
             $categorycontent = $this->coursecat_category_content($chelper, $coursecat, $depth);
@@ -1593,6 +1591,10 @@ class core_course_renderer extends plugin_renderer_base {
                 $classes[] = 'with_children';
             }
         }
+
+        // Make sure JS file to expand category content is included.
+        $this->coursecat_include_js();
+
         $content = html_writer::start_tag('div', array(
             'class' => join(' ', $classes),
             'data-categoryid' => $coursecat->id,
index 16b2ca0..c5ec9d0 100644 (file)
         redirect($CFG->wwwroot .'/');
     }
 
-    $ajaxenabled = ajaxenabled();
-
     $completion = new completion_info($course);
-    if ($completion->is_enabled() && $ajaxenabled) {
+    if ($completion->is_enabled()) {
         $PAGE->requires->string_for_js('completion-title-manual-y', 'completion');
         $PAGE->requires->string_for_js('completion-title-manual-n', 'completion');
         $PAGE->requires->string_for_js('completion-alt-manual-y', 'completion');
     $PAGE->set_heading($course->fullname);
     echo $OUTPUT->header();
 
-    if ($completion->is_enabled() && $ajaxenabled) {
+    if ($completion->is_enabled()) {
         // This value tracks whether there has been a dynamic change to the page.
         // It is used so that if a user does this - (a) set some tickmarks, (b)
         // go to another page, (c) clicks Back button - the page will
index fce0fbc..7839c1c 100644 (file)
Binary files a/course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes-debug.js and b/course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes-debug.js differ
index bfad604..e258f95 100644 (file)
Binary files a/course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes-min.js and b/course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes-min.js differ
index fce0fbc..7839c1c 100644 (file)
Binary files a/course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes.js and b/course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes.js differ
index 34ab1c5..30b18ef 100644 (file)
@@ -274,22 +274,29 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
             confirmstring = M.util.get_string('deletechecktype', 'moodle', plugindata);
         }
 
-        // Confirm element removal
-        if (!confirm(confirmstring)) {
-            return this;
-        }
+        // Create the confirmation dialogue.
+        var confirm = new M.core.confirm({
+            question: confirmstring,
+            modal: true
+        });
+
+        // If it is confirmed.
+        confirm.on('complete-yes', function() {
+
+            // Actually remove the element.
+            element.remove();
+            var data = {
+                'class': 'resource',
+                'action': 'DELETE',
+                'id': Y.Moodle.core_course.util.cm.getId(element)
+            };
+            this.send_request(data);
+            if (M.core.actionmenu && M.core.actionmenu.instance) {
+                M.core.actionmenu.instance.hideMenu();
+            }
+
+        }, this);
 
-        // Actually remove the element
-        element.remove();
-        var data = {
-            'class': 'resource',
-            'action': 'DELETE',
-            'id': Y.Moodle.core_course.util.cm.getId(element)
-        };
-        this.send_request(data);
-        if (M.core.actionmenu && M.core.actionmenu.instance) {
-            M.core.actionmenu.instance.hideMenu();
-        }
         return this;
     },
 
diff --git a/grade/grading/form/rubric/tests/behat/behat_gradingform_rubric.php b/grade/grading/form/rubric/tests/behat/behat_gradingform_rubric.php
new file mode 100644 (file)
index 0000000..bef83f9
--- /dev/null
@@ -0,0 +1,490 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Steps definitions for rubrics.
+ *
+ * @package   gradingform_rubric
+ * @category  test
+ * @copyright 2013 David Monllaó
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
+
+require_once(__DIR__ . '/../../../../../../lib/behat/behat_base.php');
+
+use Behat\Gherkin\Node\TableNode as TableNode,
+    Behat\Behat\Context\Step\Given as Given,
+    Behat\Behat\Context\Step\When as When,
+    Behat\Behat\Context\Step\Then as Then,
+    Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException,
+    Behat\Mink\Exception\ExpectationException as ExpectationException;
+
+/**
+ * Steps definitions to help with rubrics.
+ *
+ * @package   gradingform_rubric
+ * @category  test
+ * @copyright 2013 David Monllaó
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class behat_gradingform_rubric extends behat_base {
+
+    /**
+     * @var The number of levels added by default when a rubric is created.
+     */
+    const DEFAULT_RUBRIC_LEVELS = 3;
+
+    /**
+     * Defines the rubric with the provided data, following rubric's definition grid cells.
+     *
+     * This method fills the rubric of the rubric definition
+     * form; the provided TableNode should contain one row for
+     * each criterion and each cell of the row should contain:
+     * # Criterion description
+     * # Criterion level 1 name
+     * # Criterion level 1 points
+     * # Criterion level 2 name
+     * # Criterion level 2 points
+     * # Criterion level 3 .....
+     *
+     * Works with both JS and non-JS.
+     *
+     * @When /^I define the following rubric:$/
+     * @throws ExpectationException
+     * @param TableNode $rubric
+     */
+    public function i_define_the_following_rubric(TableNode $rubric) {
+
+        // Being a smart method is nothing good when we talk about step definitions, in
+        // this case we didn't have any other options as there are no labels no elements
+        // id we can point to without having to "calculate" them.
+
+        $steptableinfo = '| criterion description | level1 name  | level1 points | level2 name | level2 points | ...';
+
+        $criteria = $rubric->getRows();
+
+        $addcriterionbutton = $this->find_button(get_string('addcriterion', 'gradingform_rubric'));
+
+        // Cleaning the current ones.
+        $deletebuttons = $this->find_all('css', "input[title='" . get_string('criteriondelete', 'gradingform_rubric') . "']");
+        if ($deletebuttons) {
+
+            // We should reverse the deletebuttons because otherwise once we delete
+            // the first one the DOM will change and the [X] one will not exist anymore.
+            $deletebuttons = array_reverse($deletebuttons, true);
+            foreach ($deletebuttons as $button) {
+                $this->click_and_confirm($button);
+            }
+        }
+
+        // The level number (NEWID$N) is not reset after each criterion.
+        $levelnumber = 1;
+
+        // The next criterion is created with the same number of levels than the last criterion.
+        $defaultnumberoflevels = self::DEFAULT_RUBRIC_LEVELS;
+
+        if ($criteria) {
+            foreach ($criteria as $criterionit => $criterion) {
+
+                // Checking the number of cells.
+                if (count($criterion) % 2 === 0) {
+                    throw new ExpectationException(
+                        'The criterion levels should contain both definition and points, follow this format:' . $steptableinfo,
+                        $this->getSession()
+                    );
+                }
+
+                // Minimum 2 levels per criterion.
+                // description + definition1 + score1 + definition2 + score2 = 5.
+                if (count($criterion) < 5) {
+                    throw new ExpectationException(
+                        get_string('err_mintwolevels', 'gradingform_rubric'),
+                        $this->getSession()
+                    );
+
+                }
+
+                // Add new criterion.
+                $addcriterionbutton->click();
+
+                $criterionroot = 'rubric[criteria][NEWID' . ($criterionit + 1) . ']';
+
+                // Getting the criterion description, this one is visible by default.
+                $this->set_rubric_field_value($criterionroot . '[description]', array_shift($criterion), true);
+
+                // When JS is disabled each criterion's levels name numbers starts from 0.
+                if (!$this->running_javascript()) {
+                    $levelnumber = 0;
+                }
+
+                // Setting the correct number of levels.
+                $nlevels = count($criterion) / 2;
+                if ($nlevels < $defaultnumberoflevels) {
+
+                    // Removing levels if there are too much levels.
+                    // When we add a new level the NEWID$N is increased from the last criterion.
+                    $lastcriteriondefaultlevel = $defaultnumberoflevels + $levelnumber - 1;
+                    $lastcriterionlevel = $nlevels + $levelnumber - 1;
+                    for ($i = $lastcriteriondefaultlevel; $i > $lastcriterionlevel; $i--) {
+
+                        // If JS is disabled seems that new levels are not added.
+                        if ($this->running_javascript()) {
+                            $deletelevel = $this->find_button($criterionroot . '[levels][NEWID' . $i . '][delete]');
+                            $this->click_and_confirm($deletelevel);
+
+                        } else {
+                            // Only if the level exists.
+                            $buttonname = $criterionroot . '[levels][NEWID' . $i . '][delete]';
+                            if ($deletelevel = $this->getSession()->getPage()->findButton($buttonname)) {
+                                $deletelevel->click();
+                            }
+                        }
+                    }
+                } else if ($nlevels > $defaultnumberoflevels) {
+                    // Adding levels if we don't have enough.
+                    $addlevel = $this->find_button($criterionroot . '[levels][addlevel]');
+                    for ($i = ($defaultnumberoflevels + 1); $i <= $nlevels; $i++) {
+                        $addlevel->click();
+                    }
+                }
+
+                // Updating it.
+                if ($nlevels > self::DEFAULT_RUBRIC_LEVELS) {
+                    $defaultnumberoflevels = $nlevels;
+                } else {
+                    // If it is less than the default value it sets it to
+                    // the default value.
+                    $defaultnumberoflevels = self::DEFAULT_RUBRIC_LEVELS;
+                }
+
+                foreach ($criterion as $i => $value) {
+
+                    $levelroot = $criterionroot . '[levels][NEWID' . $levelnumber . ']';
+
+                    if ($i % 2 === 0) {
+                        // Pairs are the definitions.
+                        $fieldname = $levelroot . '[definition]';
+                        $this->set_rubric_field_value($fieldname, $value);
+
+                    } else {
+                        // Odds are the points.
+
+                        // Checking it now, we would need to remove it if we are testing the form validations...
+                        if (!is_numeric($value)) {
+                            throw new ExpectationException(
+                                'The points cells should contain numeric values, follow this format: ' . $steptableinfo,
+                                $this->getSession()
+                            );
+                        }
+
+                        $fieldname = $levelroot . '[score]';
+                        $this->set_rubric_field_value($fieldname, $value, true);
+
+                        // Increase the level by one every 2 cells.
+                        $levelnumber++;
+                    }
+
+                }
+            }
+        }
+    }
+
+    /**
+     * Replaces a value from the specified criterion. You can use it when editing rubrics, to set both name or points.
+     *
+     * @When /^I replace "(?P<current_value_string>(?:[^"]|\\")*)" rubric level with "(?P<value_string>(?:[^"]|\\")*)" in "(?P<criterion_string>(?:[^"]|\\")*)" criterion$/
+     * @throws ElementNotFoundException
+     * @param string $currentvalue
+     * @param string $value
+     * @param string $criterionname
+     * @return Given[]
+     */
+    public function i_replace_rubric_level_with($currentvalue, $value, $criterionname) {
+
+        $currentvalueliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($currentvalue);
+        $criterionliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($criterionname);
+
+        $criterionxpath = "//div[@id='rubric-rubric']" .
+            "/descendant::td[contains(concat(' ', normalize-space(@class), ' '), ' description ')]";
+        // It differs between JS on/off.
+        if ($this->running_javascript()) {
+            $criterionxpath .= "/descendant::span[@class='textvalue'][text()=$criterionliteral]" .
+                "/ancestor::tr[contains(concat(' ', normalize-space(@class), ' '), ' criterion ')]";
+        } else {
+            $criterionxpath .= "/descendant::textarea[text()=$criterionliteral]" .
+                "/ancestor::tr[contains(concat(' ', normalize-space(@class), ' '), ' criterion ')]";
+        }
+
+        $inputxpath = $criterionxpath .
+            "/descendant::input[@type='text'][@value=$currentvalueliteral]";
+        $textareaxpath = $criterionxpath .
+            "/descendant::textarea[text()=$currentvalueliteral]";
+
+        if ($this->running_javascript()) {
+
+            $spansufix = "/ancestor::div[@class='level-wrapper']" .
+                "/descendant::div[@class='definition']" .
+                "/descendant::span[@class='textvalue']";
+
+            // Expanding the level input boxes.
+            $spannode = $this->find('xpath', $inputxpath . $spansufix . '|' . $textareaxpath . $spansufix);
+            $spannode->click();
+
+            $inputfield = $this->find('xpath', $inputxpath . '|' . $textareaxpath);
+            $inputfield->setValue($value);
+
+        } else {
+            $fieldnode = $this->find('xpath', $inputxpath . '|' . $textareaxpath);
+            $this->set_rubric_field_value($fieldnode->getAttribute('name'), $value);
+        }
+
+    }
+
+    /**
+     * Grades filling the current page rubric. Set one line per criterion and for each criterion set "| Criterion name | Points | Remark |".
+     *
+     * @When /^I grade by filling the rubric with:$/
+     *
+     * @throws ExpectationException
+     * @param TableNode $rubric
+     * @return void
+     */
+    public function i_grade_by_filling_the_rubric_with(TableNode $rubric) {
+
+        $criteria = $rubric->getRowsHash();
+
+        $stepusage = '"I grade by filling the rubric with:" step needs you to provide a table where each row is a criterion' .
+            ' and each criterion has 3 different values: | Criterion name | Number of points | Remark text |';
+
+        // To fill with the steps to execute.
+        $steps = array();
+
+        // First element -> name, second -> points, third -> Remark.
+        foreach ($criteria as $name => $criterion) {
+
+            // We only expect the points and the remark, as the criterion name is $name.
+            if (count($criterion) !== 2) {
+                throw new ExpectationException($stepusage, $this->getSession());
+            }
+
+            // Numeric value here.
+            $points = $criterion[0];
+            if (!is_numeric($points)) {
+                throw new ExpectationException($stepusage, $this->getSession());
+            }
+
+            // Selecting a value.
+            // When JS is disabled there are radio options, with JS enabled divs.
+            $selectedlevelxpath = $this->get_level_xpath($points);
+            if ($this->running_javascript()) {
+
+                // Only clicking on the selected level if it was not already selected.
+                $levelnode = $this->find('xpath', $selectedlevelxpath);
+
+                // Using in_array() as there are only a few elements.
+                if (!in_array('checked', explode(' ', $levelnode->getAttribute('class')))) {
+                    $steps[] = new Given('I click on "' . $selectedlevelxpath . '" "xpath_element" in the "' .
+                        $this->escape($name) . '" "table_row"');
+                }
+
+            } else {
+
+                // Getting the name of the field.
+                $radioxpath = $this->get_criterion_xpath($name) .
+                    $selectedlevelxpath . "/descendant::input[@type='radio']";
+                $radionode = $this->find('xpath', $radioxpath);
+                // TODO MDL-43738: Change setValue() to use the generic set_value()
+                // which will delegate the process to the field type.
+                $radionode->setValue($radionode->getAttribute('value'));
+            }
+
+            // Setting the remark.
+
+            // First we need to get the textarea name, then we can set the value.
+            $textarea = $this->get_node_in_container('css_element', 'textarea', 'table_row', $name);
+            $steps[] = new Given('I fill in "' . $textarea->getAttribute('name') . '" with "' . $criterion[1] . '"');
+        }
+
+        return $steps;
+    }
+
+    /**
+     * Checks that the level was previously selected and the user changed to another level.
+     *
+     * @Then /^the level with "(?P<points_number>\d+)" points was previously selected for the rubric criterion "(?P<criterion_name_string>(?:[^"]|\\")*)"$/
+     * @throws ExpectationException
+     * @param string $criterionname
+     * @param int $points
+     * @return void
+     */
+    public function the_level_with_points_was_previously_selected_for_the_rubric_criterion($points, $criterionname) {
+
+        $levelxpath = $this->get_criterion_xpath($criterionname) .
+            $this->get_level_xpath($points) .
+            "[contains(concat(' ', normalize-space(@class), ' '), ' currentchecked ')]";
+
+        // Works both for JS and non-JS.
+        // - JS: Class -> checked is there when is marked as green.
+        // - Non-JS: When editing a rubric definition, there are radio inputs and when viewing a
+        //   grade @class contains checked.
+        $levelxpath .= "[not(contains(concat(' ', normalize-space(@class), ' '), ' checked '))]" .
+            "[not(/descendant::input[@type='radio'][@checked!='checked'])]";
+
+        try {
+            $this->find('xpath', $levelxpath);
+        } catch (ElementNotFoundException $e) {
+            throw new ExpectationException('"' . $points . '" points level was not previously selected', $this->getSession());
+        }
+    }
+
+    /**
+     * Checks that the level is currently selected. Works both when grading rubrics and viewing graded rubrics.
+     *
+     * @Then /^the level with "(?P<points_number>\d+)" points is selected for the rubric criterion "(?P<criterion_name_string>(?:[^"]|\\")*)"$/
+     * @throws ExpectationException
+     * @param string $criterionname
+     * @param int $points
+     * @return void
+     */
+    public function the_level_with_points_is_selected_for_the_rubric_criterion($points, $criterionname) {
+
+        $levelxpath = $this->get_criterion_xpath($criterionname) .
+            $this->get_level_xpath($points);
+
+        // Works both for JS and non-JS.
+        // - JS: Class -> checked is there when is marked as green.
+        // - Non-JS: When editing a rubric definition, there are radio inputs and when viewing a
+        //   grade @class contains checked.
+        $levelxpath .= "[" .
+            "contains(concat(' ', normalize-space(@class), ' '), ' checked ')" .
+            " or " .
+            "/descendant::input[@type='radio'][@checked='checked']" .
+            "]";
+
+        try {
+            $this->find('xpath', $levelxpath);
+        } catch (ElementNotFoundException $e) {
+            throw new ExpectationException('"' . $points . '" points level is not selected', $this->getSession());
+        }
+    }
+
+    /**
+     * Checks that the level is not currently selected. Works both when grading rubrics and viewing graded rubrics.
+     *
+     * @Then /^the level with "(?P<points_number>\d+)" points is not selected for the rubric criterion "(?P<criterion_name_string>(?:[^"]|\\")*)"$/
+     * @throws ExpectationException
+     * @param string $criterionname
+     * @param int $points
+     * @return void
+     */
+    public function the_level_with_points_is_not_selected_for_the_rubric_criterion($points, $criterionname) {
+
+        $levelxpath = $this->get_criterion_xpath($criterionname) .
+            $this->get_level_xpath($points);
+
+        // Works both for JS and non-JS.
+        // - JS: Class -> checked is there when is marked as green.
+        // - Non-JS: When editing a rubric definition, there are radio inputs and when viewing a
+        //   grade @class contains checked.
+        $levelxpath .= "[not(contains(concat(' ', normalize-space(@class), ' '), ' checked '))]" .
+            "[./descendant::input[@type='radio'][@checked!='checked'] or not(./descendant::input[@type='radio'])]";
+
+        try {
+            $this->find('xpath', $levelxpath);
+        } catch (ElementNotFoundException $e) {
+            throw new ExpectationException('"' . $points . '" points level is selected', $this->getSession());
+        }
+    }
+
+
+    /**
+     * Makes a hidden rubric field visible (if necessary) and sets a value on it.
+     *
+     * @param string $name The name of the field
+     * @param string $value The value to set
+     * @param bool $visible
+     * @return void
+     */
+    protected function set_rubric_field_value($name, $value, $visible = false) {
+
+        // Fields are hidden by default.
+        if ($this->running_javascript() == true && $visible === false) {
+            $xpath = "//*[@name='$name']/following-sibling::*[contains(concat(' ', normalize-space(@class), ' '), ' plainvalue ')]";
+            $textnode = $this->find('xpath', $xpath);
+            $textnode->click();
+        }
+
+        // Set the value now.
+        $description = $this->find_field($name);
+        $description->setValue($value);
+    }
+
+    /**
+     * Performs click confirming the action.
+     *
+     * @param NodeElement $node
+     * @return void
+     */
+    protected function click_and_confirm($node) {
+
+        // Clicks to perform the action.
+        $node->click();
+
+        // Confirms the delete.
+        if ($this->running_javascript()) {
+            $confirmbutton = $this->get_node_in_container(
+                'button',
+                get_string('yes'),
+                'dialogue',
+                get_string('confirmation', 'admin')
+            );
+            $confirmbutton->click();
+        }
+    }
+
+    /**
+     * Returns the xpath representing a selected level.
+     *
+     * It is not including the path to the criterion.
+     *
+     * It is the xpath when grading a rubric or viewing a rubric,
+     * it is not the same xpath when editing a rubric.
+     *
+     * @param int $points
+     * @return string
+     */
+    protected function get_level_xpath($points) {
+        return "//td[contains(concat(' ', normalize-space(@class), ' '), ' level ')]" .
+            "[./descendant::span[@class='scorevalue'][text()='$points']]";
+    }
+
+    /**
+     * Returns the xpath representing the selected criterion.
+     *
+     * It is the xpath when grading a rubric or viewing a rubric,
+     * it is not the same xpath when editing a rubric.
+     *
+     * @param string $criterionname Literal including the criterion name.
+     * @return string
+     */
+    protected function get_criterion_xpath($criterionname) {
+        $literal = $this->getSession()->getSelectorsHandler()->xpathLiteral($criterionname);
+        return "//tr[contains(concat(' ', normalize-space(@class), ' '), ' criterion ')]" .
+            "[./descendant::td[@class='description'][text()=$literal]]";
+    }
+}
diff --git a/grade/grading/form/rubric/tests/behat/edit_rubric.feature b/grade/grading/form/rubric/tests/behat/edit_rubric.feature
new file mode 100644 (file)
index 0000000..2ff3a9a
--- /dev/null
@@ -0,0 +1,159 @@
+@gradingform @gradingform_rubric
+Feature: Rubrics can be created and edited
+  In order to use and refine rubrics to grade students
+  As a teacher
+  I need to edit previously used rubrics
+
+  Background:
+    Given the following "users" exists:
+      | username | firstname | lastname | email |
+      | teacher1 | Teacher | 1 | teacher1@asd.com |
+      | student1 | Student | 1 | student1@asd.com |
+    And the following "courses" exists:
+      | fullname | shortname | format |
+      | Course 1 | C1 | topics |
+    And the following "course enrolments" exists:
+      | user | course | role |
+      | teacher1 | C1 | editingteacher |
+      | student1 | C1 | student |
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I turn editing mode on
+    And I add a "Assignment" to section "1" and I fill the form with:
+      | Assignment name | Test assignment 1 name |
+      | Description | Test assignment description |
+      | Grading method | Rubric |
+    When I go to "Test assignment 1 name" advanced grading definition page
+    # Defining a rubric.
+    And I fill the moodle form with:
+      | Name | Assignment 1 rubric |
+      | Description | Rubric test description |
+    And I define the following rubric:
+      | TMP Criterion 1 | TMP Level 11 | 11 | TMP Level 12 | 12 |
+      | TMP Criterion 2 | TMP Level 21 | 21 | TMP Level 22 | 22 |
+      | TMP Criterion 3 | TMP Level 31 | 31 | TMP Level 32 | 32 |
+      | TMP Criterion 4 | TMP Level 41 | 41 | TMP Level 42 | 42 |
+    # Checking that only the last ones are saved.
+    And I define the following rubric:
+      | Criterion 1 | Level 11 | 1 | Level 12 | 20 | Level 13 | 40 | Level 14 | 50 |
+      | Criterion 2 | Level 21 | 10 | Level 22 | 20 | Level 23 | 30 |
+      | Criterion 3 | Level 31 | 5 | Level 32 | 20 |
+    And I press "Save as draft"
+    And I go to "Test assignment 1 name" advanced grading definition page
+    And I click on "Move down" "button" in the "Criterion 1" "table_row"
+    And I press "Save rubric and make it ready"
+    Then I should see "Ready for use"
+    # Grading two students.
+    And I go to "Student 1" "Test assignment 1 name" activity advanced grading page
+    And I grade by filling the rubric with:
+      | Criterion 1 | 50 | Very good |
+    And I press "Save changes"
+    # Checking that it complains if you don't select a level for each criterion.
+    And I should see "Please choose something for each criterion"
+    And I grade by filling the rubric with:
+      | Criterion 1 | 50 | Very good |
+      | Criterion 2 | 10 | Mmmm, you can do it better |
+      | Criterion 3 | 5 | Not good |
+    And I complete the advanced grading form with these values:
+      | Feedback comments | In general... work harder... |
+    # Checking that the user grade is correct.
+    And I should see "58.33" in the "Student 1" "table_row"
+    # Updating the user grade.
+    And I go to "Student 1" "Test assignment 1 name" activity advanced grading page
+    And I grade by filling the rubric with:
+      | Criterion 1 | 20 | Bad, I changed my mind |
+      | Criterion 2 | 10 | Mmmm, you can do it better |
+      | Criterion 3 | 5 | Not good |
+    #And the level with "50" points was previously selected for the rubric criterion "Criterion 1"
+    #And the level with "20" points is selected for the rubric criterion "Criterion 1"
+    And I save the advanced grading form
+    And I should see "22.62" in the "Student 1" "table_row"
+    And I log out
+    # Viewing it as a student.
+    And I log in as "student1"
+    And I follow "Course 1"
+    And I follow "Test assignment 1 name"
+    And I should see "22.62" in the ".feedback" "css_element"
+    And I should see "Rubric test description" in the ".feedback" "css_element"
+    And I should see "In general... work harder..."
+    And the level with "10" points is selected for the rubric criterion "Criterion 2"
+    And the level with "20" points is selected for the rubric criterion "Criterion 1"
+    And the level with "5" points is selected for the rubric criterion "Criterion 3"
+    And I log out
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    # Editing a rubric definition without regrading students.
+    And I go to "Test assignment 1 name" advanced grading definition page
+    And "Save as draft" "button" should not exists
+    And I click on "Move up" "button" in the "Criterion 1" "table_row"
+    And I replace "Level 11" rubric level with "Level 11 edited" in "Criterion 1" criterion
+    And I press "Save"
+    And I should see "You are about to save changes to a rubric that has already been used for grading."
+    And I select "Do not mark for regrade" from "menurubricregrade"
+    And I press "Continue"
+    And I log out
+    # Check that the student still sees the grade.
+    And I log in as "student1"
+    And I follow "Course 1"
+    And I follow "Test assignment 1 name"
+    And I should see "22.62" in the ".feedback" "css_element"
+    And the level with "20" points is selected for the rubric criterion "Criterion 1"
+    And I log out
+    # Editing a rubric with significant changes.
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I go to "Test assignment 1 name" advanced grading definition page
+    And I click on "Move down" "button" in the "Criterion 2" "table_row"
+    And I replace "1" rubric level with "11" in "Criterion 1" criterion
+    And I press "Save"
+    And I should see "You are about to save significant changes to a rubric that has already been used for grading. The gradebook value will be unchanged, but the rubric will be hidden from students until their item is regraded."
+    And I press "Continue"
+    And I log out
+    # Check that the student doesn't see the grade.
+    And I log in as "student1"
+    And I follow "Course 1"
+    And I follow "Test assignment 1 name"
+    And I should see "22.62" in the ".feedback" "css_element"
+    And the level with "20" points is not selected for the rubric criterion "Criterion 1"
+    And I log out
+    # Regrade student.
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I follow "Test assignment 1 name"
+    And I go to "Student 1" "Test assignment 1 name" activity advanced grading page
+    And I should see "The rubric definition was changed after this student had been graded. The student can not see this rubric until you check the rubric and update the grade."
+    And I save the advanced grading form
+    And I log out
+    # Check that the student sees the grade again.
+    And I log in as "student1"
+    And I follow "Course 1"
+    And I follow "Test assignment 1 name"
+    And I should see "12.16" in the ".feedback" "css_element"
+    And the level with "20" points is not selected for the rubric criterion "Criterion 1"
+    # Hide all rubric info for students
+    And I log out
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I go to "Test assignment 1 name" advanced grading definition page
+    And I uncheck "Allow users to preview rubric used in the module (otherwise rubric will only become visible after grading)"
+    And I uncheck "Display rubric description during evaluation"
+    And I uncheck "Display rubric description to those being graded"
+    And I uncheck "Display points for each level during evaluation"
+    And I uncheck "Display points for each level to those being graded"
+    And I press "Save"
+    And I select "Do not mark for regrade" from "menurubricregrade"
+    And I press "Continue"
+    And I log out
+    # Students should not see anything.
+    And I log in as "student1"
+    And I follow "Course 1"
+    And I follow "Test assignment 1 name"
+    And I should not see "Criterion 1" in the ".submissionstatustable" "css_element"
+    And I should not see "Criterion 2" in the ".submissionstatustable" "css_element"
+    And I should not see "Criterion 3" in the ".submissionstatustable" "css_element"
+    And I should not see "Rubric test description" in the ".feedback" "css_element"
+
+  @javascript
+  Scenario: I can use rubrics to grade and edit them later updating students grades with Javascript enabled
+
+  Scenario: I can use rubrics to grade and edit them later updating students grades with Javascript disabled
diff --git a/grade/grading/form/rubric/tests/behat/publish_rubric_templates.feature b/grade/grading/form/rubric/tests/behat/publish_rubric_templates.feature
new file mode 100644 (file)
index 0000000..302a12f
--- /dev/null
@@ -0,0 +1,56 @@
+@gradingform @gradingform_rubric
+Feature: Publish rubrics as templates
+  In order to save time to teachers
+  As a manager
+  I need to publish rubrics and make them available to all teachers
+
+  Background:
+    Given the following "users" exists:
+      | username | firstname | lastname | email |
+      | teacher1 | Teacher | 1 | teacher1@asd.com |
+      | manager1 | Manager | 1 | manager1@asd.com |
+    And the following "courses" exists:
+      | fullname | shortname | format |
+      | Course 1 | C1 | topics |
+    And the following "activities" exists:
+      | activity | course | idnumber | name                   | intro | advancedgradingmethod_submissions |
+      | assign   | C1     | A1       | Test assignment 1 name | TA1   | rubric                            |
+      | assign   | C1     | A2       | Test assignment 2 name | TA2   | rubric                            |
+    And the following "course enrolments" exists:
+      | user | course | role |
+      | teacher1 | C1 | editingteacher |
+    And the following "system role assigns" exists:
+      | user | role | contextlevel | reference |
+      | manager1 | manager | System | |
+    And I log in as "manager1"
+    And I follow "Course 1"
+    And I go to "Test assignment 1 name" advanced grading definition page
+    And I fill the moodle form with:
+      | Name | Assignment 1 rubric |
+      | Description | Assignment 1 description |
+    And I define the following rubric:
+      | Criterion 1 | Level 11 | 11 | Level 12 | 12 |
+      | Criterion 2 | Level 21 | 21 | Level 22 | 22 |
+    And I press "Save rubric and make it ready"
+    When I publish "Test assignment 1 name" grading form definition as a public template
+    And I log out
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I set "Test assignment 2 name" activity to use "Assignment 1 rubric" grading form
+    Then I should see "Advanced grading: Test assignment 2 name (Submissions)"
+    And I should see "Criterion 1"
+    And I should see "Assignment 1 description"
+    And I go to "Test assignment 2 name" advanced grading definition page
+    And I should see "Current rubric status"
+
+  @javascript
+  Scenario: Create a rubric template and reuse it as a teacher, with Javascript enabled
+    Then the "Description" field should match "<p>Assignment 1 description</p>" value
+    And I should see "Criterion 1"
+    And I press "Cancel"
+
+  Scenario: Create a rubric template and reuse it as a teacher, with Javascript disabled
+    Then the "Description" field should match "Assignment 1 description" value
+    # Trying to avoid pointing by id or name as the code internals may change.
+    And "//table[@class='criteria']//textarea[text()='Criterion 1']" "xpath_element" should exists
+    And I press "Cancel"
diff --git a/grade/grading/form/rubric/tests/behat/reuse_own_rubrics.feature b/grade/grading/form/rubric/tests/behat/reuse_own_rubrics.feature
new file mode 100644 (file)
index 0000000..0c3799c
--- /dev/null
@@ -0,0 +1,52 @@
+@gradingform @gradingform_rubric
+Feature: Reuse my rubrics in other activities
+  In order to save time creating duplicated grading forms
+  As a teacher
+  I need to reuse rubrics that I created previously
+
+  Background:
+    Given the following "users" exists:
+      | username | firstname | lastname | email |
+      | teacher1 | Teacher | 1 | teacher1@asd.com |
+    And the following "courses" exists:
+      | fullname | shortname | format |
+      | Course 1 | C1 | topics |
+    And the following "course enrolments" exists:
+      | user | course | role |
+      | teacher1 | C1 | editingteacher |
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I turn editing mode on
+    And I add a "Assignment" to section "1" and I fill the form with:
+      | Assignment name | Test assignment 1 name |
+      | Description | Test assignment 1 description |
+      | Grading method | Rubric |
+    And I go to "Test assignment 1 name" advanced grading definition page
+    And I fill the moodle form with:
+      | Name | Assignment 1 rubric |
+      | Description | Assignment 1 description |
+    And I define the following rubric:
+      | Criterion 1 | Level 11 | 11 | Level 12 | 12 | Level 3 | 13 |
+      | Criterion 2 | Level 21 | 21 | Level 22 | 22 | Level 3 | 23 |
+      | Criterion 3 | Level 31 | 31 | Level 32 | 32 |
+    And I press "Save rubric and make it ready"
+    And I follow "Course 1"
+    When I add a "Assignment" to section "1" and I fill the form with:
+      | Assignment name | Test assignment 2 name |
+      | Description | Test assignment 2 description |
+      | Grading method | Rubric |
+    And I set "Test assignment 2 name" activity to use "Assignment 1 rubric" grading form
+    Then I should see "Ready for use"
+    And I should see "Criterion 1"
+    And I should see "Criterion 2"
+    And I should see "Criterion 3"
+    And I go to "Test assignment 1 name" advanced grading definition page
+    And I should see "Criterion 1"
+    And I should see "Criterion 2"
+    And I should see "Criterion 3"
+    And I press "Cancel"
+
+  @javascript
+  Scenario: A teacher can reuse one of his/her previously created rubrics, with Javascript enabled
+
+  Scenario: A teacher can reuse one of his/her previously created rubrics, with Javascript disabled
diff --git a/grade/grading/tests/behat/behat_grading.php b/grade/grading/tests/behat/behat_grading.php
new file mode 100644 (file)
index 0000000..3c60cd6
--- /dev/null
@@ -0,0 +1,181 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Grading methods steps definitions.
+ *
+ * @package   core_grading
+ * @category  test
+ * @copyright 2013 David Monllaó
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
+
+require_once(__DIR__ . '/../../../../lib/behat/behat_base.php');
+
+use Behat\Gherkin\Node\TableNode as TableNode,
+    Behat\Behat\Context\Step\Given as Given,
+    Behat\Behat\Context\Step\When as When;
+
+/**
+ * Generic grading methods step definitions.
+ *
+ * @package   core_grading
+ * @category  test
+ * @copyright 2013 David Monllaó
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class behat_grading extends behat_base {
+
+    /**
+     * Goes to the selected advanced grading page. You should be in the course page when this step begins.
+     *
+     * @Given /^I go to "(?P<activity_name_string>(?:[^"]|\\")*)" advanced grading page$/
+     * @param string $activityname
+     * @return Given[]
+     */
+    public function i_go_to_advanced_grading_page($activityname) {
+        return array(
+            new Given('I follow "' . $this->escape($activityname) . '"'),
+            new Given('I follow "' . get_string('gradingmanagement', 'grading') . '"'),
+        );
+    }
+
+    /**
+     * Goes to the selected advanced grading definition page. You should be in the course page when this step begins.
+     *
+     * @Given /^I go to "(?P<activity_name_string>(?:[^"]|\\")*)" advanced grading definition page$/
+     * @param string $activityname
+     * @return Given[]
+     */
+    public function i_go_to_advanced_grading_definition_page($activityname) {
+
+        // Transforming to literals, probably not necessary, just in case.
+        $newactionliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral(get_string("manageactionnew", "grading"));
+        $editactionliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral(get_string("manageactionedit", "grading"));
+
+        // Working both when adding and editing.
+        $definitionxpath = "//a[@class='action']" .
+            "[./descendant::*[contains(., $newactionliteral) or contains(., $editactionliteral)]]";
+
+        return array(
+            new Given('I go to "' . $this->escape($activityname) . '" advanced grading page'),
+            new Given('I click on "' . $this->escape($definitionxpath) . '" "xpath_element"'),
+        );
+    }
+    /**
+     * Goes to the student's advanced grading page.
+     *
+     * @Given /^I go to "(?P<user_fullname_string>(?:[^"]|\\")*)" "(?P<activity_name_string>(?:[^"]|\\")*)" activity advanced grading page$/
+     * @param string $userfullname The user full name including firstname and lastname.
+     * @param string $activityname The activity name
+     * @return Given[]
+     */
+    public function i_go_to_activity_advanced_grading_page($userfullname, $activityname) {
+
+        // Step to access the user grade page from the grading page.
+        $usergradetext = get_string('gradeuser', 'assign', $userfullname);
+        $gradeuserstep = new Given('I follow "' . $this->escape($usergradetext) . '"');
+
+        // Shortcut in case we already are in the grading page.
+        $usergradetextliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($usergradetext);
+        if ($this->getSession()->getPage()->find('named', array('link', $usergradetextliteral))) {
+            return $gradeuserstep;
+        }
+
+        return array(
+            new Given('I follow "' . $this->escape($activityname) . '"'),
+            new Given('I follow "' . $this->escape(get_string('viewgrading', 'assign')) . '"'),
+            $gradeuserstep
+        );
+    }
+
+    /**
+     * Publishes current activity grading defined form as a public template.
+     *
+     * @Given /^I publish "(?P<activity_name_string>(?:[^"]|\\")*)" grading form definition as a public template$/
+     * @param string $activityname
+     * @return Given[]
+     */
+    public function i_publish_grading_form_definition_as_a_public_template($activityname) {
+
+        return array(
+            new Given('I go to "' . $this->escape($activityname) . '" advanced grading page'),
+            new Given('I click on "' . $this->escape(get_string("manageactionshare", "grading")) . '" "link"'),
+            new Given('I press "' . get_string('continue') . '"')
+        );
+    }
+
+    /**
+     * Sets a previously created grading form as the activity grading form.
+     *
+     * @Given /^I set "(?P<activity_name_string>(?:[^"]|\\")*)" activity to use "(?P<grading_form_template_string>(?:[^"]|\\")*)" grading form$/
+     * @param string $activityname
+     * @param string $templatename
+     * @return Given[]
+     */
+    public function i_set_activity_to_use_grading_form($activityname, $templatename) {
+
+        $templateliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($templatename);
+
+        $templatexpath = "//h2[@class='template-name'][contains(., $templateliteral)]/" .
+            "following-sibling::div[contains(concat(' ', normalize-space(@class), ' '), ' template-actions ')]";
+
+        // Should work with both templates and own forms.
+        $literaltemplate = $this->getSession()->getSelectorsHandler()->xpathLiteral(get_string('templatepick', 'grading'));
+        $literalownform = $this->getSession()->getSelectorsHandler()->xpathLiteral(get_string('templatepickownform', 'grading'));
+        $usetemplatexpath = "//a[./descendant::div[text()=$literaltemplate]]|" .
+            "//a[./descendant::div[text()=$literalownform]]";
+
+        return array(
+            new Given('I go to "' . $this->escape($activityname) . '" advanced grading page'),
+            new Given('I follow "' . $this->escape(get_string('manageactionclone', 'grading')) . '"'),
+            new Given('I check "' . get_string('searchownforms', 'grading') . '"'),
+            new Given('I click on "' . get_string('search') . '" "button" in the "region-main" "region"'),
+            new Given('I click on "' . $this->escape($usetemplatexpath) . '" "xpath_element" ' .
+                'in the "' . $this->escape($templatexpath) . '" "xpath_element"'),
+            new Given('I press "' . get_string('continue') . '"')
+        );
+    }
+
+    /**
+     * Saves the current page advanced grading form.
+     *
+     * @When /^I save the advanced grading form$/
+     * @return When[]
+     */
+    public function i_save_the_advanced_grading_form() {
+        return array(
+            new When('I press "' . get_string('savechanges') . '"'),
+            new When('I press "' . get_string('continue') . '"')
+        );
+    }
+
+    /**
+     * Grades an activity using advanced grading. Note the grade is set by other steps, depending on the grading method.
+     *
+     * @Given /^I complete the advanced grading form with these values:$/
+     * @param TableNode $data
+     * @return Given[]
+     */
+    public function i_complete_the_advanced_grading_form_with_these_values(TableNode $data) {
+        return array(
+            new Given('I fill the moodle form with:', $data),
+            new Given('I save the advanced grading form')
+        );
+    }
+}
index 07d6e2e..990764c 100644 (file)
@@ -235,7 +235,7 @@ if ($formdata = $mform2->get_data()) {
                     $studentid = $value;
                 break;
                 case 'useridnumber':
-                    if (!$user = $DB->get_record('user', array('idnumber' => $value))) {
+                    if (empty($value) || !$user = $DB->get_record('user', array('idnumber' => $value))) {
                          // user not found, abort whole import
                         import_cleanup($importcode);
                         echo $OUTPUT->notification("user mapping error, could not find user with idnumber \"$value\"");
index 5e83918..f3e7f37 100644 (file)
@@ -152,20 +152,11 @@ $currenttab = 'groups';
 require('tabs.php');
 
 $disabled = 'disabled="disabled"';
-$ajaxenabled = ajaxenabled();
-if ($ajaxenabled) {
-    // Some buttons are enabled if single group selected
-    $showaddmembersform_disabled = $singlegroup ? '' : $disabled;
-    $showeditgroupsettingsform_disabled = $singlegroup ? '' : $disabled;
-    $deletegroup_disabled = count($groupids)>0 ? '' : $disabled;
-} else {
-    // Do not disable buttons. The buttons work based on the selected group,
-    // which you can change without reloading the page, so it is not appropriate
-    // to disable them if no group is selected.
-    $showaddmembersform_disabled = '';
-    $showeditgroupsettingsform_disabled = '';
-    $deletegroup_disabled = '';
-}
+
+// Some buttons are enabled if single group selected.
+$showaddmembersform_disabled = $singlegroup ? '' : $disabled;
+$showeditgroupsettingsform_disabled = $singlegroup ? '' : $disabled;
+$deletegroup_disabled = count($groupids) > 0 ? '' : $disabled;
 
 echo $OUTPUT->heading(format_string($course->shortname, true, array('context' => $context)) .' '.$strgroups, 3);
 echo '<form id="groupeditform" action="index.php" method="post">'."\n";
@@ -179,11 +170,7 @@ echo '<tr>'."\n";
 echo "<td>\n";
 echo '<p><label for="groups"><span id="groupslabel">'.get_string('groups').':</span><span id="thegrouping">&nbsp;</span></label></p>'."\n";
 
-if ($ajaxenabled) { // TODO: move this to JS init!
-    $onchange = 'M.core_group.membersCombo.refreshMembers();';
-} else {
-    $onchange = '';
-}
+$onchange = 'M.core_group.membersCombo.refreshMembers();';
 
 echo '<select name="groups[]" multiple="multiple" id="groups" size="15" class="select" onchange="'.$onchange.'"'."\n";
 echo ' onclick="window.status=this.selectedIndex==-1 ? \'\' : this.options[this.selectedIndex].title;" onmouseout="window.status=\'\';">'."\n";
@@ -276,10 +263,8 @@ echo '</table>'."\n";
 echo '</div>'."\n";
 echo '</form>'."\n";
 
-if ($ajaxenabled) {
-    $PAGE->requires->js_init_call('M.core_group.init_index', array($CFG->wwwroot, $courseid));
-    $PAGE->requires->js_init_call('M.core_group.groupslist', array($preventgroupremoval));
-}
+$PAGE->requires->js_init_call('M.core_group.init_index', array($CFG->wwwroot, $courseid));
+$PAGE->requires->js_init_call('M.core_group.groupslist', array($preventgroupremoval));
 
 echo $OUTPUT->footer();
 
index 2ef3ae1..16a05fb 100644 (file)
@@ -192,12 +192,12 @@ $string['configenabledevicedetection'] = 'Enables detection of mobiles, smartpho
 $string['configdisableuserimages'] = 'Disable the ability for users to change user profile images.';
 $string['configdisplayloginfailures'] = 'This will display information to selected users about previous failed logins.';
 $string['configdndallowtextandlinks'] = 'Enable or disable the dragging and dropping of text and links onto a course page, alongside the dragging and dropping of files. Note that the dragging of text into Firefox or between different browsers is unreliable and may result in no data being uploaded, or corrupted text being uploaded.';
+$string['configdoclang'] = 'This language will be used in links for the documentation pages.';
 $string['configdocroot'] = 'Defines the path to the Moodle Docs for providing context-specific documentation via \'Moodle Docs for this page\' links in the footer of each page. If the field is left blank, links will not be displayed.';
 $string['configdoctonewwindow'] = 'If you enable this, then links to Moodle Docs will be shown in a new window.';
 $string['configeditordictionary'] = 'This value will be used if aspell doesn\'t have dictionary for users own language.';
 $string['configeditorfontlist'] = 'Select the fonts that should appear in the editor\'s drop-down list.';
 $string['configemailchangeconfirmation'] = 'Require an email confirmation step when users change their email address in their profile.';
-$string['configenableajax'] = 'This setting controls the use of AJAX across the site. AJAX is required for certain functionality such as drag and drop.';
 $string['configenablecalendarexport'] = 'Enable exporting or subscribing to calendars.';
 $string['configenablecomments'] = 'Enable comments';
 $string['configenablecourserequests'] = 'This will allow any user to request a course be created.';
@@ -429,6 +429,7 @@ $string['disableuserimages'] = 'Disable user profile images';
 $string['displayerrorswarning'] = 'Enabling the PHP setting <em>display_errors</em> is not recommended on production sites because some error messages may reveal sensitive information about your server.';
 $string['displayloginfailures'] = 'Display login failures to';
 $string['dndallowtextandlinks'] = 'Drag and drop upload of text/links';
+$string['doclang'] = 'Language for docs';
 $string['docroot'] = 'Moodle Docs document root';
 $string['doctonewwindow'] = 'Open in new window';
 $string['download'] = 'Download';
@@ -459,7 +460,6 @@ $string['emoticons_desc'] = 'This form defines the emoticons (or smileys) used a
 * Alternative text (optional) - String identifier and component of the alternative text of the emoticon.';
 $string['emoticonsreset'] = 'Reset emoticons setting to default values';
 $string['emptysettingvalue'] = 'Empty';
-$string['enableajax'] = 'Enable AJAX';
 $string['enableblogs'] = 'Enable blogs';
 $string['enablecalendarexport'] = 'Enable calendar export';
 $string['enablecomments'] = 'Enable comments';
index c9f21f8..56fd008 100644 (file)
@@ -40,34 +40,6 @@ function user_preference_allow_ajax_update($name, $paramtype) {
     $USER->ajax_updatable_user_prefs[$name] = $paramtype;
 }
 
-/**
- * Returns whether ajax is enabled/allowed or not.
- * @param array $browsers optional list of alowed browsers, empty means use default list
- * @return bool
- */
-function ajaxenabled(array $browsers = null) {
-    global $CFG;
-
-    if (!empty($browsers)) {
-        $valid = false;
-        foreach ($browsers as $brand => $version) {
-            if (core_useragent::check_browser_version($brand, $version)) {
-                $valid = true;
-            }
-        }
-
-        if (!$valid) {
-            return false;
-        }
-    }
-
-    if (!empty($CFG->enableajax)) {
-        return true;
-    } else {
-        return false;
-    }
-}
-
 /**
  * Starts capturing output whilst processing an AJAX request.
  *
index b0153d9..48688b0 100644 (file)
@@ -83,10 +83,10 @@ class behat_selectors {
      */
     protected static $moodleselectors = array(
         'dialogue' => <<<XPATH
-.//div[contains(concat(' ', normalize-space(@class), ' '), ' moodle-dialogue ')]/descendant::h1[normalize-space(.) = %locator%]/ancestor::div[contains(concat(' ', normalize-space(@class), ' '), ' moodle-dialogue ')]
+//div[contains(concat(' ', normalize-space(@class), ' '), ' moodle-dialogue ')]/descendant::h1[normalize-space(.) = %locator%]/ancestor::div[contains(concat(' ', normalize-space(@class), ' '), ' moodle-dialogue ')] | //div[contains(concat(' ', normalize-space(@class), ' '), ' yui-dialog ')]/descendant::div[@class='hd'][normalize-space(.) = %locator%]/parent::div
 XPATH
         , 'block' => <<<XPATH
-.//div[contains(concat(' ', normalize-space(@class), ' '), concat(' ', %locator%, ' '))] | .//div[contains(concat(' ', normalize-space(@class), ' '), ' block ')]/descendant::h2[normalize-space(.) = %locator%]/ancestor::div[contains(concat(' ', normalize-space(@class), ' '), ' block ')]
+//div[contains(concat(' ', normalize-space(@class), ' '), concat(' ', %locator%, ' '))] | //div[contains(concat(' ', normalize-space(@class), ' '), ' block ')]/descendant::h2[normalize-space(.) = %locator%]/ancestor::div[contains(concat(' ', normalize-space(@class), ' '), ' block ')]
 XPATH
         , 'region' => <<<XPATH
 .//*[self::div | self::section | self::aside][./@id = %locator%]
index f266669..31e3ad5 100644 (file)
         <FIELD NAME="hashcode" TYPE="char" LENGTH="40" NOTNULL="true" SEQUENCE="false" COMMENT="sha1 hash of serialized qubaids_condition class. Unique for every combination of class name and property."/>
         <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
         <FIELD NAME="questionid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
+        <FIELD NAME="variant" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false"/>
         <FIELD NAME="subqid" TYPE="char" LENGTH="100" NOTNULL="true" SEQUENCE="false"/>
         <FIELD NAME="aid" TYPE="char" LENGTH="100" NOTNULL="false" SEQUENCE="false"/>
         <FIELD NAME="response" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
index 973d4af..8e1043d 100644 (file)
@@ -2982,7 +2982,13 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint(true, 2014012400.00);
     }
 
-    if ($oldversion < 2014020500.00) {
+    if ($oldversion < 2014021300.01) {
+        // Delete any cached stats to force recalculation later, then we can be sure that cached records will have the correct
+        // field.
+        $DB->delete_records('question_response_analysis');
+        $DB->delete_records('question_statistics');
+        $DB->delete_records('quiz_statistics');
+
         // Define field variant to be added to question_statistics.
         $table = new xmldb_table('question_statistics');
         $field = new xmldb_field('variant', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'subquestion');
@@ -2993,7 +2999,22 @@ function xmldb_main_upgrade($oldversion) {
         }
 
         // Main savepoint reached.
-        upgrade_main_savepoint(true, 2014020500.00);
+        upgrade_main_savepoint(true, 2014021300.01);
+    }
+
+    if ($oldversion < 2014021300.02) {
+
+        // Define field variant to be added to question_response_analysis.
+        $table = new xmldb_table('question_response_analysis');
+        $field = new xmldb_field('variant', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'questionid');
+
+        // Conditionally launch add field variant.
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+        }
+
+        // Main savepoint reached.
+        upgrade_main_savepoint(true, 2014021300.02);
     }
 
     return true;
index a24e8ee..8090bd6 100644 (file)
@@ -4266,3 +4266,17 @@ function can_use_html_editor() {
     debugging('can_use_html_editor has been deprecated please update your code to assume it returns true.', DEBUG_DEVELOPER);
     return true;
 }
+
+/**
+ * Returns whether ajax is enabled/allowed or not.
+ * This function is deprecated and always returns true.
+ *
+ * @param array $unused - not used any more.
+ * @return bool
+ * @deprecated since 2.7 MDL-33099 - please do not use this function any more.
+ * @todo MDL-44088 This will be removed in Moodle 2.9.
+ */
+function ajaxenabled(array $browsers = null) {
+    debugging('ajaxenabled() is deprecated - please update your code to assume it returns true.', DEBUG_DEVELOPER);
+    return true;
+}
index 799e53d..25f456b 100644 (file)
@@ -629,10 +629,16 @@ function get_docs_url($path = null) {
         // that will ensure people end up at the latest version of the docs.
         $branch = '.';
     }
-    if (!empty($CFG->docroot)) {
-        return $CFG->docroot . '/' . $branch . '/' . current_language() . '/' . $path;
+    if (empty($CFG->doclang)) {
+        $lang = current_language();
     } else {
-        return 'http://docs.moodle.org/'. $branch . '/' . current_language() . '/' . $path;
+        $lang = $CFG->doclang;
+    }
+    $end = '/' . $branch . '/' . $lang . '/' . $path;
+    if (empty($CFG->docroot)) {
+        return 'http://docs.moodle.org'. $end;
+    } else {
+        return $CFG->docroot . $end ;
     }
 }
 
index 7be6683..d2ec1e3 100644 (file)
@@ -629,19 +629,44 @@ class flexible_table {
     }
 
     /**
-     * Add a row of data to the table. This function takes an array with
-     * column names as keys.
+     * Add a row of data to the table. This function takes an array or object with
+     * column names as keys or property names.
+     *
      * It ignores any elements with keys that are not defined as columns. It
      * puts in empty strings into the row when there is no element in the passed
      * array corresponding to a column in the table. It puts the row elements in
-     * the proper order.
-     * @param $rowwithkeys array
+     * the proper order (internally row table data is stored by in arrays with
+     * a numerical index corresponding to the column number).
+     *
+     * @param object|array $rowwithkeys array keys or object property names are column names,
+     *                                      as defined in call to define_columns.
      * @param string $classname CSS class name to add to this row's tr tag.
      */
     function add_data_keyed($rowwithkeys, $classname = '') {
         $this->add_data($this->get_row_from_keyed($rowwithkeys), $classname);
     }
 
+    /**
+     * Add a number of rows to the table at once. And optionally finish output after they have been added.
+     *
+     * @param (object|array|null)[] $rowstoadd Array of rows to add to table, a null value in array adds a separator row. Or a
+     *                                  object or array is added to table. We expect properties for the row array as would be
+     *                                  passed to add_data_keyed.
+     * @param bool     $finish
+     */
+    public function format_and_add_array_of_rows($rowstoadd, $finish = true) {
+        foreach ($rowstoadd as $row) {
+            if (is_null($row)) {
+                $this->add_separator();
+            } else {
+                $this->add_data_keyed($this->format_row($row));
+            }
+        }
+        if ($finish) {
+            $this->finish_output(!$this->is_downloading());
+        }
+    }
+
     /**
      * Add a seperator line to table.
      */
@@ -715,11 +740,19 @@ class flexible_table {
     }
 
     /**
+     * Call appropriate methods on this table class to perform any processing on values before displaying in table.
+     * Takes raw data from the database and process it into human readable format, perhaps also adding html linking when
+     * displaying table as html, adding a div wrap, etc.
+     *
+     * See for example col_fullname below which will be called for a column whose name is 'fullname'.
      *
-     * @param array $row row of data from db used to make one row of the table.
+     * @param array|object $row row of data from db used to make one row of the table.
      * @return array one row for the table, added using add_data_keyed method.
      */
     function format_row($row) {
+        if (is_array($row)) {
+            $row = (object)$row;
+        }
         $formattedrow = array();
         foreach (array_keys($this->columns) as $column) {
             $colmethodname = 'col_'.$column;
@@ -743,9 +776,13 @@ class flexible_table {
      * then you need to override $this->useridfield to point at the correct
      * field for the user id.
      *
+     * @param object $row the data from the db containing all fields from the
+     *                    users table necessary to construct the full name of the user in
+     *                    current language.
+     * @return string contents of cell in column 'fullname', for this row.
      */
     function col_fullname($row) {
-        global $COURSE, $CFG;
+        global $COURSE;
 
         $name = fullname($row);
         if ($this->download) {
index 033b3d6..dba5b3a 100644 (file)
@@ -67,7 +67,39 @@ class core_tablelib_testcase extends basic_testcase {
         return $data;
     }
 
+    /**
+     * Create a table with properties as passed in params, add data and output html.
+     *
+     * @param string[] $columns
+     * @param string[] $headers
+     * @param bool     $sortable
+     * @param bool     $collapsible
+     * @param string[] $suppress
+     * @param string[] $nosorting
+     * @param (array|object)[] $data
+     * @param int      $pagesize
+     */
     protected function run_table_test($columns, $headers, $sortable, $collapsible, $suppress, $nosorting, $data, $pagesize) {
+        $table = $this->create_and_setup_table($columns, $headers, $sortable, $collapsible, $suppress, $nosorting);
+        $table->pagesize($pagesize, count($data));
+        foreach ($data as $row) {
+            $table->add_data_keyed($row);
+        }
+        $table->finish_output();
+    }
+
+    /**
+     * Create a table with properties as passed in params.
+     *
+     * @param string[] $columns
+     * @param string[] $headers
+     * @param bool $sortable
+     * @param bool $collapsible
+     * @param string[] $suppress
+     * @param string[] $nosorting
+     * @return flexible_table
+     */
+    protected function create_and_setup_table($columns, $headers, $sortable, $collapsible, $suppress, $nosorting) {
         $table = new flexible_table('tablelib_test');
 
         $table->define_columns($columns);
@@ -84,13 +116,8 @@ class core_tablelib_testcase extends basic_testcase {
             $table->no_sorting($column);
         }
 
-
         $table->setup();
-        $table->pagesize($pagesize, count($data));
-        foreach ($data as $row) {
-            $table->add_data_keyed($row);
-        }
-        $table->finish_output();
+        return $table;
     }
 
     public function test_empty_table() {
@@ -113,7 +140,7 @@ class core_tablelib_testcase extends basic_testcase {
         $columns = $this->generate_columns(2);
         $headers = $this->generate_headers(2);
 
-        // Search for pagination controls containing 1.*2</a>.*Next</a>
+        // Search for pagination controls containing '1.*2</a>.*Next</a>'.
         $this->expectOutputRegex('/1.*2<\/a>.*' . get_string('next') . '<\/a>/');
 
         $this->run_table_test(
@@ -134,7 +161,7 @@ class core_tablelib_testcase extends basic_testcase {
         $columns = $this->generate_columns(2);
         $headers = $this->generate_headers(2);
 
-        // Search for 'hide' links in the column headers
+        // Search for 'hide' links in the column headers.
         $this->expectOutputRegex('/' . get_string('hide') . '/');
 
         $this->run_table_test(
@@ -179,7 +206,7 @@ class core_tablelib_testcase extends basic_testcase {
         $columns = $this->generate_columns(2);
         $headers = $this->generate_headers(2);
 
-        // Search for pagination controls containing 1.*2</a>.*Next</a>
+        // Search for pagination controls containing '1.*2</a>.*Next</a>'.
         $this->expectOutputRegex('/' . get_string('sortby') . '/');
 
         $this->run_table_test(
index 780ee74..f00b412 100644 (file)
@@ -17,6 +17,7 @@ DEPRECATIONS:
 * The constants FRONTPAGECOURSELIST, FRONTPAGETOPICONLY & FRONTPAGECOURSELIMIT have been removed.
 * Various cm_info methods have been deprecated in favour of their read-only properties (get_url(), get_content(), get_extra_classes(),
   get_on_click(), get_custom_data(), get_after_link, get_after_edit_icons)
+* The ajaxenabled function has been deprecated and always returns true. All code should be fully functional in Javascript.
 
 YUI:
   * The lightbox attribute for moodle-core-notification-dialogue has been
index 9a609a5..af66f37 100644 (file)
Binary files a/lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop-debug.js and b/lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop-debug.js differ
index 54e334f..991fbbb 100644 (file)
Binary files a/lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop-min.js and b/lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop-min.js differ
index 9a609a5..af66f37 100644 (file)
Binary files a/lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop.js and b/lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop.js differ
index 10c9edf..1920c8e 100644 (file)
Binary files a/lib/yui/build/moodle-core-notification-ajaxexception/moodle-core-notification-ajaxexception-debug.js and b/lib/yui/build/moodle-core-notification-ajaxexception/moodle-core-notification-ajaxexception-debug.js differ
index 21c6f27..d8e1c4c 100644 (file)
Binary files a/lib/yui/build/moodle-core-notification-ajaxexception/moodle-core-notification-ajaxexception-min.js and b/lib/yui/build/moodle-core-notification-ajaxexception/moodle-core-notification-ajaxexception-min.js differ
index 10c9edf..1920c8e 100644 (file)
Binary files a/lib/yui/build/moodle-core-notification-ajaxexception/moodle-core-notification-ajaxexception.js and b/lib/yui/build/moodle-core-notification-ajaxexception/moodle-core-notification-ajaxexception.js differ
index 8b3d536..621569f 100644 (file)
Binary files a/lib/yui/build/moodle-core-notification-alert/moodle-core-notification-alert-debug.js and b/lib/yui/build/moodle-core-notification-alert/moodle-core-notification-alert-debug.js differ
index c831e54..58ad0e0 100644 (file)
Binary files a/lib/yui/build/moodle-core-notification-alert/moodle-core-notification-alert-min.js and b/lib/yui/build/moodle-core-notification-alert/moodle-core-notification-alert-min.js differ
index 8b3d536..621569f 100644 (file)
Binary files a/lib/yui/build/moodle-core-notification-alert/moodle-core-notification-alert.js and b/lib/yui/build/moodle-core-notification-alert/moodle-core-notification-alert.js differ
index 3c6c547..5442d9c 100644 (file)
Binary files a/lib/yui/build/moodle-core-notification-confirm/moodle-core-notification-confirm-debug.js and b/lib/yui/build/moodle-core-notification-confirm/moodle-core-notification-confirm-debug.js differ
index b3ee827..2630f7b 100644 (file)
Binary files a/lib/yui/build/moodle-core-notification-confirm/moodle-core-notification-confirm-min.js and b/lib/yui/build/moodle-core-notification-confirm/moodle-core-notification-confirm-min.js differ
index 3c6c547..5442d9c 100644 (file)
Binary files a/lib/yui/build/moodle-core-notification-confirm/moodle-core-notification-confirm.js and b/lib/yui/build/moodle-core-notification-confirm/moodle-core-notification-confirm.js differ
index 2e4bc5d..72f62e6 100644 (file)
Binary files a/lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-debug.js and b/lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-debug.js differ
index 313aa1c..da31e22 100644 (file)
Binary files a/lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-min.js and b/lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-min.js differ
index 27a544a..3bc5dd3 100644 (file)
Binary files a/lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue.js and b/lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue.js differ
index c4687f0..2aba2c7 100644 (file)
Binary files a/lib/yui/build/moodle-core-notification-exception/moodle-core-notification-exception-debug.js and b/lib/yui/build/moodle-core-notification-exception/moodle-core-notification-exception-debug.js differ
index b1177b1..b7bed86 100644 (file)
Binary files a/lib/yui/build/moodle-core-notification-exception/moodle-core-notification-exception-min.js and b/lib/yui/build/moodle-core-notification-exception/moodle-core-notification-exception-min.js differ
index c4687f0..2aba2c7 100644 (file)
Binary files a/lib/yui/build/moodle-core-notification-exception/moodle-core-notification-exception.js and b/lib/yui/build/moodle-core-notification-exception/moodle-core-notification-exception.js differ
index 03408fe..74972f7 100644 (file)
Binary files a/lib/yui/build/moodle-core-tooltip/moodle-core-tooltip-debug.js and b/lib/yui/build/moodle-core-tooltip/moodle-core-tooltip-debug.js differ
index c31276b..7697ff3 100644 (file)
Binary files a/lib/yui/build/moodle-core-tooltip/moodle-core-tooltip-min.js and b/lib/yui/build/moodle-core-tooltip/moodle-core-tooltip-min.js differ
index 03408fe..74972f7 100644 (file)
Binary files a/lib/yui/build/moodle-core-tooltip/moodle-core-tooltip.js and b/lib/yui/build/moodle-core-tooltip/moodle-core-tooltip.js differ
index a77fe23..00a8e9f 100644 (file)
@@ -536,6 +536,15 @@ Y.extend(DRAGDROP, Y.Base, {
         // Simulate the full sequence.
         this.drag_start(dragevent);
         this.global_drop_over(dropevent);
+
+        if (droptarget.hasClass(this.parentnodeclass) && droptarget.contains(dragcontainer)) {
+            // The global_drop_over function does not handle the case where an item was moved up, without the
+            // 'goingup' variable being set, as is the case wih keyboard drag/drop. We must detect this case and
+            // apply it after the drop_over, but before the drop_hit event in order for it to be moved to the
+            // correct location.
+            droptarget.prepend(dragcontainer);
+        }
+
         this.global_drop_hit(dropevent);
     },
 
index bd7cc1d..4b6d8cf 100644 (file)
@@ -9,7 +9,8 @@
     "moodle-core-notification-dialogue": {
       "jsfiles": [
         "shared.js",
-        "dialogue.js"
+        "dialogue.js",
+        "info.js"
       ]
     },
     "moodle-core-notification-alert": {
index 19b4441..f364995 100644 (file)
@@ -22,7 +22,7 @@ AJAXEXCEPTION = function(config) {
     config.closeButton = true;
     AJAXEXCEPTION.superclass.constructor.apply(this, [config]);
 };
-Y.extend(AJAXEXCEPTION, M.core.dialogue, {
+Y.extend(AJAXEXCEPTION, M.core.notification.info, {
     _keypress : null,
     initializer : function(config) {
         var content,
index b7a0edc..e80096a 100644 (file)
@@ -20,7 +20,7 @@ ALERT = function(config) {
     config.closeButton = false;
     ALERT.superclass.constructor.apply(this, [config]);
 };
-Y.extend(ALERT, M.core.dialogue, {
+Y.extend(ALERT, M.core.notification.info, {
     closeEvents: [],
     initializer : function() {
         this.publish('complete');
index ec6cf76..9b51d50 100644 (file)
@@ -19,7 +19,7 @@ var CONFIRM_NAME = 'Moodle confirmation dialogue',
 CONFIRM = function(config) {
     CONFIRM.superclass.constructor.apply(this, [config]);
 };
-Y.extend(CONFIRM, M.core.dialogue, {
+Y.extend(CONFIRM, M.core.notification.info, {
     closeEvents: [],
     initializer : function() {
         this.publish('complete');
index 2f3424a..bc684e4 100644 (file)
@@ -74,7 +74,7 @@ Y.extend(DIALOGUE, Y.Panel, {
      * @method initializer
      * @return void
      */
-    initializer : function(config) {
+    initializer : function() {
         var bb;
 
         if (this.get('render')) {
@@ -82,7 +82,7 @@ Y.extend(DIALOGUE, Y.Panel, {
         }
         this.makeResponsive();
         this.after('visibleChange', this.visibilityChanged, this);
-        if (config.center) {
+        if (this.get('center')) {
             this.centerDialogue();
         }
         this.set('COUNT', COUNT);
@@ -95,10 +95,10 @@ Y.extend(DIALOGUE, Y.Panel, {
         // and allow setting of z-index in theme.
         bb = this.get('boundingBox');
 
-        if (config.extraClasses) {
-            Y.Array.each(config.extraClasses, bb.addClass, bb);
-        }
-        if (config.visible) {
+        // Add any additional classes that were specified.
+        Y.Array.each(this.get('extraClasses'), bb.addClass, bb);
+
+        if (this.get('visible')) {
             this.applyZIndex();
         }
         // Recalculate the zIndex every time the modal is altered.
@@ -107,7 +107,7 @@ Y.extend(DIALOGUE, Y.Panel, {
         // either by centerDialogue or makeResonsive. This is because the show() will trigger
         // a focus on the dialogue, which will scroll the page. If the dialogue has not
         // been positioned it will scroll back to the top of the page.
-        if (config.visible) {
+        if (this.get('visible')) {
             this.show();
             this.keyDelegation();
         }
@@ -309,7 +309,15 @@ Y.extend(DIALOGUE, Y.Panel, {
         return result;
     },
 
-    hide: function() {
+    hide: function(e) {
+        if (e) {
+            // If the event was closed by an escape key event, then we need to check that this
+            // dialogue is currently focused to prevent closing all dialogues in the stack.
+            if (e.type === 'key' && e.keyCode === 27 && !this.get('focused')) {
+                return;
+            }
+        }
+
         // Unlock scroll if the plugin is present.
         if (this.lockScroll) {
             this.lockScroll.disableScrollLock();
@@ -536,6 +544,17 @@ Y.Base.modifyAttrs(DIALOGUE, {
     render : {
         value : true,
         writeOnce : true
+    },
+
+    /**
+     * Any additional classes to add to the boundingBox.
+     *
+     * @attributes extraClasses
+     * @type Array
+     * @default []
+     */
+    extraClasses: {
+        value: []
     }
 });
 
index ebd83f6..618800a 100644 (file)
@@ -22,7 +22,7 @@ EXCEPTION = function(config) {
     config.closeButton = true;
     EXCEPTION.superclass.constructor.apply(this, [config]);
 };
-Y.extend(EXCEPTION, M.core.dialogue, {
+Y.extend(EXCEPTION, M.core.notification.info, {
     _hideTimeout : null,
     _keypress : null,
     initializer : function(config) {
diff --git a/lib/yui/src/notification/js/info.js b/lib/yui/src/notification/js/info.js
new file mode 100644 (file)
index 0000000..01c973b
--- /dev/null
@@ -0,0 +1,56 @@
+/**
+ * A dialogue type designed to display informative messages to users.
+ *
+ * @module moodle-core-notification
+ */
+
+/**
+ * Extends core Dialogue to provide a type of dialogue which can be used
+ * for informative message which are modal, and centered.
+ *
+ * @param {Object} config Object literal specifying the dialogue configuration properties.
+ * @constructor
+ * @class M.core.notification.info
+ * @extends M.core.dialogue
+ */
+var INFO = function() {
+    INFO.superclass.constructor.apply(this, arguments);
+};
+
+Y.extend(INFO, M.core.dialogue, {
+}, {
+    NAME: 'Moodle information dialogue',
+    CSS_PREFIX: DIALOGUE_PREFIX
+});
+
+Y.Base.modifyAttrs(INFO, {
+    /**
+     * Boolean indicating whether or not the Widget is visible.
+     *
+     * We override this from the default M.core.dialogue attribute value.
+     *
+     * @attribute visible
+     * @default true
+     * @type Boolean
+     */
+    visible: {
+        value: true
+    },
+
+   /**
+    * Whether the widget should be modal or not.
+    *
+    * We override this to change the default from false to true for a subset of dialogues.
+    *
+    * @attribute modal
+    * @type Boolean
+    * @default true
+    */
+    modal: {
+        validator: Y.Lang.isBoolean,
+        value: true
+    }
+});
+
+M.core.notification = M.core.notification || {};
+M.core.notification.info = INFO;
index 1812cb4..f89bbf5 100644 (file)
@@ -422,7 +422,7 @@ Y.extend(TOOLTIP, M.core.dialogue, {
 
     close_panel: function(e) {
         // Hide the panel first.
-        this.hide();
+        this.hide(e);
 
         // Cancel the listeners that we added in display_panel.
         this.cancel_events();
index 1db7168..52eb29c 100644 (file)
@@ -7,7 +7,7 @@ http://yuilibrary.com/license/
 
 if (typeof __coverage__ === 'undefined') { __coverage__ = {}; }
 if (!__coverage__['build/widget-modality/widget-modality.js']) {
-   __coverage__['build/widget-modality/widget-modality.js'] = {"path":"build/widget-modality/widget-modality.js","s":{"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":0,"94":0,"95":0,"96":0,"97":0,"98":0,"99":0,"100":0,"101":0,"102":0,"103":0,"104":0,"105":0,"106":0,"107":0,"108":0,"109":0,"110":0,"111":0,"112":0,"113":0,"114":0,"115":0,"116":0,"117":0,"118":0,"119":0},"b":{"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0,0,0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0,0],"21":[0,0],"22":[0,0,0],"23":[0,0],"24":[0,0,0],"25":[0,0],"26":[0,0,0],"27":[0,0],"28":[0,0],"29":[0,0],"30":[0,0],"31":[0,0],"32":[0,0,0,0],"33":[0,0],"34":[0,0],"35":[0,0],"36":[0,0]},"f":{"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0},"fnMap":{"1":{"name":"(anonymous_1)","line":1,"loc":{"start":{"line":1,"column":27},"end":{"line":1,"column":46}}},"2":{"name":"(anonymous_2)","line":25,"loc":{"start":{"line":25,"column":24},"end":{"line":25,"column":34}}},"3":{"name":"WidgetModal","line":57,"loc":{"start":{"line":57,"column":4},"end":{"line":57,"column":33}}},"4":{"name":"(anonymous_4)","line":110,"loc":{"start":{"line":110,"column":25},"end":{"line":110,"column":36}}},"5":{"name":"(anonymous_5)","line":141,"loc":{"start":{"line":141,"column":28},"end":{"line":141,"column":39}}},"6":{"name":"(anonymous_6)","line":184,"loc":{"start":{"line":184,"column":21},"end":{"line":184,"column":33}}},"7":{"name":"(anonymous_7)","line":190,"loc":{"start":{"line":190,"column":20},"end":{"line":190,"column":32}}},"8":{"name":"(anonymous_8)","line":209,"loc":{"start":{"line":209,"column":25},"end":{"line":209,"column":37}}},"9":{"name":"(anonymous_9)","line":234,"loc":{"start":{"line":234,"column":23},"end":{"line":234,"column":35}}},"10":{"name":"(anonymous_10)","line":262,"loc":{"start":{"line":262,"column":23},"end":{"line":262,"column":35}}},"11":{"name":"(anonymous_11)","line":275,"loc":{"start":{"line":275,"column":17},"end":{"line":275,"column":30}}},"12":{"name":"(anonymous_12)","line":288,"loc":{"start":{"line":288,"column":16},"end":{"line":288,"column":28}}},"13":{"name":"(anonymous_13)","line":299,"loc":{"start":{"line":299,"column":23},"end":{"line":299,"column":35}}},"14":{"name":"(anonymous_14)","line":310,"loc":{"start":{"line":310,"column":33},"end":{"line":310,"column":52}}},"15":{"name":"(anonymous_15)","line":318,"loc":{"start":{"line":318,"column":36},"end":{"line":318,"column":51}}},"16":{"name":"(anonymous_16)","line":376,"loc":{"start":{"line":376,"column":32},"end":{"line":376,"column":50}}},"17":{"name":"(anonymous_17)","line":391,"loc":{"start":{"line":391,"column":32},"end":{"line":391,"column":44}}},"18":{"name":"(anonymous_18)","line":435,"loc":{"start":{"line":435,"column":64},"end":{"line":435,"column":75}}},"19":{"name":"(anonymous_19)","line":448,"loc":{"start":{"line":448,"column":32},"end":{"line":448,"column":44}}},"20":{"name":"(anonymous_20)","line":449,"loc":{"start":{"line":449,"column":41},"end":{"line":449,"column":52}}},"21":{"name":"(anonymous_21)","line":461,"loc":{"start":{"line":461,"column":39},"end":{"line":461,"column":52}}},"22":{"name":"(anonymous_22)","line":472,"loc":{"start":{"line":472,"column":38},"end":{"line":472,"column":51}}},"23":{"name":"(anonymous_23)","line":484,"loc":{"start":{"line":484,"column":18},"end":{"line":484,"column":29}}},"24":{"name":"(anonymous_24)","line":496,"loc":{"start":{"line":496,"column":25},"end":{"line":496,"column":44}}},"25":{"name":"(anonymous_25)","line":531,"loc":{"start":{"line":531,"column":21},"end":{"line":531,"column":34}}},"26":{"name":"(anonymous_26)","line":552,"loc":{"start":{"line":552,"column":30},"end":{"line":552,"column":42}}}},"statementMap":{"1":{"start":{"line":1,"column":0},"end":{"line":565,"column":89}},"2":{"start":{"line":9,"column":0},"end":{"line":48,"column":9}},"3":{"start":{"line":29,"column":8},"end":{"line":31,"column":21}},"4":{"start":{"line":33,"column":8},"end":{"line":45,"column":9}},"5":{"start":{"line":34,"column":12},"end":{"line":34,"column":42}},"6":{"start":{"line":35,"column":12},"end":{"line":44,"column":13}},"7":{"start":{"line":36,"column":16},"end":{"line":36,"column":44}},"8":{"start":{"line":37,"column":16},"end":{"line":37,"column":38}},"9":{"start":{"line":38,"column":16},"end":{"line":38,"column":32}},"10":{"start":{"line":39,"column":16},"end":{"line":43,"column":17}},"11":{"start":{"line":40,"column":20},"end":{"line":40,"column":41}},"12":{"start":{"line":41,"column":20},"end":{"line":41,"column":56}},"13":{"start":{"line":42,"column":20},"end":{"line":42,"column":41}},"14":{"start":{"line":47,"column":8},"end":{"line":47,"column":27}},"15":{"start":{"line":57,"column":4},"end":{"line":57,"column":35}},"16":{"start":{"line":59,"column":4},"end":{"line":64,"column":10}},"17":{"start":{"line":74,"column":4},"end":{"line":126,"column":6}},"18":{"start":{"line":111,"column":20},"end":{"line":120,"column":22}},"19":{"start":{"line":129,"column":4},"end":{"line":129,"column":40}},"20":{"start":{"line":141,"column":4},"end":{"line":173,"column":6}},"21":{"start":{"line":143,"column":8},"end":{"line":144,"column":32}},"22":{"start":{"line":146,"column":8},"end":{"line":148,"column":9}},"23":{"start":{"line":147,"column":12},"end":{"line":147,"column":24}},"24":{"start":{"line":150,"column":8},"end":{"line":150,"column":73}},"25":{"start":{"line":152,"column":8},"end":{"line":170,"column":9}},"26":{"start":{"line":153,"column":12},"end":{"line":160,"column":15}},"27":{"start":{"line":162,"column":12},"end":{"line":169,"column":15}},"28":{"start":{"line":172,"column":8},"end":{"line":172,"column":20}},"29":{"start":{"line":179,"column":4},"end":{"line":179,"column":27}},"30":{"start":{"line":182,"column":4},"end":{"line":559,"column":6}},"31":{"start":{"line":185,"column":12},"end":{"line":185,"column":58}},"32":{"start":{"line":186,"column":12},"end":{"line":186,"column":54}},"33":{"start":{"line":187,"column":12},"end":{"line":187,"column":54}},"34":{"start":{"line":192,"column":12},"end":{"line":192,"column":47}},"35":{"start":{"line":211,"column":12},"end":{"line":211,"column":44}},"36":{"start":{"line":219,"column":12},"end":{"line":219,"column":39}},"37":{"start":{"line":220,"column":12},"end":{"line":220,"column":45}},"38":{"start":{"line":236,"column":12},"end":{"line":236,"column":74}},"39":{"start":{"line":237,"column":12},"end":{"line":237,"column":73}},"40":{"start":{"line":238,"column":12},"end":{"line":238,"column":66}},"41":{"start":{"line":245,"column":12},"end":{"line":250,"column":13}},"42":{"start":{"line":249,"column":16},"end":{"line":249,"column":66}},"43":{"start":{"line":266,"column":12},"end":{"line":266,"column":59}},"44":{"start":{"line":277,"column":12},"end":{"line":278,"column":39}},"45":{"start":{"line":280,"column":12},"end":{"line":280,"column":55}},"46":{"start":{"line":281,"column":12},"end":{"line":281,"column":25}},"47":{"start":{"line":290,"column":12},"end":{"line":290,"column":24}},"48":{"start":{"line":301,"column":12},"end":{"line":301,"column":43}},"49":{"start":{"line":311,"column":12},"end":{"line":314,"column":32}},"50":{"start":{"line":316,"column":12},"end":{"line":367,"column":13}},"51":{"start":{"line":318,"column":16},"end":{"line":321,"column":19}},"52":{"start":{"line":319,"column":20},"end":{"line":319,"column":50}},"53":{"start":{"line":320,"column":20},"end":{"line":320,"column":34}},"54":{"start":{"line":324,"column":16},"end":{"line":324,"column":36}},"55":{"start":{"line":326,"column":16},"end":{"line":326,"column":43}},"56":{"start":{"line":327,"column":16},"end":{"line":327,"column":62}},"57":{"start":{"line":329,"column":16},"end":{"line":333,"column":17}},"58":{"start":{"line":330,"column":20},"end":{"line":330,"column":36}},"59":{"start":{"line":331,"column":20},"end":{"line":331,"column":62}},"60":{"start":{"line":332,"column":20},"end":{"line":332,"column":34}},"61":{"start":{"line":338,"column":16},"end":{"line":338,"column":53}},"62":{"start":{"line":339,"column":16},"end":{"line":342,"column":17}},"63":{"start":{"line":341,"column":20},"end":{"line":341,"column":43}},"64":{"start":{"line":344,"column":16},"end":{"line":344,"column":45}},"65":{"start":{"line":345,"column":16},"end":{"line":345,"column":29}},"66":{"start":{"line":347,"column":16},"end":{"line":365,"column":17}},"67":{"start":{"line":348,"column":20},"end":{"line":348,"column":40}},"68":{"start":{"line":349,"column":20},"end":{"line":349,"column":51}},"69":{"start":{"line":351,"column":20},"end":{"line":351,"column":74}},"70":{"start":{"line":353,"column":20},"end":{"line":357,"column":21}},"71":{"start":{"line":355,"column":24},"end":{"line":355,"column":70}},"72":{"start":{"line":356,"column":24},"end":{"line":356,"column":42}},"73":{"start":{"line":361,"column":20},"end":{"line":363,"column":21}},"74":{"start":{"line":362,"column":24},"end":{"line":362,"column":40}},"75":{"start":{"line":378,"column":12},"end":{"line":380,"column":13}},"76":{"start":{"line":379,"column":16},"end":{"line":379,"column":68}},"77":{"start":{"line":393,"column":12},"end":{"line":397,"column":13}},"78":{"start":{"line":396,"column":16},"end":{"line":396,"column":23}},"79":{"start":{"line":399,"column":12},"end":{"line":404,"column":26}},"80":{"start":{"line":406,"column":12},"end":{"line":432,"column":13}},"81":{"start":{"line":408,"column":16},"end":{"line":408,"column":23}},"82":{"start":{"line":409,"column":16},"end":{"line":409,"column":41}},"83":{"start":{"line":410,"column":16},"end":{"line":410,"column":44}},"84":{"start":{"line":411,"column":16},"end":{"line":411,"column":47}},"85":{"start":{"line":414,"column":16},"end":{"line":430,"column":17}},"86":{"start":{"line":415,"column":20},"end":{"line":415,"column":55}},"87":{"start":{"line":419,"column":21},"end":{"line":430,"column":17}},"88":{"start":{"line":420,"column":20},"end":{"line":420,"column":59}},"89":{"start":{"line":424,"column":21},"end":{"line":430,"column":17}},"90":{"start":{"line":425,"column":20},"end":{"line":425,"column":70}},"91":{"start":{"line":429,"column":20},"end":{"line":429,"column":103}},"92":{"start":{"line":434,"column":12},"end":{"line":438,"column":13}},"93":{"start":{"line":435,"column":16},"end":{"line":437,"column":27}},"94":{"start":{"line":436,"column":20},"end":{"line":436,"column":73}},"95":{"start":{"line":440,"column":12},"end":{"line":440,"column":45}},"96":{"start":{"line":449,"column":12},"end":{"line":451,"column":15}},"97":{"start":{"line":450,"column":16},"end":{"line":450,"column":27}},"98":{"start":{"line":452,"column":12},"end":{"line":452,"column":40}},"99":{"start":{"line":463,"column":12},"end":{"line":463,"column":50}},"100":{"start":{"line":474,"column":12},"end":{"line":474,"column":49}},"101":{"start":{"line":485,"column":12},"end":{"line":486,"column":49}},"102":{"start":{"line":487,"column":12},"end":{"line":487,"column":26}},"103":{"start":{"line":498,"column":12},"end":{"line":501,"column":29}},"104":{"start":{"line":504,"column":12},"end":{"line":520,"column":13}},"105":{"start":{"line":506,"column":16},"end":{"line":506,"column":34}},"106":{"start":{"line":507,"column":16},"end":{"line":507,"column":36}},"107":{"start":{"line":511,"column":17},"end":{"line":520,"column":13}},"108":{"start":{"line":514,"column":16},"end":{"line":514,"column":34}},"109":{"start":{"line":515,"column":16},"end":{"line":515,"column":36}},"110":{"start":{"line":516,"column":16},"end":{"line":516,"column":48}},"111":{"start":{"line":517,"column":16},"end":{"line":517,"column":65}},"112":{"start":{"line":518,"column":16},"end":{"line":518,"column":70}},"113":{"start":{"line":519,"column":16},"end":{"line":519,"column":36}},"114":{"start":{"line":532,"column":12},"end":{"line":537,"column":47}},"115":{"start":{"line":539,"column":12},"end":{"line":544,"column":15}},"116":{"start":{"line":553,"column":12},"end":{"line":553,"column":41}},"117":{"start":{"line":555,"column":12},"end":{"line":557,"column":13}},"118":{"start":{"line":556,"column":16},"end":{"line":556,"column":45}},"119":{"start":{"line":561,"column":4},"end":{"line":561,"column":35}}},"branchMap":{"1":{"line":33,"type":"if","locations":[{"start":{"line":33,"column":8},"end":{"line":33,"column":8}},{"start":{"line":33,"column":8},"end":{"line":33,"column":8}}]},"2":{"line":35,"type":"if","locations":[{"start":{"line":35,"column":12},"end":{"line":35,"column":12}},{"start":{"line":35,"column":12},"end":{"line":35,"column":12}}]},"3":{"line":35,"type":"binary-expr","locations":[{"start":{"line":35,"column":16},"end":{"line":35,"column":18}},{"start":{"line":35,"column":22},"end":{"line":35,"column":30}}]},"4":{"line":39,"type":"if","locations":[{"start":{"line":39,"column":16},"end":{"line":39,"column":16}},{"start":{"line":39,"column":16},"end":{"line":39,"column":16}}]},"5":{"line":39,"type":"binary-expr","locations":[{"start":{"line":39,"column":20},"end":{"line":39,"column":24}},{"start":{"line":39,"column":28},"end":{"line":39,"column":44}},{"start":{"line":39,"column":48},"end":{"line":39,"column":64}}]},"6":{"line":146,"type":"if","locations":[{"start":{"line":146,"column":8},"end":{"line":146,"column":8}},{"start":{"line":146,"column":8},"end":{"line":146,"column":8}}]},"7":{"line":152,"type":"if","locations":[{"start":{"line":152,"column":8},"end":{"line":152,"column":8}},{"start":{"line":152,"column":8},"end":{"line":152,"column":8}}]},"8":{"line":245,"type":"if","locations":[{"start":{"line":245,"column":12},"end":{"line":245,"column":12}},{"start":{"line":245,"column":12},"end":{"line":245,"column":12}}]},"9":{"line":245,"type":"binary-expr","locations":[{"start":{"line":245,"column":16},"end":{"line":245,"column":33}},{"start":{"line":246,"column":21},"end":{"line":246,"column":29}},{"start":{"line":246,"column":33},"end":{"line":246,"column":45}},{"start":{"line":247,"column":21},"end":{"line":247,"column":33}},{"start":{"line":247,"column":37},"end":{"line":247,"column":53}}]},"10":{"line":280,"type":"cond-expr","locations":[{"start":{"line":280,"column":44},"end":{"line":280,"column":49}},{"start":{"line":280,"column":52},"end":{"line":280,"column":53}}]},"11":{"line":316,"type":"if","locations":[{"start":{"line":316,"column":12},"end":{"line":316,"column":12}},{"start":{"line":316,"column":12},"end":{"line":316,"column":12}}]},"12":{"line":329,"type":"if","locations":[{"start":{"line":329,"column":16},"end":{"line":329,"column":16}},{"start":{"line":329,"column":16},"end":{"line":329,"column":16}}]},"13":{"line":339,"type":"if","locations":[{"start":{"line":339,"column":16},"end":{"line":339,"column":16}},{"start":{"line":339,"column":16},"end":{"line":339,"column":16}}]},"14":{"line":347,"type":"if","locations":[{"start":{"line":347,"column":16},"end":{"line":347,"column":16}},{"start":{"line":347,"column":16},"end":{"line":347,"column":16}}]},"15":{"line":353,"type":"if","locations":[{"start":{"line":353,"column":20},"end":{"line":353,"column":20}},{"start":{"line":353,"column":20},"end":{"line":353,"column":20}}]},"16":{"line":361,"type":"if","locations":[{"start":{"line":361,"column":20},"end":{"line":361,"column":20}},{"start":{"line":361,"column":20},"end":{"line":361,"column":20}}]},"17":{"line":378,"type":"if","locations":[{"start":{"line":378,"column":12},"end":{"line":378,"column":12}},{"start":{"line":378,"column":12},"end":{"line":378,"column":12}}]},"18":{"line":379,"type":"binary-expr","locations":[{"start":{"line":379,"column":55},"end":{"line":379,"column":61}},{"start":{"line":379,"column":65},"end":{"line":379,"column":66}}]},"19":{"line":393,"type":"if","locations":[{"start":{"line":393,"column":12},"end":{"line":393,"column":12}},{"start":{"line":393,"column":12},"end":{"line":393,"column":12}}]},"20":{"line":393,"type":"binary-expr","locations":[{"start":{"line":393,"column":16},"end":{"line":393,"column":36}},{"start":{"line":393,"column":40},"end":{"line":393,"column":69}}]},"21":{"line":414,"type":"if","locations":[{"start":{"line":414,"column":16},"end":{"line":414,"column":16}},{"start":{"line":414,"column":16},"end":{"line":414,"column":16}}]},"22":{"line":414,"type":"binary-expr","locations":[{"start":{"line":414,"column":20},"end":{"line":414,"column":27}},{"start":{"line":414,"column":31},"end":{"line":414,"column":41}},{"start":{"line":414,"column":45},"end":{"line":414,"column":49}}]},"23":{"line":419,"type":"if","locations":[{"start":{"line":419,"column":21},"end":{"line":419,"column":21}},{"start":{"line":419,"column":21},"end":{"line":419,"column":21}}]},"24":{"line":419,"type":"binary-expr","locations":[{"start":{"line":419,"column":25},"end":{"line":419,"column":31}},{"start":{"line":419,"column":35},"end":{"line":419,"column":45}},{"start":{"line":419,"column":49},"end":{"line":419,"column":53}}]},"25":{"line":424,"type":"if","locations":[{"start":{"line":424,"column":21},"end":{"line":424,"column":21}},{"start":{"line":424,"column":21},"end":{"line":424,"column":21}}]},"26":{"line":424,"type":"binary-expr","locations":[{"start":{"line":424,"column":25},"end":{"line":424,"column":31}},{"start":{"line":424,"column":35},"end":{"line":424,"column":44}},{"start":{"line":424,"column":48},"end":{"line":424,"column":52}}]},"27":{"line":434,"type":"if","locations":[{"start":{"line":434,"column":12},"end":{"line":434,"column":12}},{"start":{"line":434,"column":12},"end":{"line":434,"column":12}}]},"28":{"line":486,"type":"cond-expr","locations":[{"start":{"line":486,"column":36},"end":{"line":486,"column":40}},{"start":{"line":486,"column":43},"end":{"line":486,"column":48}}]},"29":{"line":504,"type":"if","locations":[{"start":{"line":504,"column":12},"end":{"line":504,"column":12}},{"start":{"line":504,"column":12},"end":{"line":504,"column":12}}]},"30":{"line":504,"type":"binary-expr","locations":[{"start":{"line":504,"column":16},"end":{"line":504,"column":28}},{"start":{"line":504,"column":32},"end":{"line":504,"column":42}}]},"31":{"line":511,"type":"if","locations":[{"start":{"line":511,"column":17},"end":{"line":511,"column":17}},{"start":{"line":511,"column":17},"end":{"line":511,"column":17}}]},"32":{"line":511,"type":"binary-expr","locations":[{"start":{"line":511,"column":22},"end":{"line":511,"column":35}},{"start":{"line":511,"column":39},"end":{"line":511,"column":48}},{"start":{"line":511,"column":54},"end":{"line":511,"column":66}},{"start":{"line":511,"column":70},"end":{"line":511,"column":79}}]},"33":{"line":517,"type":"binary-expr","locations":[{"start":{"line":517,"column":27},"end":{"line":517,"column":47}},{"start":{"line":517,"column":51},"end":{"line":517,"column":64}}]},"34":{"line":535,"type":"binary-expr","locations":[{"start":{"line":535,"column":26},"end":{"line":535,"column":45}},{"start":{"line":535,"column":49},"end":{"line":535,"column":66}}]},"35":{"line":536,"type":"binary-expr","locations":[{"start":{"line":536,"column":26},"end":{"line":536,"column":46}},{"start":{"line":536,"column":50},"end":{"line":536,"column":68}}]},"36":{"line":555,"type":"if","locations":[{"start":{"line":555,"column":12},"end":{"line":555,"column":12}},{"start":{"line":555,"column":12},"end":{"line":555,"column":12}}]}},"code":["(function () { YUI.add('widget-modality', function (Y, NAME) {","","/**"," * Provides modality support for Widgets, though an extension"," *"," * @module widget-modality"," */","","var WIDGET       = 'widget',","    RENDER_UI    = 'renderUI',","    BIND_UI      = 'bindUI',","    SYNC_UI      = 'syncUI',","    BOUNDING_BOX = 'boundingBox',","    CONTENT_BOX  = 'contentBox',","    VISIBLE      = 'visible',","    Z_INDEX      = 'zIndex',","    CHANGE       = 'Change',","    isBoolean    = Y.Lang.isBoolean,","    getCN        = Y.ClassNameManager.getClassName,","    MaskShow     = \"maskShow\",","    MaskHide     = \"maskHide\",","    ClickOutside = \"clickoutside\",","    FocusOutside = \"focusoutside\",","","    supportsPosFixed = (function(){","","        /*! IS_POSITION_FIXED_SUPPORTED - Juriy Zaytsev (kangax) - http://yura.thinkweb2.com/cft/ */","","        var doc         = Y.config.doc,","            isSupported = null,","            el, root;","","        if (doc.createElement) {","            el = doc.createElement('div');","            if (el && el.style) {","                el.style.position = 'fixed';","                el.style.top = '10px';","                root = doc.body;","                if (root && root.appendChild && root.removeChild) {","                    root.appendChild(el);","                    isSupported = (el.offsetTop === 10);","                    root.removeChild(el);","                }","            }","        }","","        return isSupported;","    }());","","    /**","     * Widget extension, which can be used to add modality support to the base Widget class,","     * through the Base.create method.","     *","     * @class WidgetModality","     * @param {Object} config User configuration object","     */","    function WidgetModal(config) {}","","    var MODAL           = 'modal',","        MASK            = 'mask',","        MODAL_CLASSES   = {","            modal   : getCN(WIDGET, MODAL),","            mask    : getCN(WIDGET, MASK)","        };","","    /**","    * Static property used to define the default attribute","    * configuration introduced by WidgetModality.","    *","    * @property ATTRS","    * @static","    * @type Object","    */","    WidgetModal.ATTRS = {","            /**","             * @attribute maskNode","             * @type Y.Node","             *","             * @description Returns a Y.Node instance of the node being used as the mask.","             */","            maskNode : {","                getter      : '_getMaskNode',","                readOnly    : true","            },","","","            /**","             * @attribute modal","             * @type boolean","             *","             * @description Whether the widget should be modal or not.","             */","            modal: {","                value:false,","                validator: isBoolean","            },","","            /**","             * @attribute focusOn","             * @type array","             *","             * @description An array of objects corresponding to the nodes and events that will trigger a re-focus back on the widget.","             * The implementer can supply an array of objects, with each object having the following properties:","             * <p>eventName: (string, required): The eventName to listen to.</p>","             * <p>node: (Y.Node, optional): The Y.Node that will fire the event (defaults to the boundingBox of the widget)</p>","             * <p>By default, this attribute consists of two objects which will cause the widget to re-focus if anything","             * outside the widget is clicked on or focussed upon.</p>","             */","            focusOn: {","                valueFn: function() {","                    return [","                        {","                            // node: this.get(BOUNDING_BOX),","                            eventName: ClickOutside","                        },","                        {","                            //node: this.get(BOUNDING_BOX),","                            eventName: FocusOutside","                        }","                    ];","                },","","                validator: Y.Lang.isArray","            }","","    };","","","    WidgetModal.CLASSES = MODAL_CLASSES;","","","    /**","     * Returns the mask if it exists on the page - otherwise creates a mask. There's only","     * one mask on a page at a given time.","     * <p>","     * This method in invoked internally by the getter of the maskNode ATTR.","     * </p>","     * @method _GET_MASK","     * @static","     */","    WidgetModal._GET_MASK = function() {","","        var mask = Y.one('.' + MODAL_CLASSES.mask),","            win  = Y.one('win');","","        if (mask) {","            return mask;","        }","","        mask = Y.Node.create('<div></div>').addClass(MODAL_CLASSES.mask);","","        if (supportsPosFixed) {","            mask.setStyles({","                position: 'fixed',","                width   : '100%',","                height  : '100%',","                top     : '0',","                left    : '0',","                display : 'block'","            });","        } else {","            mask.setStyles({","                position: 'absolute',","                width   : win.get('winWidth') +'px',","                height  : win.get('winHeight') + 'px',","                top     : '0',","                left    : '0',","                display : 'block'","            });","        }","","        return mask;","    };","","    /**","     * A stack of Y.Widget objects representing the current hierarchy of modal widgets presently displayed on the screen","     * @property STACK","     */","    WidgetModal.STACK = [];","","","    WidgetModal.prototype = {","","        initializer: function () {","            Y.after(this._renderUIModal, this, RENDER_UI);","            Y.after(this._syncUIModal, this, SYNC_UI);","            Y.after(this._bindUIModal, this, BIND_UI);","        },","","        destructor: function () {","            // Hack to remove this thing from the STACK.","            this._uiSetHostVisibleModal(false);","        },","","        // *** Instance Members *** //","","        _uiHandlesModal: null,","","","        /**","         * Adds modal class to the bounding box of the widget","         * <p>","         * This method in invoked after renderUI is invoked for the Widget class","         * using YUI's aop infrastructure.","         * </p>","         * @method _renderUIModal","         * @protected","         */","        _renderUIModal : function () {","","            var bb = this.get(BOUNDING_BOX);","                //cb = this.get(CONTENT_BOX);","","            //this makes the content box content appear over the mask","            // cb.setStyles({","            //     position: \"\"","            // });","","            this._repositionMask(this);","            bb.addClass(MODAL_CLASSES.modal);","","        },","","","        /**","         * Hooks up methods to be executed when the widget's visibility or z-index changes","         * <p>","         * This method in invoked after bindUI is invoked for the Widget class","         * using YUI's aop infrastructure.","         * </p>","         * @method _bindUIModal","         * @protected","         */","        _bindUIModal : function () {","","            this.after(VISIBLE+CHANGE, this._afterHostVisibleChangeModal);","            this.after(Z_INDEX+CHANGE, this._afterHostZIndexChangeModal);","            this.after(\"focusOnChange\", this._afterFocusOnChange);","","            // Re-align the mask in the viewport if `position: fixed;` is not","            // supported. iOS < 5 and Android < 3 don't actually support it even","            // though they both pass the feature test; the UA sniff is here to","            // account for that. Ideally this should be replaced with a better","            // feature test.","            if (!supportsPosFixed ||","                    (Y.UA.ios && Y.UA.ios < 5) ||","                    (Y.UA.android && Y.UA.android < 3)) {","","                Y.one('win').on('scroll', this._resyncMask, this);","            }","        },","","        /**","         * Syncs the mask with the widget's current state, namely the visibility and z-index of the widget","         * <p>","         * This method in invoked after syncUI is invoked for the Widget class","         * using YUI's aop infrastructure.","         * </p>","         * @method _syncUIModal","         * @protected","         */","        _syncUIModal : function () {","","            //var host = this.get(HOST);","","            this._uiSetHostVisibleModal(this.get(VISIBLE));","","        },","","        /**","         * Provides mouse and tab focus to the widget's bounding box.","         *","         * @method _focus","         */","        _focus : function (e) {","","            var bb = this.get(BOUNDING_BOX),","            oldTI = bb.get('tabIndex');","","            bb.set('tabIndex', oldTI >= 0 ? oldTI : 0);","            this.focus();","        },","        /**","         * Blurs the widget.","         *","         * @method _blur","         */","        _blur : function () {","","            this.blur();","        },","","        /**","         * Returns the Y.Node instance of the maskNode","         *","         * @method _getMaskNode","         * @return {Node} The Y.Node instance of the mask, as returned from WidgetModal._GET_MASK","         */","        _getMaskNode : function () {","","            return WidgetModal._GET_MASK();","        },","","        /**","         * Performs events attaching/detaching, stack shifting and mask repositioning based on the visibility of the widget","         *","         * @method _uiSetHostVisibleModal","         * @param {boolean} Whether the widget is visible or not","         */","        _uiSetHostVisibleModal : function (visible) {","            var stack    = WidgetModal.STACK,","                maskNode = this.get('maskNode'),","                isModal  = this.get('modal'),","                topModal, index;","","            if (visible) {","","                Y.Array.each(stack, function(modal){","                    modal._detachUIHandlesModal();","                    modal._blur();","                });","","                // push on top of stack","                stack.unshift(this);","","                this._repositionMask(this);","                this._uiSetHostZIndexModal(this.get(Z_INDEX));","","                if (isModal) {","                    maskNode.show();","                    Y.later(1, this, '_attachUIHandlesModal');","                    this._focus();","                }","","","            } else {","","                index = Y.Array.indexOf(stack, this);","                if (index >= 0) {","                    // Remove modal widget from global stack.","                    stack.splice(index, 1);","                }","","                this._detachUIHandlesModal();","                this._blur();","","                if (stack.length) {","                    topModal = stack[0];","                    this._repositionMask(topModal);","                    //topModal._attachUIHandlesModal();","                    topModal._uiSetHostZIndexModal(topModal.get(Z_INDEX));","","                    if (topModal.get('modal')) {","                        //topModal._attachUIHandlesModal();","                        Y.later(1, topModal, '_attachUIHandlesModal');","                        topModal._focus();","                    }","","                } else {","","                    if (maskNode.getStyle('display') === 'block') {","                        maskNode.hide();","                    }","","                }","","            }","        },","","        /**","         * Sets the z-index of the mask node.","         *","         * @method _uiSetHostZIndexModal","         * @param {Number} Z-Index of the widget","         */","        _uiSetHostZIndexModal : function (zIndex) {","","            if (this.get('modal')) {","                this.get('maskNode').setStyle(Z_INDEX, zIndex || 0);","            }","","        },","","        /**","         * Attaches UI Listeners for \"clickoutside\" and \"focusoutside\" on the","         * widget. When these events occur, and the widget is modal, focus is","         * shifted back onto the widget.","         *","         * @method _attachUIHandlesModal","         */","        _attachUIHandlesModal : function () {","","            if (this._uiHandlesModal || WidgetModal.STACK[0] !== this) {","                // Quit early if we have ui handles, or if we not at the top","                // of the global stack.","                return;","            }","","            var bb          = this.get(BOUNDING_BOX),","                maskNode    = this.get('maskNode'),","                focusOn     = this.get('focusOn'),","                focus       = Y.bind(this._focus, this),","                uiHandles   = [],","                i, len, o;","","            for (i = 0, len = focusOn.length; i < len; i++) {","","                o = {};","                o.node = focusOn[i].node;","                o.ev = focusOn[i].eventName;","                o.keyCode = focusOn[i].keyCode;","","                //no keycode or node defined","                if (!o.node && !o.keyCode && o.ev) {","                    uiHandles.push(bb.on(o.ev, focus));","                }","","                //node defined, no keycode (not a keypress)","                else if (o.node && !o.keyCode && o.ev) {","                    uiHandles.push(o.node.on(o.ev, focus));","                }","","                //node defined, keycode defined, event defined (its a key press)","                else if (o.node && o.keyCode && o.ev) {","                    uiHandles.push(o.node.on(o.ev, focus, o.keyCode));","                }","","                else {","                    Y.Log('focusOn ATTR Error: The event with name \"'+o.ev+'\" could not be attached.');","                }","","            }","","            if ( ! supportsPosFixed) {","                uiHandles.push(Y.one('win').on('scroll', Y.bind(function(e){","                    maskNode.setStyle('top', maskNode.get('docScrollY'));","                }, this)));","            }","","            this._uiHandlesModal = uiHandles;","        },","","        /**","         * Detaches all UI Listeners that were set in _attachUIHandlesModal from the widget.","         *","         * @method _detachUIHandlesModal","         */","        _detachUIHandlesModal : function () {","            Y.each(this._uiHandlesModal, function(h){","                h.detach();","            });","            this._uiHandlesModal = null;","        },","","        /**","         * Default function that is called when visibility is changed on the widget.","         *","         * @method _afterHostVisibleChangeModal","         * @param {EventFacade} e The event facade of the change","         */","        _afterHostVisibleChangeModal : function (e) {","","            this._uiSetHostVisibleModal(e.newVal);","        },","","        /**","         * Default function that is called when z-index is changed on the widget.","         *","         * @method _afterHostZIndexChangeModal","         * @param {EventFacade} e The event facade of the change","         */","        _afterHostZIndexChangeModal : function (e) {","","            this._uiSetHostZIndexModal(e.newVal);","        },","","        /**","         * Returns a boolean representing whether the current widget is in a \"nested modality\" state.","         * This is done by checking the number of widgets currently on the stack.","         *","         * @method isNested","         * @public","         */","        isNested: function() {","            var length = WidgetModal.STACK.length,","            retval = (length > 1) ? true : false;","            return retval;","        },","","        /**","         * Repositions the mask in the DOM for nested modality cases.","         *","         * @method _repositionMask","         * @param {Widget} nextElem The Y.Widget instance that will be visible in the stack once the current widget is closed.","         */","        _repositionMask: function(nextElem) {","","            var currentModal = this.get('modal'),","                nextModal    = nextElem.get('modal'),","                maskNode     = this.get('maskNode'),","                bb, bbParent;","","            //if this is modal and host is not modal","            if (currentModal && !nextModal) {","                //leave the mask where it is, since the host is not modal.","                maskNode.remove();","                this.fire(MaskHide);","            }","","            //if the main widget is not modal but the host is modal, or both of them are modal","            else if ((!currentModal && nextModal) || (currentModal && nextModal)) {","","                //then remove the mask off DOM, reposition it, and reinsert it into the DOM","                maskNode.remove();","                this.fire(MaskHide);","                bb = nextElem.get(BOUNDING_BOX);","                bbParent = bb.get('parentNode') || Y.one('body');","                bbParent.insert(maskNode, bbParent.get('firstChild'));","                this.fire(MaskShow);","            }","","        },","","        /**","         * Resyncs the mask in the viewport for browsers that don't support fixed positioning","         *","         * @method _resyncMask","         * @param {Y.Widget} nextElem The Y.Widget instance that will be visible in the stack once the current widget is closed.","         * @private","         */","        _resyncMask: function (e) {","            var o       = e.currentTarget,","                offsetX = o.get('docScrollX'),","                offsetY = o.get('docScrollY'),","                w       = o.get('innerWidth') || o.get('winWidth'),","                h       = o.get('innerHeight') || o.get('winHeight'),","                mask    = this.get('maskNode');","","            mask.setStyles({","                \"top\": offsetY + \"px\",","                \"left\": offsetX + \"px\",","                \"width\": w + 'px',","                \"height\": h + 'px'","            });","        },","","        /**","         * Default function called when focusOn Attribute is changed. Remove existing listeners and create new listeners.","         *","         * @method _afterFocusOnChange","         */","        _afterFocusOnChange : function(e) {","            this._detachUIHandlesModal();","","            if (this.get(VISIBLE)) {","                this._attachUIHandlesModal();","            }","        }","    };","","    Y.WidgetModality = WidgetModal;","","","","}, '3.13.0', {\"requires\": [\"base-build\", \"event-outside\", \"widget\"], \"skinnable\": true});","","}());"]};
+   __coverage__['build/widget-modality/widget-modality.js'] = {"path":"build/widget-modality/widget-modality.js","s":{"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":0,"94":0,"95":0,"96":0,"97":0,"98":0,"99":0,"100":0,"101":0,"102":0,"103":0,"104":0,"105":0,"106":0,"107":0,"108":0,"109":0,"110":0,"111":0,"112":0,"113":0,"114":0,"115":0,"116":0,"117":0,"118":0,"119":0,"120":0},"b":{"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0,0,0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0,0],"21":[0,0],"22":[0,0],"23":[0,0,0],"24":[0,0],"25":[0,0,0],"26":[0,0],"27":[0,0,0],"28":[0,0],"29":[0,0],"30":[0,0],"31":[0,0],"32":[0,0],"33":[0,0,0,0],"34":[0,0],"35":[0,0],"36":[0,0],"37":[0,0]},"f":{"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0},"fnMap":{"1":{"name":"(anonymous_1)","line":1,"loc":{"start":{"line":1,"column":27},"end":{"line":1,"column":46}}},"2":{"name":"(anonymous_2)","line":26,"loc":{"start":{"line":26,"column":24},"end":{"line":26,"column":34}}},"3":{"name":"WidgetModal","line":58,"loc":{"start":{"line":58,"column":4},"end":{"line":58,"column":33}}},"4":{"name":"(anonymous_4)","line":111,"loc":{"start":{"line":111,"column":25},"end":{"line":111,"column":36}}},"5":{"name":"(anonymous_5)","line":142,"loc":{"start":{"line":142,"column":28},"end":{"line":142,"column":39}}},"6":{"name":"(anonymous_6)","line":185,"loc":{"start":{"line":185,"column":21},"end":{"line":185,"column":33}}},"7":{"name":"(anonymous_7)","line":191,"loc":{"start":{"line":191,"column":20},"end":{"line":191,"column":32}}},"8":{"name":"(anonymous_8)","line":210,"loc":{"start":{"line":210,"column":25},"end":{"line":210,"column":37}}},"9":{"name":"(anonymous_9)","line":235,"loc":{"start":{"line":235,"column":23},"end":{"line":235,"column":35}}},"10":{"name":"(anonymous_10)","line":263,"loc":{"start":{"line":263,"column":23},"end":{"line":263,"column":35}}},"11":{"name":"(anonymous_11)","line":276,"loc":{"start":{"line":276,"column":17},"end":{"line":276,"column":30}}},"12":{"name":"(anonymous_12)","line":289,"loc":{"start":{"line":289,"column":16},"end":{"line":289,"column":28}}},"13":{"name":"(anonymous_13)","line":300,"loc":{"start":{"line":300,"column":23},"end":{"line":300,"column":35}}},"14":{"name":"(anonymous_14)","line":311,"loc":{"start":{"line":311,"column":33},"end":{"line":311,"column":52}}},"15":{"name":"(anonymous_15)","line":319,"loc":{"start":{"line":319,"column":36},"end":{"line":319,"column":51}}},"16":{"name":"(anonymous_16)","line":379,"loc":{"start":{"line":379,"column":32},"end":{"line":379,"column":50}}},"17":{"name":"(anonymous_17)","line":394,"loc":{"start":{"line":394,"column":32},"end":{"line":394,"column":44}}},"18":{"name":"(anonymous_18)","line":438,"loc":{"start":{"line":438,"column":64},"end":{"line":438,"column":75}}},"19":{"name":"(anonymous_19)","line":451,"loc":{"start":{"line":451,"column":32},"end":{"line":451,"column":44}}},"20":{"name":"(anonymous_20)","line":452,"loc":{"start":{"line":452,"column":41},"end":{"line":452,"column":52}}},"21":{"name":"(anonymous_21)","line":464,"loc":{"start":{"line":464,"column":39},"end":{"line":464,"column":52}}},"22":{"name":"(anonymous_22)","line":475,"loc":{"start":{"line":475,"column":38},"end":{"line":475,"column":51}}},"23":{"name":"(anonymous_23)","line":487,"loc":{"start":{"line":487,"column":18},"end":{"line":487,"column":29}}},"24":{"name":"(anonymous_24)","line":499,"loc":{"start":{"line":499,"column":25},"end":{"line":499,"column":44}}},"25":{"name":"(anonymous_25)","line":534,"loc":{"start":{"line":534,"column":21},"end":{"line":534,"column":34}}},"26":{"name":"(anonymous_26)","line":555,"loc":{"start":{"line":555,"column":30},"end":{"line":555,"column":42}}}},"statementMap":{"1":{"start":{"line":1,"column":0},"end":{"line":568,"column":89}},"2":{"start":{"line":9,"column":0},"end":{"line":49,"column":9}},"3":{"start":{"line":30,"column":8},"end":{"line":32,"column":21}},"4":{"start":{"line":34,"column":8},"end":{"line":46,"column":9}},"5":{"start":{"line":35,"column":12},"end":{"line":35,"column":42}},"6":{"start":{"line":36,"column":12},"end":{"line":45,"column":13}},"7":{"start":{"line":37,"column":16},"end":{"line":37,"column":44}},"8":{"start":{"line":38,"column":16},"end":{"line":38,"column":38}},"9":{"start":{"line":39,"column":16},"end":{"line":39,"column":32}},"10":{"start":{"line":40,"column":16},"end":{"line":44,"column":17}},"11":{"start":{"line":41,"column":20},"end":{"line":41,"column":41}},"12":{"start":{"line":42,"column":20},"end":{"line":42,"column":56}},"13":{"start":{"line":43,"column":20},"end":{"line":43,"column":41}},"14":{"start":{"line":48,"column":8},"end":{"line":48,"column":27}},"15":{"start":{"line":58,"column":4},"end":{"line":58,"column":35}},"16":{"start":{"line":60,"column":4},"end":{"line":65,"column":10}},"17":{"start":{"line":75,"column":4},"end":{"line":127,"column":6}},"18":{"start":{"line":112,"column":20},"end":{"line":121,"column":22}},"19":{"start":{"line":130,"column":4},"end":{"line":130,"column":40}},"20":{"start":{"line":142,"column":4},"end":{"line":174,"column":6}},"21":{"start":{"line":144,"column":8},"end":{"line":145,"column":32}},"22":{"start":{"line":147,"column":8},"end":{"line":149,"column":9}},"23":{"start":{"line":148,"column":12},"end":{"line":148,"column":24}},"24":{"start":{"line":151,"column":8},"end":{"line":151,"column":73}},"25":{"start":{"line":153,"column":8},"end":{"line":171,"column":9}},"26":{"start":{"line":154,"column":12},"end":{"line":161,"column":15}},"27":{"start":{"line":163,"column":12},"end":{"line":170,"column":15}},"28":{"start":{"line":173,"column":8},"end":{"line":173,"column":20}},"29":{"start":{"line":180,"column":4},"end":{"line":180,"column":27}},"30":{"start":{"line":183,"column":4},"end":{"line":562,"column":6}},"31":{"start":{"line":186,"column":12},"end":{"line":186,"column":58}},"32":{"start":{"line":187,"column":12},"end":{"line":187,"column":54}},"33":{"start":{"line":188,"column":12},"end":{"line":188,"column":54}},"34":{"start":{"line":193,"column":12},"end":{"line":193,"column":47}},"35":{"start":{"line":212,"column":12},"end":{"line":212,"column":44}},"36":{"start":{"line":220,"column":12},"end":{"line":220,"column":39}},"37":{"start":{"line":221,"column":12},"end":{"line":221,"column":45}},"38":{"start":{"line":237,"column":12},"end":{"line":237,"column":74}},"39":{"start":{"line":238,"column":12},"end":{"line":238,"column":73}},"40":{"start":{"line":239,"column":12},"end":{"line":239,"column":66}},"41":{"start":{"line":246,"column":12},"end":{"line":251,"column":13}},"42":{"start":{"line":250,"column":16},"end":{"line":250,"column":66}},"43":{"start":{"line":267,"column":12},"end":{"line":267,"column":59}},"44":{"start":{"line":278,"column":12},"end":{"line":279,"column":39}},"45":{"start":{"line":281,"column":12},"end":{"line":281,"column":55}},"46":{"start":{"line":282,"column":12},"end":{"line":282,"column":25}},"47":{"start":{"line":291,"column":12},"end":{"line":291,"column":24}},"48":{"start":{"line":302,"column":12},"end":{"line":302,"column":43}},"49":{"start":{"line":312,"column":12},"end":{"line":315,"column":32}},"50":{"start":{"line":317,"column":12},"end":{"line":370,"column":13}},"51":{"start":{"line":319,"column":16},"end":{"line":322,"column":19}},"52":{"start":{"line":320,"column":20},"end":{"line":320,"column":50}},"53":{"start":{"line":321,"column":20},"end":{"line":321,"column":34}},"54":{"start":{"line":325,"column":16},"end":{"line":325,"column":36}},"55":{"start":{"line":327,"column":16},"end":{"line":327,"column":43}},"56":{"start":{"line":328,"column":16},"end":{"line":328,"column":62}},"57":{"start":{"line":330,"column":16},"end":{"line":336,"column":17}},"58":{"start":{"line":331,"column":20},"end":{"line":331,"column":36}},"59":{"start":{"line":332,"column":20},"end":{"line":332,"column":62}},"60":{"start":{"line":333,"column":20},"end":{"line":335,"column":21}},"61":{"start":{"line":334,"column":24},"end":{"line":334,"column":38}},"62":{"start":{"line":341,"column":16},"end":{"line":341,"column":53}},"63":{"start":{"line":342,"column":16},"end":{"line":345,"column":17}},"64":{"start":{"line":344,"column":20},"end":{"line":344,"column":43}},"65":{"start":{"line":347,"column":16},"end":{"line":347,"column":45}},"66":{"start":{"line":348,"column":16},"end":{"line":348,"column":29}},"67":{"start":{"line":350,"column":16},"end":{"line":368,"column":17}},"68":{"start":{"line":351,"column":20},"end":{"line":351,"column":40}},"69":{"start":{"line":352,"column":20},"end":{"line":352,"column":51}},"70":{"start":{"line":354,"column":20},"end":{"line":354,"column":74}},"71":{"start":{"line":356,"column":20},"end":{"line":360,"column":21}},"72":{"start":{"line":358,"column":24},"end":{"line":358,"column":70}},"73":{"start":{"line":359,"column":24},"end":{"line":359,"column":42}},"74":{"start":{"line":364,"column":20},"end":{"line":366,"column":21}},"75":{"start":{"line":365,"column":24},"end":{"line":365,"column":40}},"76":{"start":{"line":381,"column":12},"end":{"line":383,"column":13}},"77":{"start":{"line":382,"column":16},"end":{"line":382,"column":68}},"78":{"start":{"line":396,"column":12},"end":{"line":400,"column":13}},"79":{"start":{"line":399,"column":16},"end":{"line":399,"column":23}},"80":{"start":{"line":402,"column":12},"end":{"line":407,"column":26}},"81":{"start":{"line":409,"column":12},"end":{"line":435,"column":13}},"82":{"start":{"line":411,"column":16},"end":{"line":411,"column":23}},"83":{"start":{"line":412,"column":16},"end":{"line":412,"column":41}},"84":{"start":{"line":413,"column":16},"end":{"line":413,"column":44}},"85":{"start":{"line":414,"column":16},"end":{"line":414,"column":47}},"86":{"start":{"line":417,"column":16},"end":{"line":433,"column":17}},"87":{"start":{"line":418,"column":20},"end":{"line":418,"column":55}},"88":{"start":{"line":422,"column":21},"end":{"line":433,"column":17}},"89":{"start":{"line":423,"column":20},"end":{"line":423,"column":59}},"90":{"start":{"line":427,"column":21},"end":{"line":433,"column":17}},"91":{"start":{"line":428,"column":20},"end":{"line":428,"column":70}},"92":{"start":{"line":432,"column":20},"end":{"line":432,"column":103}},"93":{"start":{"line":437,"column":12},"end":{"line":441,"column":13}},"94":{"start":{"line":438,"column":16},"end":{"line":440,"column":27}},"95":{"start":{"line":439,"column":20},"end":{"line":439,"column":73}},"96":{"start":{"line":443,"column":12},"end":{"line":443,"column":45}},"97":{"start":{"line":452,"column":12},"end":{"line":454,"column":15}},"98":{"start":{"line":453,"column":16},"end":{"line":453,"column":27}},"99":{"start":{"line":455,"column":12},"end":{"line":455,"column":40}},"100":{"start":{"line":466,"column":12},"end":{"line":466,"column":50}},"101":{"start":{"line":477,"column":12},"end":{"line":477,"column":49}},"102":{"start":{"line":488,"column":12},"end":{"line":489,"column":49}},"103":{"start":{"line":490,"column":12},"end":{"line":490,"column":26}},"104":{"start":{"line":501,"column":12},"end":{"line":504,"column":29}},"105":{"start":{"line":507,"column":12},"end":{"line":523,"column":13}},"106":{"start":{"line":509,"column":16},"end":{"line":509,"column":34}},"107":{"start":{"line":510,"column":16},"end":{"line":510,"column":36}},"108":{"start":{"line":514,"column":17},"end":{"line":523,"column":13}},"109":{"start":{"line":517,"column":16},"end":{"line":517,"column":34}},"110":{"start":{"line":518,"column":16},"end":{"line":518,"column":36}},"111":{"start":{"line":519,"column":16},"end":{"line":519,"column":48}},"112":{"start":{"line":520,"column":16},"end":{"line":520,"column":65}},"113":{"start":{"line":521,"column":16},"end":{"line":521,"column":70}},"114":{"start":{"line":522,"column":16},"end":{"line":522,"column":36}},"115":{"start":{"line":535,"column":12},"end":{"line":540,"column":47}},"116":{"start":{"line":542,"column":12},"end":{"line":547,"column":15}},"117":{"start":{"line":556,"column":12},"end":{"line":556,"column":41}},"118":{"start":{"line":558,"column":12},"end":{"line":560,"column":13}},"119":{"start":{"line":559,"column":16},"end":{"line":559,"column":45}},"120":{"start":{"line":564,"column":4},"end":{"line":564,"column":35}}},"branchMap":{"1":{"line":34,"type":"if","locations":[{"start":{"line":34,"column":8},"end":{"line":34,"column":8}},{"start":{"line":34,"column":8},"end":{"line":34,"column":8}}]},"2":{"line":36,"type":"if","locations":[{"start":{"line":36,"column":12},"end":{"line":36,"column":12}},{"start":{"line":36,"column":12},"end":{"line":36,"column":12}}]},"3":{"line":36,"type":"binary-expr","locations":[{"start":{"line":36,"column":16},"end":{"line":36,"column":18}},{"start":{"line":36,"column":22},"end":{"line":36,"column":30}}]},"4":{"line":40,"type":"if","locations":[{"start":{"line":40,"column":16},"end":{"line":40,"column":16}},{"start":{"line":40,"column":16},"end":{"line":40,"column":16}}]},"5":{"line":40,"type":"binary-expr","locations":[{"start":{"line":40,"column":20},"end":{"line":40,"column":24}},{"start":{"line":40,"column":28},"end":{"line":40,"column":44}},{"start":{"line":40,"column":48},"end":{"line":40,"column":64}}]},"6":{"line":147,"type":"if","locations":[{"start":{"line":147,"column":8},"end":{"line":147,"column":8}},{"start":{"line":147,"column":8},"end":{"line":147,"column":8}}]},"7":{"line":153,"type":"if","locations":[{"start":{"line":153,"column":8},"end":{"line":153,"column":8}},{"start":{"line":153,"column":8},"end":{"line":153,"column":8}}]},"8":{"line":246,"type":"if","locations":[{"start":{"line":246,"column":12},"end":{"line":246,"column":12}},{"start":{"line":246,"column":12},"end":{"line":246,"column":12}}]},"9":{"line":246,"type":"binary-expr","locations":[{"start":{"line":246,"column":16},"end":{"line":246,"column":33}},{"start":{"line":247,"column":21},"end":{"line":247,"column":29}},{"start":{"line":247,"column":33},"end":{"line":247,"column":45}},{"start":{"line":248,"column":21},"end":{"line":248,"column":33}},{"start":{"line":248,"column":37},"end":{"line":248,"column":53}}]},"10":{"line":281,"type":"cond-expr","locations":[{"start":{"line":281,"column":44},"end":{"line":281,"column":49}},{"start":{"line":281,"column":52},"end":{"line":281,"column":53}}]},"11":{"line":317,"type":"if","locations":[{"start":{"line":317,"column":12},"end":{"line":317,"column":12}},{"start":{"line":317,"column":12},"end":{"line":317,"column":12}}]},"12":{"line":330,"type":"if","locations":[{"start":{"line":330,"column":16},"end":{"line":330,"column":16}},{"start":{"line":330,"column":16},"end":{"line":330,"column":16}}]},"13":{"line":333,"type":"if","locations":[{"start":{"line":333,"column":20},"end":{"line":333,"column":20}},{"start":{"line":333,"column":20},"end":{"line":333,"column":20}}]},"14":{"line":342,"type":"if","locations":[{"start":{"line":342,"column":16},"end":{"line":342,"column":16}},{"start":{"line":342,"column":16},"end":{"line":342,"column":16}}]},"15":{"line":350,"type":"if","locations":[{"start":{"line":350,"column":16},"end":{"line":350,"column":16}},{"start":{"line":350,"column":16},"end":{"line":350,"column":16}}]},"16":{"line":356,"type":"if","locations":[{"start":{"line":356,"column":20},"end":{"line":356,"column":20}},{"start":{"line":356,"column":20},"end":{"line":356,"column":20}}]},"17":{"line":364,"type":"if","locations":[{"start":{"line":364,"column":20},"end":{"line":364,"column":20}},{"start":{"line":364,"column":20},"end":{"line":364,"column":20}}]},"18":{"line":381,"type":"if","locations":[{"start":{"line":381,"column":12},"end":{"line":381,"column":12}},{"start":{"line":381,"column":12},"end":{"line":381,"column":12}}]},"19":{"line":382,"type":"binary-expr","locations":[{"start":{"line":382,"column":55},"end":{"line":382,"column":61}},{"start":{"line":382,"column":65},"end":{"line":382,"column":66}}]},"20":{"line":396,"type":"if","locations":[{"start":{"line":396,"column":12},"end":{"line":396,"column":12}},{"start":{"line":396,"column":12},"end":{"line":396,"column":12}}]},"21":{"line":396,"type":"binary-expr","locations":[{"start":{"line":396,"column":16},"end":{"line":396,"column":36}},{"start":{"line":396,"column":40},"end":{"line":396,"column":69}}]},"22":{"line":417,"type":"if","locations":[{"start":{"line":417,"column":16},"end":{"line":417,"column":16}},{"start":{"line":417,"column":16},"end":{"line":417,"column":16}}]},"23":{"line":417,"type":"binary-expr","locations":[{"start":{"line":417,"column":20},"end":{"line":417,"column":27}},{"start":{"line":417,"column":31},"end":{"line":417,"column":41}},{"start":{"line":417,"column":45},"end":{"line":417,"column":49}}]},"24":{"line":422,"type":"if","locations":[{"start":{"line":422,"column":21},"end":{"line":422,"column":21}},{"start":{"line":422,"column":21},"end":{"line":422,"column":21}}]},"25":{"line":422,"type":"binary-expr","locations":[{"start":{"line":422,"column":25},"end":{"line":422,"column":31}},{"start":{"line":422,"column":35},"end":{"line":422,"column":45}},{"start":{"line":422,"column":49},"end":{"line":422,"column":53}}]},"26":{"line":427,"type":"if","locations":[{"start":{"line":427,"column":21},"end":{"line":427,"column":21}},{"start":{"line":427,"column":21},"end":{"line":427,"column":21}}]},"27":{"line":427,"type":"binary-expr","locations":[{"start":{"line":427,"column":25},"end":{"line":427,"column":31}},{"start":{"line":427,"column":35},"end":{"line":427,"column":44}},{"start":{"line":427,"column":48},"end":{"line":427,"column":52}}]},"28":{"line":437,"type":"if","locations":[{"start":{"line":437,"column":12},"end":{"line":437,"column":12}},{"start":{"line":437,"column":12},"end":{"line":437,"column":12}}]},"29":{"line":489,"type":"cond-expr","locations":[{"start":{"line":489,"column":36},"end":{"line":489,"column":40}},{"start":{"line":489,"column":43},"end":{"line":489,"column":48}}]},"30":{"line":507,"type":"if","locations":[{"start":{"line":507,"column":12},"end":{"line":507,"column":12}},{"start":{"line":507,"column":12},"end":{"line":507,"column":12}}]},"31":{"line":507,"type":"binary-expr","locations":[{"start":{"line":507,"column":16},"end":{"line":507,"column":28}},{"start":{"line":507,"column":32},"end":{"line":507,"column":42}}]},"32":{"line":514,"type":"if","locations":[{"start":{"line":514,"column":17},"end":{"line":514,"column":17}},{"start":{"line":514,"column":17},"end":{"line":514,"column":17}}]},"33":{"line":514,"type":"binary-expr","locations":[{"start":{"line":514,"column":22},"end":{"line":514,"column":35}},{"start":{"line":514,"column":39},"end":{"line":514,"column":48}},{"start":{"line":514,"column":54},"end":{"line":514,"column":66}},{"start":{"line":514,"column":70},"end":{"line":514,"column":79}}]},"34":{"line":520,"type":"binary-expr","locations":[{"start":{"line":520,"column":27},"end":{"line":520,"column":47}},{"start":{"line":520,"column":51},"end":{"line":520,"column":64}}]},"35":{"line":538,"type":"binary-expr","locations":[{"start":{"line":538,"column":26},"end":{"line":538,"column":45}},{"start":{"line":538,"column":49},"end":{"line":538,"column":66}}]},"36":{"line":539,"type":"binary-expr","locations":[{"start":{"line":539,"column":26},"end":{"line":539,"column":46}},{"start":{"line":539,"column":50},"end":{"line":539,"column":68}}]},"37":{"line":558,"type":"if","locations":[{"start":{"line":558,"column":12},"end":{"line":558,"column":12}},{"start":{"line":558,"column":12},"end":{"line":558,"column":12}}]}},"code":["(function () { YUI.add('widget-modality', function (Y, NAME) {","","/**"," * Provides modality support for Widgets, though an extension"," *"," * @module widget-modality"," */","","var WIDGET       = 'widget',","    RENDER_UI    = 'renderUI',","    BIND_UI      = 'bindUI',","    SYNC_UI      = 'syncUI',","    BOUNDING_BOX = 'boundingBox',","    CONTENT_BOX  = 'contentBox',","    RENDERED     = 'rendered',","    VISIBLE      = 'visible',","    Z_INDEX      = 'zIndex',","    CHANGE       = 'Change',","    isBoolean    = Y.Lang.isBoolean,","    getCN        = Y.ClassNameManager.getClassName,","    MaskShow     = \"maskShow\",","    MaskHide     = \"maskHide\",","    ClickOutside = \"clickoutside\",","    FocusOutside = \"focusoutside\",","","    supportsPosFixed = (function(){","","        /*! IS_POSITION_FIXED_SUPPORTED - Juriy Zaytsev (kangax) - http://yura.thinkweb2.com/cft/ */","","        var doc         = Y.config.doc,","            isSupported = null,","            el, root;","","        if (doc.createElement) {","            el = doc.createElement('div');","            if (el && el.style) {","                el.style.position = 'fixed';","                el.style.top = '10px';","                root = doc.body;","                if (root && root.appendChild && root.removeChild) {","                    root.appendChild(el);","                    isSupported = (el.offsetTop === 10);","                    root.removeChild(el);","                }","            }","        }","","        return isSupported;","    }());","","    /**","     * Widget extension, which can be used to add modality support to the base Widget class,","     * through the Base.create method.","     *","     * @class WidgetModality","     * @param {Object} config User configuration object","     */","    function WidgetModal(config) {}","","    var MODAL           = 'modal',","        MASK            = 'mask',","        MODAL_CLASSES   = {","            modal   : getCN(WIDGET, MODAL),","            mask    : getCN(WIDGET, MASK)","        };","","    /**","    * Static property used to define the default attribute","    * configuration introduced by WidgetModality.","    *","    * @property ATTRS","    * @static","    * @type Object","    */","    WidgetModal.ATTRS = {","            /**","             * @attribute maskNode","             * @type Y.Node","             *","             * @description Returns a Y.Node instance of the node being used as the mask.","             */","            maskNode : {","                getter      : '_getMaskNode',","                readOnly    : true","            },","","","            /**","             * @attribute modal","             * @type boolean","             *","             * @description Whether the widget should be modal or not.","             */","            modal: {","                value:false,","                validator: isBoolean","            },","","            /**","             * @attribute focusOn","             * @type array","             *","             * @description An array of objects corresponding to the nodes and events that will trigger a re-focus back on the widget.","             * The implementer can supply an array of objects, with each object having the following properties:","             * <p>eventName: (string, required): The eventName to listen to.</p>","             * <p>node: (Y.Node, optional): The Y.Node that will fire the event (defaults to the boundingBox of the widget)</p>","             * <p>By default, this attribute consists of two objects which will cause the widget to re-focus if anything","             * outside the widget is clicked on or focussed upon.</p>","             */","            focusOn: {","                valueFn: function() {","                    return [","                        {","                            // node: this.get(BOUNDING_BOX),","                            eventName: ClickOutside","                        },","                        {","                            //node: this.get(BOUNDING_BOX),","                            eventName: FocusOutside","                        }","                    ];","                },","","                validator: Y.Lang.isArray","            }","","    };","","","    WidgetModal.CLASSES = MODAL_CLASSES;","","","    /**","     * Returns the mask if it exists on the page - otherwise creates a mask. There's only","     * one mask on a page at a given time.","     * <p>","     * This method in invoked internally by the getter of the maskNode ATTR.","     * </p>","     * @method _GET_MASK","     * @static","     */","    WidgetModal._GET_MASK = function() {","","        var mask = Y.one('.' + MODAL_CLASSES.mask),","            win  = Y.one('win');","","        if (mask) {","            return mask;","        }","","        mask = Y.Node.create('<div></div>').addClass(MODAL_CLASSES.mask);","","        if (supportsPosFixed) {","            mask.setStyles({","                position: 'fixed',","                width   : '100%',","                height  : '100%',","                top     : '0',","                left    : '0',","                display : 'block'","            });","        } else {","            mask.setStyles({","                position: 'absolute',","                width   : win.get('winWidth') +'px',","                height  : win.get('winHeight') + 'px',","                top     : '0',","                left    : '0',","                display : 'block'","            });","        }","","        return mask;","    };","","    /**","     * A stack of Y.Widget objects representing the current hierarchy of modal widgets presently displayed on the screen","     * @property STACK","     */","    WidgetModal.STACK = [];","","","    WidgetModal.prototype = {","","        initializer: function () {","            Y.after(this._renderUIModal, this, RENDER_UI);","            Y.after(this._syncUIModal, this, SYNC_UI);","            Y.after(this._bindUIModal, this, BIND_UI);","        },","","        destructor: function () {","            // Hack to remove this thing from the STACK.","            this._uiSetHostVisibleModal(false);","        },","","        // *** Instance Members *** //","","        _uiHandlesModal: null,","","","        /**","         * Adds modal class to the bounding box of the widget","         * <p>","         * This method in invoked after renderUI is invoked for the Widget class","         * using YUI's aop infrastructure.","         * </p>","         * @method _renderUIModal","         * @protected","         */","        _renderUIModal : function () {","","            var bb = this.get(BOUNDING_BOX);","                //cb = this.get(CONTENT_BOX);","","            //this makes the content box content appear over the mask","            // cb.setStyles({","            //     position: \"\"","            // });","","            this._repositionMask(this);","            bb.addClass(MODAL_CLASSES.modal);","","        },","","","        /**","         * Hooks up methods to be executed when the widget's visibility or z-index changes","         * <p>","         * This method in invoked after bindUI is invoked for the Widget class","         * using YUI's aop infrastructure.","         * </p>","         * @method _bindUIModal","         * @protected","         */","        _bindUIModal : function () {","","            this.after(VISIBLE+CHANGE, this._afterHostVisibleChangeModal);","            this.after(Z_INDEX+CHANGE, this._afterHostZIndexChangeModal);","            this.after(\"focusOnChange\", this._afterFocusOnChange);","","            // Re-align the mask in the viewport if `position: fixed;` is not","            // supported. iOS < 5 and Android < 3 don't actually support it even","            // though they both pass the feature test; the UA sniff is here to","            // account for that. Ideally this should be replaced with a better","            // feature test.","            if (!supportsPosFixed ||","                    (Y.UA.ios && Y.UA.ios < 5) ||","                    (Y.UA.android && Y.UA.android < 3)) {","","                Y.one('win').on('scroll', this._resyncMask, this);","            }","        },","","        /**","         * Syncs the mask with the widget's current state, namely the visibility and z-index of the widget","         * <p>","         * This method in invoked after syncUI is invoked for the Widget class","         * using YUI's aop infrastructure.","         * </p>","         * @method _syncUIModal","         * @protected","         */","        _syncUIModal : function () {","","            //var host = this.get(HOST);","","            this._uiSetHostVisibleModal(this.get(VISIBLE));","","        },","","        /**","         * Provides mouse and tab focus to the widget's bounding box.","         *","         * @method _focus","         */","        _focus : function (e) {","","            var bb = this.get(BOUNDING_BOX),","            oldTI = bb.get('tabIndex');","","            bb.set('tabIndex', oldTI >= 0 ? oldTI : 0);","            this.focus();","        },","        /**","         * Blurs the widget.","         *","         * @method _blur","         */","        _blur : function () {","","            this.blur();","        },","","        /**","         * Returns the Y.Node instance of the maskNode","         *","         * @method _getMaskNode","         * @return {Node} The Y.Node instance of the mask, as returned from WidgetModal._GET_MASK","         */","        _getMaskNode : function () {","","            return WidgetModal._GET_MASK();","        },","","        /**","         * Performs events attaching/detaching, stack shifting and mask repositioning based on the visibility of the widget","         *","         * @method _uiSetHostVisibleModal","         * @param {boolean} Whether the widget is visible or not","         */","        _uiSetHostVisibleModal : function (visible) {","            var stack    = WidgetModal.STACK,","                maskNode = this.get('maskNode'),","                isModal  = this.get('modal'),","                topModal, index;","","            if (visible) {","","                Y.Array.each(stack, function(modal){","                    modal._detachUIHandlesModal();","                    modal._blur();","                });","","                // push on top of stack","                stack.unshift(this);","","                this._repositionMask(this);","                this._uiSetHostZIndexModal(this.get(Z_INDEX));","","                if (isModal) {","                    maskNode.show();","                    Y.later(1, this, '_attachUIHandlesModal');","                    if (this.get(RENDERED)) {","                        this._focus();","                    }","                }","","","            } else {","","                index = Y.Array.indexOf(stack, this);","                if (index >= 0) {","                    // Remove modal widget from global stack.","                    stack.splice(index, 1);","                }","","                this._detachUIHandlesModal();","                this._blur();","","                if (stack.length) {","                    topModal = stack[0];","                    this._repositionMask(topModal);","                    //topModal._attachUIHandlesModal();","                    topModal._uiSetHostZIndexModal(topModal.get(Z_INDEX));","","                    if (topModal.get('modal')) {","                        //topModal._attachUIHandlesModal();","                        Y.later(1, topModal, '_attachUIHandlesModal');","                        topModal._focus();","                    }","","                } else {","","                    if (maskNode.getStyle('display') === 'block') {","                        maskNode.hide();","                    }","","                }","","            }","        },","","        /**","         * Sets the z-index of the mask node.","         *","         * @method _uiSetHostZIndexModal","         * @param {Number} Z-Index of the widget","         */","        _uiSetHostZIndexModal : function (zIndex) {","","            if (this.get('modal')) {","                this.get('maskNode').setStyle(Z_INDEX, zIndex || 0);","            }","","        },","","        /**","         * Attaches UI Listeners for \"clickoutside\" and \"focusoutside\" on the","         * widget. When these events occur, and the widget is modal, focus is","         * shifted back onto the widget.","         *","         * @method _attachUIHandlesModal","         */","        _attachUIHandlesModal : function () {","","            if (this._uiHandlesModal || WidgetModal.STACK[0] !== this) {","                // Quit early if we have ui handles, or if we not at the top","                // of the global stack.","                return;","            }","","            var bb          = this.get(BOUNDING_BOX),","                maskNode    = this.get('maskNode'),","                focusOn     = this.get('focusOn'),","                focus       = Y.bind(this._focus, this),","                uiHandles   = [],","                i, len, o;","","            for (i = 0, len = focusOn.length; i < len; i++) {","","                o = {};","                o.node = focusOn[i].node;","                o.ev = focusOn[i].eventName;","                o.keyCode = focusOn[i].keyCode;","","                //no keycode or node defined","                if (!o.node && !o.keyCode && o.ev) {","                    uiHandles.push(bb.on(o.ev, focus));","                }","","                //node defined, no keycode (not a keypress)","                else if (o.node && !o.keyCode && o.ev) {","                    uiHandles.push(o.node.on(o.ev, focus));","                }","","                //node defined, keycode defined, event defined (its a key press)","                else if (o.node && o.keyCode && o.ev) {","                    uiHandles.push(o.node.on(o.ev, focus, o.keyCode));","                }","","                else {","                    Y.Log('focusOn ATTR Error: The event with name \"'+o.ev+'\" could not be attached.');","                }","","            }","","            if ( ! supportsPosFixed) {","                uiHandles.push(Y.one('win').on('scroll', Y.bind(function(e){","                    maskNode.setStyle('top', maskNode.get('docScrollY'));","                }, this)));","            }","","            this._uiHandlesModal = uiHandles;","        },","","        /**","         * Detaches all UI Listeners that were set in _attachUIHandlesModal from the widget.","         *","         * @method _detachUIHandlesModal","         */","        _detachUIHandlesModal : function () {","            Y.each(this._uiHandlesModal, function(h){","                h.detach();","            });","            this._uiHandlesModal = null;","        },","","        /**","         * Default function that is called when visibility is changed on the widget.","         *","         * @method _afterHostVisibleChangeModal","         * @param {EventFacade} e The event facade of the change","         */","        _afterHostVisibleChangeModal : function (e) {","","            this._uiSetHostVisibleModal(e.newVal);","        },","","        /**","         * Default function that is called when z-index is changed on the widget.","         *","         * @method _afterHostZIndexChangeModal","         * @param {EventFacade} e The event facade of the change","         */","        _afterHostZIndexChangeModal : function (e) {","","            this._uiSetHostZIndexModal(e.newVal);","        },","","        /**","         * Returns a boolean representing whether the current widget is in a \"nested modality\" state.","         * This is done by checking the number of widgets currently on the stack.","         *","         * @method isNested","         * @public","         */","        isNested: function() {","            var length = WidgetModal.STACK.length,","            retval = (length > 1) ? true : false;","            return retval;","        },","","        /**","         * Repositions the mask in the DOM for nested modality cases.","         *","         * @method _repositionMask","         * @param {Widget} nextElem The Y.Widget instance that will be visible in the stack once the current widget is closed.","         */","        _repositionMask: function(nextElem) {","","            var currentModal = this.get('modal'),","                nextModal    = nextElem.get('modal'),","                maskNode     = this.get('maskNode'),","                bb, bbParent;","","            //if this is modal and host is not modal","            if (currentModal && !nextModal) {","                //leave the mask where it is, since the host is not modal.","                maskNode.remove();","                this.fire(MaskHide);","            }","","            //if the main widget is not modal but the host is modal, or both of them are modal","            else if ((!currentModal && nextModal) || (currentModal && nextModal)) {","","                //then remove the mask off DOM, reposition it, and reinsert it into the DOM","                maskNode.remove();","                this.fire(MaskHide);","                bb = nextElem.get(BOUNDING_BOX);","                bbParent = bb.get('parentNode') || Y.one('body');","                bbParent.insert(maskNode, bbParent.get('firstChild'));","                this.fire(MaskShow);","            }","","        },","","        /**","         * Resyncs the mask in the viewport for browsers that don't support fixed positioning","         *","         * @method _resyncMask","         * @param {Y.Widget} nextElem The Y.Widget instance that will be visible in the stack once the current widget is closed.","         * @private","         */","        _resyncMask: function (e) {","            var o       = e.currentTarget,","                offsetX = o.get('docScrollX'),","                offsetY = o.get('docScrollY'),","                w       = o.get('innerWidth') || o.get('winWidth'),","                h       = o.get('innerHeight') || o.get('winHeight'),","                mask    = this.get('maskNode');","","            mask.setStyles({","                \"top\": offsetY + \"px\",","                \"left\": offsetX + \"px\",","                \"width\": w + 'px',","                \"height\": h + 'px'","            });","        },","","        /**","         * Default function called when focusOn Attribute is changed. Remove existing listeners and create new listeners.","         *","         * @method _afterFocusOnChange","         */","        _afterFocusOnChange : function(e) {","            this._detachUIHandlesModal();","","            if (this.get(VISIBLE)) {","                this._attachUIHandlesModal();","            }","        }","    };","","    Y.WidgetModality = WidgetModal;","","","","}, '3.13.0', {\"requires\": [\"base-build\", \"event-outside\", \"widget\"], \"skinnable\": true});","","}());"]};
 }
 var __cov_3t8wDvjOucpJBP6BEEqjTg = __coverage__['build/widget-modality/widget-modality.js'];
-__cov_3t8wDvjOucpJBP6BEEqjTg.s['1']++;YUI.add('widget-modality',function(Y,NAME){__cov_3t8wDvjOucpJBP6BEEqjTg.f['1']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['2']++;var WIDGET='widget',RENDER_UI='renderUI',BIND_UI='bindUI',SYNC_UI='syncUI',BOUNDING_BOX='boundingBox',CONTENT_BOX='contentBox',VISIBLE='visible',Z_INDEX='zIndex',CHANGE='Change',isBoolean=Y.Lang.isBoolean,getCN=Y.ClassNameManager.getClassName,MaskShow='maskShow',MaskHide='maskHide',ClickOutside='clickoutside',FocusOutside='focusoutside',supportsPosFixed=function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['2']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['3']++;var doc=Y.config.doc,isSupported=null,el,root;__cov_3t8wDvjOucpJBP6BEEqjTg.s['4']++;if(doc.createElement){__cov_3t8wDvjOucpJBP6BEEqjTg.b['1'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['5']++;el=doc.createElement('div');__cov_3t8wDvjOucpJBP6BEEqjTg.s['6']++;if((__cov_3t8wDvjOucpJBP6BEEqjTg.b['3'][0]++,el)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['3'][1]++,el.style)){__cov_3t8wDvjOucpJBP6BEEqjTg.b['2'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['7']++;el.style.position='fixed';__cov_3t8wDvjOucpJBP6BEEqjTg.s['8']++;el.style.top='10px';__cov_3t8wDvjOucpJBP6BEEqjTg.s['9']++;root=doc.body;__cov_3t8wDvjOucpJBP6BEEqjTg.s['10']++;if((__cov_3t8wDvjOucpJBP6BEEqjTg.b['5'][0]++,root)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['5'][1]++,root.appendChild)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['5'][2]++,root.removeChild)){__cov_3t8wDvjOucpJBP6BEEqjTg.b['4'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['11']++;root.appendChild(el);__cov_3t8wDvjOucpJBP6BEEqjTg.s['12']++;isSupported=el.offsetTop===10;__cov_3t8wDvjOucpJBP6BEEqjTg.s['13']++;root.removeChild(el);}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['4'][1]++;}}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['2'][1]++;}}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['1'][1]++;}__cov_3t8wDvjOucpJBP6BEEqjTg.s['14']++;return isSupported;}();__cov_3t8wDvjOucpJBP6BEEqjTg.s['15']++;function WidgetModal(config){__cov_3t8wDvjOucpJBP6BEEqjTg.f['3']++;}__cov_3t8wDvjOucpJBP6BEEqjTg.s['16']++;var MODAL='modal',MASK='mask',MODAL_CLASSES={modal:getCN(WIDGET,MODAL),mask:getCN(WIDGET,MASK)};__cov_3t8wDvjOucpJBP6BEEqjTg.s['17']++;WidgetModal.ATTRS={maskNode:{getter:'_getMaskNode',readOnly:true},modal:{value:false,validator:isBoolean},focusOn:{valueFn:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['4']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['18']++;return[{eventName:ClickOutside},{eventName:FocusOutside}];},validator:Y.Lang.isArray}};__cov_3t8wDvjOucpJBP6BEEqjTg.s['19']++;WidgetModal.CLASSES=MODAL_CLASSES;__cov_3t8wDvjOucpJBP6BEEqjTg.s['20']++;WidgetModal._GET_MASK=function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['5']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['21']++;var mask=Y.one('.'+MODAL_CLASSES.mask),win=Y.one('win');__cov_3t8wDvjOucpJBP6BEEqjTg.s['22']++;if(mask){__cov_3t8wDvjOucpJBP6BEEqjTg.b['6'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['23']++;return mask;}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['6'][1]++;}__cov_3t8wDvjOucpJBP6BEEqjTg.s['24']++;mask=Y.Node.create('<div></div>').addClass(MODAL_CLASSES.mask);__cov_3t8wDvjOucpJBP6BEEqjTg.s['25']++;if(supportsPosFixed){__cov_3t8wDvjOucpJBP6BEEqjTg.b['7'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['26']++;mask.setStyles({position:'fixed',width:'100%',height:'100%',top:'0',left:'0',display:'block'});}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['7'][1]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['27']++;mask.setStyles({position:'absolute',width:win.get('winWidth')+'px',height:win.get('winHeight')+'px',top:'0',left:'0',display:'block'});}__cov_3t8wDvjOucpJBP6BEEqjTg.s['28']++;return mask;};__cov_3t8wDvjOucpJBP6BEEqjTg.s['29']++;WidgetModal.STACK=[];__cov_3t8wDvjOucpJBP6BEEqjTg.s['30']++;WidgetModal.prototype={initializer:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['6']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['31']++;Y.after(this._renderUIModal,this,RENDER_UI);__cov_3t8wDvjOucpJBP6BEEqjTg.s['32']++;Y.after(this._syncUIModal,this,SYNC_UI);__cov_3t8wDvjOucpJBP6BEEqjTg.s['33']++;Y.after(this._bindUIModal,this,BIND_UI);},destructor:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['7']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['34']++;this._uiSetHostVisibleModal(false);},_uiHandlesModal:null,_renderUIModal:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['8']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['35']++;var bb=this.get(BOUNDING_BOX);__cov_3t8wDvjOucpJBP6BEEqjTg.s['36']++;this._repositionMask(this);__cov_3t8wDvjOucpJBP6BEEqjTg.s['37']++;bb.addClass(MODAL_CLASSES.modal);},_bindUIModal:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['9']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['38']++;this.after(VISIBLE+CHANGE,this._afterHostVisibleChangeModal);__cov_3t8wDvjOucpJBP6BEEqjTg.s['39']++;this.after(Z_INDEX+CHANGE,this._afterHostZIndexChangeModal);__cov_3t8wDvjOucpJBP6BEEqjTg.s['40']++;this.after('focusOnChange',this._afterFocusOnChange);__cov_3t8wDvjOucpJBP6BEEqjTg.s['41']++;if((__cov_3t8wDvjOucpJBP6BEEqjTg.b['9'][0]++,!supportsPosFixed)||(__cov_3t8wDvjOucpJBP6BEEqjTg.b['9'][1]++,Y.UA.ios)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['9'][2]++,Y.UA.ios<5)||(__cov_3t8wDvjOucpJBP6BEEqjTg.b['9'][3]++,Y.UA.android)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['9'][4]++,Y.UA.android<3)){__cov_3t8wDvjOucpJBP6BEEqjTg.b['8'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['42']++;Y.one('win').on('scroll',this._resyncMask,this);}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['8'][1]++;}},_syncUIModal:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['10']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['43']++;this._uiSetHostVisibleModal(this.get(VISIBLE));},_focus:function(e){__cov_3t8wDvjOucpJBP6BEEqjTg.f['11']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['44']++;var bb=this.get(BOUNDING_BOX),oldTI=bb.get('tabIndex');__cov_3t8wDvjOucpJBP6BEEqjTg.s['45']++;bb.set('tabIndex',oldTI>=0?(__cov_3t8wDvjOucpJBP6BEEqjTg.b['10'][0]++,oldTI):(__cov_3t8wDvjOucpJBP6BEEqjTg.b['10'][1]++,0));__cov_3t8wDvjOucpJBP6BEEqjTg.s['46']++;this.focus();},_blur:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['12']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['47']++;this.blur();},_getMaskNode:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['13']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['48']++;return WidgetModal._GET_MASK();},_uiSetHostVisibleModal:function(visible){__cov_3t8wDvjOucpJBP6BEEqjTg.f['14']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['49']++;var stack=WidgetModal.STACK,maskNode=this.get('maskNode'),isModal=this.get('modal'),topModal,index;__cov_3t8wDvjOucpJBP6BEEqjTg.s['50']++;if(visible){__cov_3t8wDvjOucpJBP6BEEqjTg.b['11'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['51']++;Y.Array.each(stack,function(modal){__cov_3t8wDvjOucpJBP6BEEqjTg.f['15']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['52']++;modal._detachUIHandlesModal();__cov_3t8wDvjOucpJBP6BEEqjTg.s['53']++;modal._blur();});__cov_3t8wDvjOucpJBP6BEEqjTg.s['54']++;stack.unshift(this);__cov_3t8wDvjOucpJBP6BEEqjTg.s['55']++;this._repositionMask(this);__cov_3t8wDvjOucpJBP6BEEqjTg.s['56']++;this._uiSetHostZIndexModal(this.get(Z_INDEX));__cov_3t8wDvjOucpJBP6BEEqjTg.s['57']++;if(isModal){__cov_3t8wDvjOucpJBP6BEEqjTg.b['12'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['58']++;maskNode.show();__cov_3t8wDvjOucpJBP6BEEqjTg.s['59']++;Y.later(1,this,'_attachUIHandlesModal');__cov_3t8wDvjOucpJBP6BEEqjTg.s['60']++;this._focus();}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['12'][1]++;}}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['11'][1]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['61']++;index=Y.Array.indexOf(stack,this);__cov_3t8wDvjOucpJBP6BEEqjTg.s['62']++;if(index>=0){__cov_3t8wDvjOucpJBP6BEEqjTg.b['13'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['63']++;stack.splice(index,1);}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['13'][1]++;}__cov_3t8wDvjOucpJBP6BEEqjTg.s['64']++;this._detachUIHandlesModal();__cov_3t8wDvjOucpJBP6BEEqjTg.s['65']++;this._blur();__cov_3t8wDvjOucpJBP6BEEqjTg.s['66']++;if(stack.length){__cov_3t8wDvjOucpJBP6BEEqjTg.b['14'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['67']++;topModal=stack[0];__cov_3t8wDvjOucpJBP6BEEqjTg.s['68']++;this._repositionMask(topModal);__cov_3t8wDvjOucpJBP6BEEqjTg.s['69']++;topModal._uiSetHostZIndexModal(topModal.get(Z_INDEX));__cov_3t8wDvjOucpJBP6BEEqjTg.s['70']++;if(topModal.get('modal')){__cov_3t8wDvjOucpJBP6BEEqjTg.b['15'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['71']++;Y.later(1,topModal,'_attachUIHandlesModal');__cov_3t8wDvjOucpJBP6BEEqjTg.s['72']++;topModal._focus();}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['15'][1]++;}}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['14'][1]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['73']++;if(maskNode.getStyle('display')==='block'){__cov_3t8wDvjOucpJBP6BEEqjTg.b['16'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['74']++;maskNode.hide();}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['16'][1]++;}}}},_uiSetHostZIndexModal:function(zIndex){__cov_3t8wDvjOucpJBP6BEEqjTg.f['16']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['75']++;if(this.get('modal')){__cov_3t8wDvjOucpJBP6BEEqjTg.b['17'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['76']++;this.get('maskNode').setStyle(Z_INDEX,(__cov_3t8wDvjOucpJBP6BEEqjTg.b['18'][0]++,zIndex)||(__cov_3t8wDvjOucpJBP6BEEqjTg.b['18'][1]++,0));}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['17'][1]++;}},_attachUIHandlesModal:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['17']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['77']++;if((__cov_3t8wDvjOucpJBP6BEEqjTg.b['20'][0]++,this._uiHandlesModal)||(__cov_3t8wDvjOucpJBP6BEEqjTg.b['20'][1]++,WidgetModal.STACK[0]!==this)){__cov_3t8wDvjOucpJBP6BEEqjTg.b['19'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['78']++;return;}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['19'][1]++;}__cov_3t8wDvjOucpJBP6BEEqjTg.s['79']++;var bb=this.get(BOUNDING_BOX),maskNode=this.get('maskNode'),focusOn=this.get('focusOn'),focus=Y.bind(this._focus,this),uiHandles=[],i,len,o;__cov_3t8wDvjOucpJBP6BEEqjTg.s['80']++;for(i=0,len=focusOn.length;i<len;i++){__cov_3t8wDvjOucpJBP6BEEqjTg.s['81']++;o={};__cov_3t8wDvjOucpJBP6BEEqjTg.s['82']++;o.node=focusOn[i].node;__cov_3t8wDvjOucpJBP6BEEqjTg.s['83']++;o.ev=focusOn[i].eventName;__cov_3t8wDvjOucpJBP6BEEqjTg.s['84']++;o.keyCode=focusOn[i].keyCode;__cov_3t8wDvjOucpJBP6BEEqjTg.s['85']++;if((__cov_3t8wDvjOucpJBP6BEEqjTg.b['22'][0]++,!o.node)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['22'][1]++,!o.keyCode)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['22'][2]++,o.ev)){__cov_3t8wDvjOucpJBP6BEEqjTg.b['21'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['86']++;uiHandles.push(bb.on(o.ev,focus));}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['21'][1]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['87']++;if((__cov_3t8wDvjOucpJBP6BEEqjTg.b['24'][0]++,o.node)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['24'][1]++,!o.keyCode)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['24'][2]++,o.ev)){__cov_3t8wDvjOucpJBP6BEEqjTg.b['23'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['88']++;uiHandles.push(o.node.on(o.ev,focus));}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['23'][1]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['89']++;if((__cov_3t8wDvjOucpJBP6BEEqjTg.b['26'][0]++,o.node)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['26'][1]++,o.keyCode)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['26'][2]++,o.ev)){__cov_3t8wDvjOucpJBP6BEEqjTg.b['25'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['90']++;uiHandles.push(o.node.on(o.ev,focus,o.keyCode));}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['25'][1]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['91']++;Y.Log('focusOn ATTR Error: The event with name "'+o.ev+'" could not be attached.');}}}}__cov_3t8wDvjOucpJBP6BEEqjTg.s['92']++;if(!supportsPosFixed){__cov_3t8wDvjOucpJBP6BEEqjTg.b['27'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['93']++;uiHandles.push(Y.one('win').on('scroll',Y.bind(function(e){__cov_3t8wDvjOucpJBP6BEEqjTg.f['18']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['94']++;maskNode.setStyle('top',maskNode.get('docScrollY'));},this)));}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['27'][1]++;}__cov_3t8wDvjOucpJBP6BEEqjTg.s['95']++;this._uiHandlesModal=uiHandles;},_detachUIHandlesModal:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['19']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['96']++;Y.each(this._uiHandlesModal,function(h){__cov_3t8wDvjOucpJBP6BEEqjTg.f['20']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['97']++;h.detach();});__cov_3t8wDvjOucpJBP6BEEqjTg.s['98']++;this._uiHandlesModal=null;},_afterHostVisibleChangeModal:function(e){__cov_3t8wDvjOucpJBP6BEEqjTg.f['21']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['99']++;this._uiSetHostVisibleModal(e.newVal);},_afterHostZIndexChangeModal:function(e){__cov_3t8wDvjOucpJBP6BEEqjTg.f['22']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['100']++;this._uiSetHostZIndexModal(e.newVal);},isNested:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['23']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['101']++;var length=WidgetModal.STACK.length,retval=length>1?(__cov_3t8wDvjOucpJBP6BEEqjTg.b['28'][0]++,true):(__cov_3t8wDvjOucpJBP6BEEqjTg.b['28'][1]++,false);__cov_3t8wDvjOucpJBP6BEEqjTg.s['102']++;return retval;},_repositionMask:function(nextElem){__cov_3t8wDvjOucpJBP6BEEqjTg.f['24']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['103']++;var currentModal=this.get('modal'),nextModal=nextElem.get('modal'),maskNode=this.get('maskNode'),bb,bbParent;__cov_3t8wDvjOucpJBP6BEEqjTg.s['104']++;if((__cov_3t8wDvjOucpJBP6BEEqjTg.b['30'][0]++,currentModal)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['30'][1]++,!nextModal)){__cov_3t8wDvjOucpJBP6BEEqjTg.b['29'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['105']++;maskNode.remove();__cov_3t8wDvjOucpJBP6BEEqjTg.s['106']++;this.fire(MaskHide);}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['29'][1]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['107']++;if((__cov_3t8wDvjOucpJBP6BEEqjTg.b['32'][0]++,!currentModal)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['32'][1]++,nextModal)||(__cov_3t8wDvjOucpJBP6BEEqjTg.b['32'][2]++,currentModal)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['32'][3]++,nextModal)){__cov_3t8wDvjOucpJBP6BEEqjTg.b['31'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['108']++;maskNode.remove();__cov_3t8wDvjOucpJBP6BEEqjTg.s['109']++;this.fire(MaskHide);__cov_3t8wDvjOucpJBP6BEEqjTg.s['110']++;bb=nextElem.get(BOUNDING_BOX);__cov_3t8wDvjOucpJBP6BEEqjTg.s['111']++;bbParent=(__cov_3t8wDvjOucpJBP6BEEqjTg.b['33'][0]++,bb.get('parentNode'))||(__cov_3t8wDvjOucpJBP6BEEqjTg.b['33'][1]++,Y.one('body'));__cov_3t8wDvjOucpJBP6BEEqjTg.s['112']++;bbParent.insert(maskNode,bbParent.get('firstChild'));__cov_3t8wDvjOucpJBP6BEEqjTg.s['113']++;this.fire(MaskShow);}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['31'][1]++;}}},_resyncMask:function(e){__cov_3t8wDvjOucpJBP6BEEqjTg.f['25']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['114']++;var o=e.currentTarget,offsetX=o.get('docScrollX'),offsetY=o.get('docScrollY'),w=(__cov_3t8wDvjOucpJBP6BEEqjTg.b['34'][0]++,o.get('innerWidth'))||(__cov_3t8wDvjOucpJBP6BEEqjTg.b['34'][1]++,o.get('winWidth')),h=(__cov_3t8wDvjOucpJBP6BEEqjTg.b['35'][0]++,o.get('innerHeight'))||(__cov_3t8wDvjOucpJBP6BEEqjTg.b['35'][1]++,o.get('winHeight')),mask=this.get('maskNode');__cov_3t8wDvjOucpJBP6BEEqjTg.s['115']++;mask.setStyles({'top':offsetY+'px','left':offsetX+'px','width':w+'px','height':h+'px'});},_afterFocusOnChange:function(e){__cov_3t8wDvjOucpJBP6BEEqjTg.f['26']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['116']++;this._detachUIHandlesModal();__cov_3t8wDvjOucpJBP6BEEqjTg.s['117']++;if(this.get(VISIBLE)){__cov_3t8wDvjOucpJBP6BEEqjTg.b['36'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['118']++;this._attachUIHandlesModal();}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['36'][1]++;}}};__cov_3t8wDvjOucpJBP6BEEqjTg.s['119']++;Y.WidgetModality=WidgetModal;},'3.13.0',{'requires':['base-build','event-outside','widget'],'skinnable':true});
+__cov_3t8wDvjOucpJBP6BEEqjTg.s['1']++;YUI.add('widget-modality',function(Y,NAME){__cov_3t8wDvjOucpJBP6BEEqjTg.f['1']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['2']++;var WIDGET='widget',RENDER_UI='renderUI',BIND_UI='bindUI',SYNC_UI='syncUI',BOUNDING_BOX='boundingBox',CONTENT_BOX='contentBox',RENDERED='rendered',VISIBLE='visible',Z_INDEX='zIndex',CHANGE='Change',isBoolean=Y.Lang.isBoolean,getCN=Y.ClassNameManager.getClassName,MaskShow='maskShow',MaskHide='maskHide',ClickOutside='clickoutside',FocusOutside='focusoutside',supportsPosFixed=function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['2']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['3']++;var doc=Y.config.doc,isSupported=null,el,root;__cov_3t8wDvjOucpJBP6BEEqjTg.s['4']++;if(doc.createElement){__cov_3t8wDvjOucpJBP6BEEqjTg.b['1'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['5']++;el=doc.createElement('div');__cov_3t8wDvjOucpJBP6BEEqjTg.s['6']++;if((__cov_3t8wDvjOucpJBP6BEEqjTg.b['3'][0]++,el)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['3'][1]++,el.style)){__cov_3t8wDvjOucpJBP6BEEqjTg.b['2'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['7']++;el.style.position='fixed';__cov_3t8wDvjOucpJBP6BEEqjTg.s['8']++;el.style.top='10px';__cov_3t8wDvjOucpJBP6BEEqjTg.s['9']++;root=doc.body;__cov_3t8wDvjOucpJBP6BEEqjTg.s['10']++;if((__cov_3t8wDvjOucpJBP6BEEqjTg.b['5'][0]++,root)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['5'][1]++,root.appendChild)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['5'][2]++,root.removeChild)){__cov_3t8wDvjOucpJBP6BEEqjTg.b['4'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['11']++;root.appendChild(el);__cov_3t8wDvjOucpJBP6BEEqjTg.s['12']++;isSupported=el.offsetTop===10;__cov_3t8wDvjOucpJBP6BEEqjTg.s['13']++;root.removeChild(el);}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['4'][1]++;}}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['2'][1]++;}}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['1'][1]++;}__cov_3t8wDvjOucpJBP6BEEqjTg.s['14']++;return isSupported;}();__cov_3t8wDvjOucpJBP6BEEqjTg.s['15']++;function WidgetModal(config){__cov_3t8wDvjOucpJBP6BEEqjTg.f['3']++;}__cov_3t8wDvjOucpJBP6BEEqjTg.s['16']++;var MODAL='modal',MASK='mask',MODAL_CLASSES={modal:getCN(WIDGET,MODAL),mask:getCN(WIDGET,MASK)};__cov_3t8wDvjOucpJBP6BEEqjTg.s['17']++;WidgetModal.ATTRS={maskNode:{getter:'_getMaskNode',readOnly:true},modal:{value:false,validator:isBoolean},focusOn:{valueFn:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['4']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['18']++;return[{eventName:ClickOutside},{eventName:FocusOutside}];},validator:Y.Lang.isArray}};__cov_3t8wDvjOucpJBP6BEEqjTg.s['19']++;WidgetModal.CLASSES=MODAL_CLASSES;__cov_3t8wDvjOucpJBP6BEEqjTg.s['20']++;WidgetModal._GET_MASK=function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['5']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['21']++;var mask=Y.one('.'+MODAL_CLASSES.mask),win=Y.one('win');__cov_3t8wDvjOucpJBP6BEEqjTg.s['22']++;if(mask){__cov_3t8wDvjOucpJBP6BEEqjTg.b['6'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['23']++;return mask;}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['6'][1]++;}__cov_3t8wDvjOucpJBP6BEEqjTg.s['24']++;mask=Y.Node.create('<div></div>').addClass(MODAL_CLASSES.mask);__cov_3t8wDvjOucpJBP6BEEqjTg.s['25']++;if(supportsPosFixed){__cov_3t8wDvjOucpJBP6BEEqjTg.b['7'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['26']++;mask.setStyles({position:'fixed',width:'100%',height:'100%',top:'0',left:'0',display:'block'});}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['7'][1]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['27']++;mask.setStyles({position:'absolute',width:win.get('winWidth')+'px',height:win.get('winHeight')+'px',top:'0',left:'0',display:'block'});}__cov_3t8wDvjOucpJBP6BEEqjTg.s['28']++;return mask;};__cov_3t8wDvjOucpJBP6BEEqjTg.s['29']++;WidgetModal.STACK=[];__cov_3t8wDvjOucpJBP6BEEqjTg.s['30']++;WidgetModal.prototype={initializer:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['6']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['31']++;Y.after(this._renderUIModal,this,RENDER_UI);__cov_3t8wDvjOucpJBP6BEEqjTg.s['32']++;Y.after(this._syncUIModal,this,SYNC_UI);__cov_3t8wDvjOucpJBP6BEEqjTg.s['33']++;Y.after(this._bindUIModal,this,BIND_UI);},destructor:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['7']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['34']++;this._uiSetHostVisibleModal(false);},_uiHandlesModal:null,_renderUIModal:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['8']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['35']++;var bb=this.get(BOUNDING_BOX);__cov_3t8wDvjOucpJBP6BEEqjTg.s['36']++;this._repositionMask(this);__cov_3t8wDvjOucpJBP6BEEqjTg.s['37']++;bb.addClass(MODAL_CLASSES.modal);},_bindUIModal:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['9']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['38']++;this.after(VISIBLE+CHANGE,this._afterHostVisibleChangeModal);__cov_3t8wDvjOucpJBP6BEEqjTg.s['39']++;this.after(Z_INDEX+CHANGE,this._afterHostZIndexChangeModal);__cov_3t8wDvjOucpJBP6BEEqjTg.s['40']++;this.after('focusOnChange',this._afterFocusOnChange);__cov_3t8wDvjOucpJBP6BEEqjTg.s['41']++;if((__cov_3t8wDvjOucpJBP6BEEqjTg.b['9'][0]++,!supportsPosFixed)||(__cov_3t8wDvjOucpJBP6BEEqjTg.b['9'][1]++,Y.UA.ios)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['9'][2]++,Y.UA.ios<5)||(__cov_3t8wDvjOucpJBP6BEEqjTg.b['9'][3]++,Y.UA.android)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['9'][4]++,Y.UA.android<3)){__cov_3t8wDvjOucpJBP6BEEqjTg.b['8'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['42']++;Y.one('win').on('scroll',this._resyncMask,this);}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['8'][1]++;}},_syncUIModal:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['10']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['43']++;this._uiSetHostVisibleModal(this.get(VISIBLE));},_focus:function(e){__cov_3t8wDvjOucpJBP6BEEqjTg.f['11']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['44']++;var bb=this.get(BOUNDING_BOX),oldTI=bb.get('tabIndex');__cov_3t8wDvjOucpJBP6BEEqjTg.s['45']++;bb.set('tabIndex',oldTI>=0?(__cov_3t8wDvjOucpJBP6BEEqjTg.b['10'][0]++,oldTI):(__cov_3t8wDvjOucpJBP6BEEqjTg.b['10'][1]++,0));__cov_3t8wDvjOucpJBP6BEEqjTg.s['46']++;this.focus();},_blur:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['12']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['47']++;this.blur();},_getMaskNode:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['13']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['48']++;return WidgetModal._GET_MASK();},_uiSetHostVisibleModal:function(visible){__cov_3t8wDvjOucpJBP6BEEqjTg.f['14']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['49']++;var stack=WidgetModal.STACK,maskNode=this.get('maskNode'),isModal=this.get('modal'),topModal,index;__cov_3t8wDvjOucpJBP6BEEqjTg.s['50']++;if(visible){__cov_3t8wDvjOucpJBP6BEEqjTg.b['11'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['51']++;Y.Array.each(stack,function(modal){__cov_3t8wDvjOucpJBP6BEEqjTg.f['15']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['52']++;modal._detachUIHandlesModal();__cov_3t8wDvjOucpJBP6BEEqjTg.s['53']++;modal._blur();});__cov_3t8wDvjOucpJBP6BEEqjTg.s['54']++;stack.unshift(this);__cov_3t8wDvjOucpJBP6BEEqjTg.s['55']++;this._repositionMask(this);__cov_3t8wDvjOucpJBP6BEEqjTg.s['56']++;this._uiSetHostZIndexModal(this.get(Z_INDEX));__cov_3t8wDvjOucpJBP6BEEqjTg.s['57']++;if(isModal){__cov_3t8wDvjOucpJBP6BEEqjTg.b['12'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['58']++;maskNode.show();__cov_3t8wDvjOucpJBP6BEEqjTg.s['59']++;Y.later(1,this,'_attachUIHandlesModal');__cov_3t8wDvjOucpJBP6BEEqjTg.s['60']++;if(this.get(RENDERED)){__cov_3t8wDvjOucpJBP6BEEqjTg.b['13'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['61']++;this._focus();}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['13'][1]++;}}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['12'][1]++;}}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['11'][1]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['62']++;index=Y.Array.indexOf(stack,this);__cov_3t8wDvjOucpJBP6BEEqjTg.s['63']++;if(index>=0){__cov_3t8wDvjOucpJBP6BEEqjTg.b['14'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['64']++;stack.splice(index,1);}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['14'][1]++;}__cov_3t8wDvjOucpJBP6BEEqjTg.s['65']++;this._detachUIHandlesModal();__cov_3t8wDvjOucpJBP6BEEqjTg.s['66']++;this._blur();__cov_3t8wDvjOucpJBP6BEEqjTg.s['67']++;if(stack.length){__cov_3t8wDvjOucpJBP6BEEqjTg.b['15'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['68']++;topModal=stack[0];__cov_3t8wDvjOucpJBP6BEEqjTg.s['69']++;this._repositionMask(topModal);__cov_3t8wDvjOucpJBP6BEEqjTg.s['70']++;topModal._uiSetHostZIndexModal(topModal.get(Z_INDEX));__cov_3t8wDvjOucpJBP6BEEqjTg.s['71']++;if(topModal.get('modal')){__cov_3t8wDvjOucpJBP6BEEqjTg.b['16'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['72']++;Y.later(1,topModal,'_attachUIHandlesModal');__cov_3t8wDvjOucpJBP6BEEqjTg.s['73']++;topModal._focus();}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['16'][1]++;}}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['15'][1]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['74']++;if(maskNode.getStyle('display')==='block'){__cov_3t8wDvjOucpJBP6BEEqjTg.b['17'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['75']++;maskNode.hide();}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['17'][1]++;}}}},_uiSetHostZIndexModal:function(zIndex){__cov_3t8wDvjOucpJBP6BEEqjTg.f['16']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['76']++;if(this.get('modal')){__cov_3t8wDvjOucpJBP6BEEqjTg.b['18'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['77']++;this.get('maskNode').setStyle(Z_INDEX,(__cov_3t8wDvjOucpJBP6BEEqjTg.b['19'][0]++,zIndex)||(__cov_3t8wDvjOucpJBP6BEEqjTg.b['19'][1]++,0));}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['18'][1]++;}},_attachUIHandlesModal:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['17']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['78']++;if((__cov_3t8wDvjOucpJBP6BEEqjTg.b['21'][0]++,this._uiHandlesModal)||(__cov_3t8wDvjOucpJBP6BEEqjTg.b['21'][1]++,WidgetModal.STACK[0]!==this)){__cov_3t8wDvjOucpJBP6BEEqjTg.b['20'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['79']++;return;}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['20'][1]++;}__cov_3t8wDvjOucpJBP6BEEqjTg.s['80']++;var bb=this.get(BOUNDING_BOX),maskNode=this.get('maskNode'),focusOn=this.get('focusOn'),focus=Y.bind(this._focus,this),uiHandles=[],i,len,o;__cov_3t8wDvjOucpJBP6BEEqjTg.s['81']++;for(i=0,len=focusOn.length;i<len;i++){__cov_3t8wDvjOucpJBP6BEEqjTg.s['82']++;o={};__cov_3t8wDvjOucpJBP6BEEqjTg.s['83']++;o.node=focusOn[i].node;__cov_3t8wDvjOucpJBP6BEEqjTg.s['84']++;o.ev=focusOn[i].eventName;__cov_3t8wDvjOucpJBP6BEEqjTg.s['85']++;o.keyCode=focusOn[i].keyCode;__cov_3t8wDvjOucpJBP6BEEqjTg.s['86']++;if((__cov_3t8wDvjOucpJBP6BEEqjTg.b['23'][0]++,!o.node)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['23'][1]++,!o.keyCode)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['23'][2]++,o.ev)){__cov_3t8wDvjOucpJBP6BEEqjTg.b['22'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['87']++;uiHandles.push(bb.on(o.ev,focus));}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['22'][1]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['88']++;if((__cov_3t8wDvjOucpJBP6BEEqjTg.b['25'][0]++,o.node)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['25'][1]++,!o.keyCode)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['25'][2]++,o.ev)){__cov_3t8wDvjOucpJBP6BEEqjTg.b['24'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['89']++;uiHandles.push(o.node.on(o.ev,focus));}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['24'][1]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['90']++;if((__cov_3t8wDvjOucpJBP6BEEqjTg.b['27'][0]++,o.node)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['27'][1]++,o.keyCode)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['27'][2]++,o.ev)){__cov_3t8wDvjOucpJBP6BEEqjTg.b['26'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['91']++;uiHandles.push(o.node.on(o.ev,focus,o.keyCode));}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['26'][1]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['92']++;Y.Log('focusOn ATTR Error: The event with name "'+o.ev+'" could not be attached.');}}}}__cov_3t8wDvjOucpJBP6BEEqjTg.s['93']++;if(!supportsPosFixed){__cov_3t8wDvjOucpJBP6BEEqjTg.b['28'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['94']++;uiHandles.push(Y.one('win').on('scroll',Y.bind(function(e){__cov_3t8wDvjOucpJBP6BEEqjTg.f['18']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['95']++;maskNode.setStyle('top',maskNode.get('docScrollY'));},this)));}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['28'][1]++;}__cov_3t8wDvjOucpJBP6BEEqjTg.s['96']++;this._uiHandlesModal=uiHandles;},_detachUIHandlesModal:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['19']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['97']++;Y.each(this._uiHandlesModal,function(h){__cov_3t8wDvjOucpJBP6BEEqjTg.f['20']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['98']++;h.detach();});__cov_3t8wDvjOucpJBP6BEEqjTg.s['99']++;this._uiHandlesModal=null;},_afterHostVisibleChangeModal:function(e){__cov_3t8wDvjOucpJBP6BEEqjTg.f['21']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['100']++;this._uiSetHostVisibleModal(e.newVal);},_afterHostZIndexChangeModal:function(e){__cov_3t8wDvjOucpJBP6BEEqjTg.f['22']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['101']++;this._uiSetHostZIndexModal(e.newVal);},isNested:function(){__cov_3t8wDvjOucpJBP6BEEqjTg.f['23']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['102']++;var length=WidgetModal.STACK.length,retval=length>1?(__cov_3t8wDvjOucpJBP6BEEqjTg.b['29'][0]++,true):(__cov_3t8wDvjOucpJBP6BEEqjTg.b['29'][1]++,false);__cov_3t8wDvjOucpJBP6BEEqjTg.s['103']++;return retval;},_repositionMask:function(nextElem){__cov_3t8wDvjOucpJBP6BEEqjTg.f['24']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['104']++;var currentModal=this.get('modal'),nextModal=nextElem.get('modal'),maskNode=this.get('maskNode'),bb,bbParent;__cov_3t8wDvjOucpJBP6BEEqjTg.s['105']++;if((__cov_3t8wDvjOucpJBP6BEEqjTg.b['31'][0]++,currentModal)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['31'][1]++,!nextModal)){__cov_3t8wDvjOucpJBP6BEEqjTg.b['30'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['106']++;maskNode.remove();__cov_3t8wDvjOucpJBP6BEEqjTg.s['107']++;this.fire(MaskHide);}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['30'][1]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['108']++;if((__cov_3t8wDvjOucpJBP6BEEqjTg.b['33'][0]++,!currentModal)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['33'][1]++,nextModal)||(__cov_3t8wDvjOucpJBP6BEEqjTg.b['33'][2]++,currentModal)&&(__cov_3t8wDvjOucpJBP6BEEqjTg.b['33'][3]++,nextModal)){__cov_3t8wDvjOucpJBP6BEEqjTg.b['32'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['109']++;maskNode.remove();__cov_3t8wDvjOucpJBP6BEEqjTg.s['110']++;this.fire(MaskHide);__cov_3t8wDvjOucpJBP6BEEqjTg.s['111']++;bb=nextElem.get(BOUNDING_BOX);__cov_3t8wDvjOucpJBP6BEEqjTg.s['112']++;bbParent=(__cov_3t8wDvjOucpJBP6BEEqjTg.b['34'][0]++,bb.get('parentNode'))||(__cov_3t8wDvjOucpJBP6BEEqjTg.b['34'][1]++,Y.one('body'));__cov_3t8wDvjOucpJBP6BEEqjTg.s['113']++;bbParent.insert(maskNode,bbParent.get('firstChild'));__cov_3t8wDvjOucpJBP6BEEqjTg.s['114']++;this.fire(MaskShow);}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['32'][1]++;}}},_resyncMask:function(e){__cov_3t8wDvjOucpJBP6BEEqjTg.f['25']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['115']++;var o=e.currentTarget,offsetX=o.get('docScrollX'),offsetY=o.get('docScrollY'),w=(__cov_3t8wDvjOucpJBP6BEEqjTg.b['35'][0]++,o.get('innerWidth'))||(__cov_3t8wDvjOucpJBP6BEEqjTg.b['35'][1]++,o.get('winWidth')),h=(__cov_3t8wDvjOucpJBP6BEEqjTg.b['36'][0]++,o.get('innerHeight'))||(__cov_3t8wDvjOucpJBP6BEEqjTg.b['36'][1]++,o.get('winHeight')),mask=this.get('maskNode');__cov_3t8wDvjOucpJBP6BEEqjTg.s['116']++;mask.setStyles({'top':offsetY+'px','left':offsetX+'px','width':w+'px','height':h+'px'});},_afterFocusOnChange:function(e){__cov_3t8wDvjOucpJBP6BEEqjTg.f['26']++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['117']++;this._detachUIHandlesModal();__cov_3t8wDvjOucpJBP6BEEqjTg.s['118']++;if(this.get(VISIBLE)){__cov_3t8wDvjOucpJBP6BEEqjTg.b['37'][0]++;__cov_3t8wDvjOucpJBP6BEEqjTg.s['119']++;this._attachUIHandlesModal();}else{__cov_3t8wDvjOucpJBP6BEEqjTg.b['37'][1]++;}}};__cov_3t8wDvjOucpJBP6BEEqjTg.s['120']++;Y.WidgetModality=WidgetModal;},'3.13.0',{'requires':['base-build','event-outside','widget'],'skinnable':true});
index 49336f6..5e0cb8f 100644 (file)
@@ -19,6 +19,7 @@ var WIDGET       = 'widget',
     SYNC_UI      = 'syncUI',
     BOUNDING_BOX = 'boundingBox',
     CONTENT_BOX  = 'contentBox',
+    RENDERED     = 'rendered',
     VISIBLE      = 'visible',
     Z_INDEX      = 'zIndex',
     CHANGE       = 'Change',
@@ -336,7 +337,9 @@ var WIDGET       = 'widget',
                 if (isModal) {
                     maskNode.show();
                     Y.later(1, this, '_attachUIHandlesModal');
-                    this._focus();
+                    if (this.get(RENDERED)) {
+                        this._focus();
+                    }
                 }
 
 
index f8aa88d..a4b2f5d 100644 (file)
@@ -5,6 +5,6 @@ Licensed under the BSD License.
 http://yuilibrary.com/license/
 */
 
-YUI.add("widget-modality",function(e,t){function y(e){}var n="widget",r="renderUI",i="bindUI",s="syncUI",o="boundingBox",u="contentBox",a="visible",f="zIndex",l="Change",c=e.Lang.isBoolean,h=e.ClassNameManager.getClassName,p="maskShow",d="maskHide",v="clickoutside",m="focusoutside",g=function(){
+YUI.add("widget-modality",function(e,t){function b(e){}var n="widget",r="renderUI",i="bindUI",s="syncUI",o="boundingBox",u="contentBox",a="rendered",f="visible",l="zIndex",c="Change",h=e.Lang.isBoolean,p=e.ClassNameManager.getClassName,d="maskShow",v="maskHide",m="clickoutside",g="focusoutside",y=function(){
 /*! IS_POSITION_FIXED_SUPPORTED - Juriy Zaytsev (kangax) - http://yura.thinkweb2.com/cft/ */
-;var t=e.config.doc,n=null,r,i;return t.createElement&&(r=t.createElement("div"),r&&r.style&&(r.style.position="fixed",r.style.top="10px",i=t.body,i&&i.appendChild&&i.removeChild&&(i.appendChild(r),n=r.offsetTop===10,i.removeChild(r)))),n}(),b="modal",w="mask",E={modal:h(n,b),mask:h(n,w)};y.ATTRS={maskNode:{getter:"_getMaskNode",readOnly:!0},modal:{value:!1,validator:c},focusOn:{valueFn:function(){return[{eventName:v},{eventName:m}]},validator:e.Lang.isArray}},y.CLASSES=E,y._GET_MASK=function(){var t=e.one("."+E.mask),n=e.one("win");return t?t:(t=e.Node.create("<div></div>").addClass(E.mask),g?t.setStyles({position:"fixed",width:"100%",height:"100%",top:"0",left:"0",display:"block"}):t.setStyles({position:"absolute",width:n.get("winWidth")+"px",height:n.get("winHeight")+"px",top:"0",left:"0",display:"block"}),t)},y.STACK=[],y.prototype={initializer:function(){e.after(this._renderUIModal,this,r),e.after(this._syncUIModal,this,s),e.after(this._bindUIModal,this,i)},destructor:function(){this._uiSetHostVisibleModal(!1)},_uiHandlesModal:null,_renderUIModal:function(){var e=this.get(o);this._repositionMask(this),e.addClass(E.modal)},_bindUIModal:function(){this.after(a+l,this._afterHostVisibleChangeModal),this.after(f+l,this._afterHostZIndexChangeModal),this.after("focusOnChange",this._afterFocusOnChange),(!g||e.UA.ios&&e.UA.ios<5||e.UA.android&&e.UA.android<3)&&e.one("win").on("scroll",this._resyncMask,this)},_syncUIModal:function(){this._uiSetHostVisibleModal(this.get(a))},_focus:function(e){var t=this.get(o),n=t.get("tabIndex");t.set("tabIndex",n>=0?n:0),this.focus()},_blur:function(){this.blur()},_getMaskNode:function(){return y._GET_MASK()},_uiSetHostVisibleModal:function(t){var n=y.STACK,r=this.get("maskNode"),i=this.get("modal"),s,o;t?(e.Array.each(n,function(e){e._detachUIHandlesModal(),e._blur()}),n.unshift(this),this._repositionMask(this),this._uiSetHostZIndexModal(this.get(f)),i&&(r.show(),e.later(1,this,"_attachUIHandlesModal"),this._focus())):(o=e.Array.indexOf(n,this),o>=0&&n.splice(o,1),this._detachUIHandlesModal(),this._blur(),n.length?(s=n[0],this._repositionMask(s),s._uiSetHostZIndexModal(s.get(f)),s.get("modal")&&(e.later(1,s,"_attachUIHandlesModal"),s._focus())):r.getStyle("display")==="block"&&r.hide())},_uiSetHostZIndexModal:function(e){this.get("modal")&&this.get("maskNode").setStyle(f,e||0)},_attachUIHandlesModal:function(){if(this._uiHandlesModal||y.STACK[0]!==this)return;var t=this.get(o),n=this.get("maskNode"),r=this.get("focusOn"),i=e.bind(this._focus,this),s=[],u,a,f;for(u=0,a=r.length;u<a;u++)f={},f.node=r[u].node,f.ev=r[u].eventName,f.keyCode=r[u].keyCode,!f.node&&!f.keyCode&&f.ev?s.push(t.on(f.ev,i)):f.node&&!f.keyCode&&f.ev?s.push(f.node.on(f.ev,i)):f.node&&f.keyCode&&f.ev?s.push(f.node.on(f.ev,i,f.keyCode)):e.Log('focusOn ATTR Error: The event with name "'+f.ev+'" could not be attached.');g||s.push(e.one("win").on("scroll",e.bind(function(e){n.setStyle("top",n.get("docScrollY"))},this))),this._uiHandlesModal=s},_detachUIHandlesModal:function(){e.each(this._uiHandlesModal,function(e){e.detach()}),this._uiHandlesModal=null},_afterHostVisibleChangeModal:function(e){this._uiSetHostVisibleModal(e.newVal)},_afterHostZIndexChangeModal:function(e){this._uiSetHostZIndexModal(e.newVal)},isNested:function(){var e=y.STACK.length,t=e>1?!0:!1;return t},_repositionMask:function(t){var n=this.get("modal"),r=t.get("modal"),i=this.get("maskNode"),s,u;if(n&&!r)i.remove(),this.fire(d);else if(!n&&r||n&&r)i.remove(),this.fire(d),s=t.get(o),u=s.get("parentNode")||e.one("body"),u.insert(i,u.get("firstChild")),this.fire(p)},_resyncMask:function(e){var t=e.currentTarget,n=t.get("docScrollX"),r=t.get("docScrollY"),i=t.get("innerWidth")||t.get("winWidth"),s=t.get("innerHeight")||t.get("winHeight"),o=this.get("maskNode");o.setStyles({top:r+"px",left:n+"px",width:i+"px",height:s+"px"})},_afterFocusOnChange:function(e){this._detachUIHandlesModal(),this.get(a)&&this._attachUIHandlesModal()}},e.WidgetModality=y},"3.13.0",{requires:["base-build","event-outside","widget"],skinnable:!0});
+;var t=e.config.doc,n=null,r,i;return t.createElement&&(r=t.createElement("div"),r&&r.style&&(r.style.position="fixed",r.style.top="10px",i=t.body,i&&i.appendChild&&i.removeChild&&(i.appendChild(r),n=r.offsetTop===10,i.removeChild(r)))),n}(),w="modal",E="mask",S={modal:p(n,w),mask:p(n,E)};b.ATTRS={maskNode:{getter:"_getMaskNode",readOnly:!0},modal:{value:!1,validator:h},focusOn:{valueFn:function(){return[{eventName:m},{eventName:g}]},validator:e.Lang.isArray}},b.CLASSES=S,b._GET_MASK=function(){var t=e.one("."+S.mask),n=e.one("win");return t?t:(t=e.Node.create("<div></div>").addClass(S.mask),y?t.setStyles({position:"fixed",width:"100%",height:"100%",top:"0",left:"0",display:"block"}):t.setStyles({position:"absolute",width:n.get("winWidth")+"px",height:n.get("winHeight")+"px",top:"0",left:"0",display:"block"}),t)},b.STACK=[],b.prototype={initializer:function(){e.after(this._renderUIModal,this,r),e.after(this._syncUIModal,this,s),e.after(this._bindUIModal,this,i)},destructor:function(){this._uiSetHostVisibleModal(!1)},_uiHandlesModal:null,_renderUIModal:function(){var e=this.get(o);this._repositionMask(this),e.addClass(S.modal)},_bindUIModal:function(){this.after(f+c,this._afterHostVisibleChangeModal),this.after(l+c,this._afterHostZIndexChangeModal),this.after("focusOnChange",this._afterFocusOnChange),(!y||e.UA.ios&&e.UA.ios<5||e.UA.android&&e.UA.android<3)&&e.one("win").on("scroll",this._resyncMask,this)},_syncUIModal:function(){this._uiSetHostVisibleModal(this.get(f))},_focus:function(e){var t=this.get(o),n=t.get("tabIndex");t.set("tabIndex",n>=0?n:0),this.focus()},_blur:function(){this.blur()},_getMaskNode:function(){return b._GET_MASK()},_uiSetHostVisibleModal:function(t){var n=b.STACK,r=this.get("maskNode"),i=this.get("modal"),s,o;t?(e.Array.each(n,function(e){e._detachUIHandlesModal(),e._blur()}),n.unshift(this),this._repositionMask(this),this._uiSetHostZIndexModal(this.get(l)),i&&(r.show(),e.later(1,this,"_attachUIHandlesModal"),this.get(a)&&this._focus())):(o=e.Array.indexOf(n,this),o>=0&&n.splice(o,1),this._detachUIHandlesModal(),this._blur(),n.length?(s=n[0],this._repositionMask(s),s._uiSetHostZIndexModal(s.get(l)),s.get("modal")&&(e.later(1,s,"_attachUIHandlesModal"),s._focus())):r.getStyle("display")==="block"&&r.hide())},_uiSetHostZIndexModal:function(e){this.get("modal")&&this.get("maskNode").setStyle(l,e||0)},_attachUIHandlesModal:function(){if(this._uiHandlesModal||b.STACK[0]!==this)return;var t=this.get(o),n=this.get("maskNode"),r=this.get("focusOn"),i=e.bind(this._focus,this),s=[],u,a,f;for(u=0,a=r.length;u<a;u++)f={},f.node=r[u].node,f.ev=r[u].eventName,f.keyCode=r[u].keyCode,!f.node&&!f.keyCode&&f.ev?s.push(t.on(f.ev,i)):f.node&&!f.keyCode&&f.ev?s.push(f.node.on(f.ev,i)):f.node&&f.keyCode&&f.ev?s.push(f.node.on(f.ev,i,f.keyCode)):e.Log('focusOn ATTR Error: The event with name "'+f.ev+'" could not be attached.');y||s.push(e.one("win").on("scroll",e.bind(function(e){n.setStyle("top",n.get("docScrollY"))},this))),this._uiHandlesModal=s},_detachUIHandlesModal:function(){e.each(this._uiHandlesModal,function(e){e.detach()}),this._uiHandlesModal=null},_afterHostVisibleChangeModal:function(e){this._uiSetHostVisibleModal(e.newVal)},_afterHostZIndexChangeModal:function(e){this._uiSetHostZIndexModal(e.newVal)},isNested:function(){var e=b.STACK.length,t=e>1?!0:!1;return t},_repositionMask:function(t){var n=this.get("modal"),r=t.get("modal"),i=this.get("maskNode"),s,u;if(n&&!r)i.remove(),this.fire(v);else if(!n&&r||n&&r)i.remove(),this.fire(v),s=t.get(o),u=s.get("parentNode")||e.one("body"),u.insert(i,u.get("firstChild")),this.fire(d)},_resyncMask:function(e){var t=e.currentTarget,n=t.get("docScrollX"),r=t.get("docScrollY"),i=t.get("innerWidth")||t.get("winWidth"),s=t.get("innerHeight")||t.get("winHeight"),o=this.get("maskNode");o.setStyles({top:r+"px",left:n+"px",width:i+"px",height:s+"px"})},_afterFocusOnChange:function(e){this._detachUIHandlesModal(),this.get(f)&&this._attachUIHandlesModal()}},e.WidgetModality=b},"3.13.0",{requires:["base-build","event-outside","widget"],skinnable:!0});
index 49336f6..5e0cb8f 100644 (file)
@@ -19,6 +19,7 @@ var WIDGET       = 'widget',
     SYNC_UI      = 'syncUI',
     BOUNDING_BOX = 'boundingBox',
     CONTENT_BOX  = 'contentBox',
+    RENDERED     = 'rendered',
     VISIBLE      = 'visible',
     Z_INDEX      = 'zIndex',
     CHANGE       = 'Change',
@@ -336,7 +337,9 @@ var WIDGET       = 'widget',
                 if (isModal) {
                     maskNode.show();
                     Y.later(1, this, '_attachUIHandlesModal');
-                    this._focus();
+                    if (this.get(RENDERED)) {
+                        this._focus();
+                    }
                 }
 
 
index e00100a..7b06b6f 100644 (file)
Binary files a/mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-debug.js and b/mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-debug.js differ
index 066f2e0..651bbd9 100644 (file)
Binary files a/mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-min.js and b/mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-min.js differ
index e00100a..7b06b6f 100644 (file)
Binary files a/mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor.js and b/mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor.js differ
index 7989a7a..5d10701 100644 (file)
@@ -288,6 +288,7 @@ EDITOR.prototype = {
                 headerContent: this.get('header'),
                 bodyContent: this.get('body'),
                 footerContent: this.get('footer'),
+                modal: true,
                 width: '840px',
                 visible: false,
                 draggable: true
diff --git a/mod/data/classes/event/course_module_instance_list_viewed.php b/mod/data/classes/event/course_module_instance_list_viewed.php
new file mode 100644 (file)
index 0000000..7e19721
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * The mod_data course module instance list viewed event.
+ *
+ * @package    mod_data
+ * @copyright  2014 Mark Nelson <markn@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_data\event;
+
+defined('MOODLE_INTERNAL') || die();
+
+class course_module_instance_list_viewed extends \core\event\course_module_instance_list_viewed {
+    // No code required here as the parent class handles it all.
+}
+
diff --git a/mod/data/classes/event/course_module_viewed.php b/mod/data/classes/event/course_module_viewed.php
new file mode 100644 (file)
index 0000000..14358e2
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * The mod_data course module viewed event.
+ *
+ * @package    mod_data
+ * @copyright  2014 Mark Nelson <markn@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_data\event;
+
+defined('MOODLE_INTERNAL') || die();
+
+class course_module_viewed extends \core\event\course_module_viewed {
+
+    /**
+     * Init method.
+     *
+     * @return void
+     */
+    protected function init() {
+        $this->data['objecttable'] = 'data';
+        $this->data['crud'] = 'r';
+        $this->data['edulevel'] = self::LEVEL_PARTICIPATING;
+    }
+}
diff --git a/mod/data/classes/event/field_created.php b/mod/data/classes/event/field_created.php
new file mode 100644 (file)
index 0000000..e479697
--- /dev/null
@@ -0,0 +1,94 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * The mod_data field created event.
+ *
+ * @property-read array $other {
+ *      Extra information about event.
+ *
+ *      @type string fieldname the name of the field.
+ *      @type int dataid the id of the data activity.
+ * }
+ *
+ * @package    mod_data
+ * @copyright  2014 Mark Nelson <markn@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_data\event;
+
+defined('MOODLE_INTERNAL') || die();
+
+class field_created extends \core\event\base {
+
+    /**
+     * Init method.
+     *
+     * @return void
+     */
+    protected function init() {
+        $this->data['objecttable'] = 'data_fields';
+        $this->data['crud'] = 'c';
+        $this->data['edulevel'] = self::LEVEL_TEACHING;
+    }
+
+    /**
+     * Return localised event name.
+     *
+     * @return string
+     */
+    public static function get_name() {
+        return get_string('eventfieldcreated', 'mod_data');
+    }
+
+    /**
+     * Returns description of what happened.
+     *
+     * @return string
+     */
+    public function get_description() {
+        return 'The field ' . $this->objectid . ' belonging to the data activity ' . $this->other['dataid'] . ' has been created.';
+    }
+
+    /**
+     * Get the legacy event log data.
+     *
+     * @return array
+     */
+    public function get_legacy_logdata() {
+        return array($this->courseid, 'data', 'fields add', 'field.php?d=' . $this->other['dataid'] . '&amp;mode=display&amp;fid=' .
+            $this->objectid, $this->objectid, $this->contextinstanceid);
+    }
+
+    /**
+     * Custom validation.
+     *
+     * @throws \coding_exception when validation does not pass.
+     * @return void
+     */
+    protected function validate_data() {
+        parent::validate_data();
+
+        if (!isset($this->other['fieldname'])) {
+            throw new \coding_exception('The fieldname must be set in $other.');
+        }
+
+        if (!isset($this->other['dataid'])) {
+            throw new \coding_exception('The dataid must be set in $other.');
+        }
+    }
+}
diff --git a/mod/data/classes/event/field_deleted.php b/mod/data/classes/event/field_deleted.php
new file mode 100644 (file)
index 0000000..8004537
--- /dev/null
@@ -0,0 +1,94 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * The mod_data field deleted event.
+ *
+ * @property-read array $other {
+ *      Extra information about event.
+ *
+ *      @type string fieldname the name of the field.
+ *      @type int dataid the id of the data activity.
+ * }
+ *
+ * @package    mod_data
+ * @copyright  2014 Mark Nelson <markn@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_data\event;
+
+defined('MOODLE_INTERNAL') || die();
+
+class field_deleted extends \core\event\base {
+
+    /**
+     * Init method.
+     *
+     * @return void
+     */
+    protected function init() {
+        $this->data['objecttable'] = 'data_fields';
+        $this->data['crud'] = 'd';
+        $this->data['edulevel'] = self::LEVEL_TEACHING;
+    }
+
+    /**
+     * Return localised event name.
+     *
+     * @return string
+     */
+    public static function get_name() {
+        return get_string('eventfielddeleted', 'mod_data');
+    }
+
+    /**
+     * Returns description of what happened.
+     *
+     * @return string
+     */
+    public function get_description() {
+        return 'The field ' . $this->objectid . ' belonging to the data activity ' . $this->other['dataid'] . ' has been deleted.';
+    }
+
+    /**
+     * Get the legacy event log data.
+     *
+     * @return array
+     */
+    public function get_legacy_logdata() {
+        return array($this->courseid, 'data', 'fields delete', 'field.php?d=' . $this->other['dataid'],
+            $this->other['fieldname'], $this->contextinstanceid);
+    }
+
+    /**
+     * Custom validation.
+     *
+     * @throws \coding_exception when validation does not pass.
+     * @return void
+     */
+    protected function validate_data() {
+        parent::validate_data();
+
+        if (!isset($this->other['fieldname'])) {
+            throw new \coding_exception('The fieldname must be set in $other.');
+        }
+
+        if (!isset($this->other['dataid'])) {
+            throw new \coding_exception('The dataid must be set in $other.');
+        }
+    }
+}
diff --git a/mod/data/classes/event/field_updated.php b/mod/data/classes/event/field_updated.php
new file mode 100644 (file)
index 0000000..eb80890
--- /dev/null
@@ -0,0 +1,94 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * The mod_data field updated event.
+ *
+ * @property-read array $other {
+ *      Extra information about event.
+ *
+ *      @type string fieldname the name of the field.
+ *      @type int dataid the id of the data activity.
+ * }
+ *
+ * @package    mod_data
+ * @copyright  2014 Mark Nelson <markn@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_data\event;
+
+defined('MOODLE_INTERNAL') || die();
+
+class field_updated extends \core\event\base {
+
+    /**
+     * Init method.
+     *
+     * @return void
+     */
+    protected function init() {
+        $this->data['objecttable'] = 'data_fields';
+        $this->data['crud'] = 'u';
+        $this->data['edulevel'] = self::LEVEL_TEACHING;
+    }
+
+    /**
+     * Return localised event name.
+     *
+     * @return string
+     */
+    public static function get_name() {
+        return get_string('eventfieldupdated', 'mod_data');
+    }
+
+    /**
+     * Returns description of what happened.
+     *
+     * @return string
+     */
+    public function get_description() {
+        return 'The field ' . $this->objectid . ' belonging to the data activity ' . $this->other['dataid'] . ' has been updated.';
+    }
+
+    /**
+     * Get the legacy event log data.
+     *
+     * @return array
+     */
+    public function get_legacy_logdata() {
+        return array($this->courseid, 'data', 'fields update', 'field.php?d=' . $this->other['dataid'] .
+            '&amp;mode=display&amp;fid=' . $this->objectid, $this->objectid, $this->contextinstanceid);
+    }
+
+    /**
+     * Custom validation.
+     *
+     * @throws \coding_exception when validation does not pass.
+     * @return void
+     */
+    protected function validate_data() {
+        parent::validate_data();
+
+        if (!isset($this->other['fieldname'])) {
+            throw new \coding_exception('The fieldname must be set in $other.');
+        }
+
+        if (!isset($this->other['dataid'])) {
+            throw new \coding_exception('The dataid must be set in $other.');
+        }
+    }
+}
diff --git a/mod/data/classes/event/record_created.php b/mod/data/classes/event/record_created.php
new file mode 100644 (file)
index 0000000..5cbfe26
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * The mod_data data record created event.
+ *
+ * @property-read array $other {
+ *      Extra information about event.
+ *
+ *      @type int dataid the id of the data activity.
+ * }
+ *
+ * @package    mod_data
+ * @copyright  2014 Mark Nelson <markn@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_data\event;
+
+defined('MOODLE_INTERNAL') || die();
+
+class record_created extends \core\event\base {
+
+    /**
+     * Init method.
+     *
+     * @return void
+     */
+    protected function init() {
+        $this->data['objecttable'] = 'data_records';
+        $this->data['crud'] = 'c';
+        $this->data['edulevel'] = self::LEVEL_TEACHING;
+    }
+
+    /**
+     * Return localised event name.
+     *
+     * @return string
+     */
+    public static function get_name() {
+        return get_string('eventrecordcreated', 'mod_data');
+    }
+
+    /**
+     * Returns description of what happened.
+     *
+     * @return string
+     */
+    public function get_description() {
+        return 'The data record ' . $this->objectid . ' belonging to the database activity ' . $this->other['dataid'] .
+            ' was created by the user ' . $this->userid;
+    }
+
+    /**
+     * Get the legacy event log data.
+     *
+     * @return array
+     */
+    public function get_legacy_logdata() {
+        return array($this->courseid, 'data', 'add', 'view.php?d=' . $this->other['dataid'] . '&amp;rid=' . $this->objectid,
+            $this->other['dataid'], $this->contextinstanceid);
+    }
+
+    /**
+     * Custom validation.
+     *
+     * @throws \coding_exception when validation does not pass.
+     * @return void
+     */
+    protected function validate_data() {
+        parent::validate_data();
+
+        if (!isset($this->other['dataid'])) {
+            throw new \coding_exception('The dataid must be set in $other.');
+        }
+    }
+}
diff --git a/mod/data/classes/event/record_deleted.php b/mod/data/classes/event/record_deleted.php
new file mode 100644 (file)
index 0000000..f611d9a
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * The mod_data record deleted event.
+ *
+ * @property-read array $other {
+ *      Extra information about event.
+ *
+ *      @type int dataid the id of the data activity.
+ * }
+ *
+ * @package    mod_data
+ * @copyright  2014 Mark Nelson <markn@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_data\event;
+
+defined('MOODLE_INTERNAL') || die();
+
+class record_deleted extends \core\event\base {
+
+    /**
+     * Init method.
+     *
+     * @return void
+     */
+    protected function init() {
+        $this->data['objecttable'] = 'data_records';
+        $this->data['crud'] = 'd';
+        $this->data['edulevel'] = self::LEVEL_TEACHING;
+    }
+
+    /**
+     * Return localised event name.
+     *
+     * @return string
+     */
+    public static function get_name() {
+        return get_string('eventrecorddeleted', 'mod_data');
+    }
+
+    /**
+     * Returns description of what happened.
+     *
+     * @return string
+     */
+    public function get_description() {
+        return 'The data record ' . $this->objectid . ' belonging to the database activity ' . $this->other['dataid'] .
+            ' was deleted by the user ' . $this->userid;
+    }
+
+    /**
+     * Get the legacy event log data.
+     *
+     * @return array
+     */
+    public function get_legacy_logdata() {
+        return array($this->courseid, 'data', 'record delete', 'view.php?id=' . $this->contextinstanceid,
+            $this->other['dataid'], $this->contextinstanceid);
+    }
+
+    /**
+     * Custom validation.
+     *
+     * @throws \coding_exception when validation does not pass.
+     * @return void
+     */
+    protected function validate_data() {
+        parent::validate_data();
+
+        if (!isset($this->other['dataid'])) {
+            throw new \coding_exception('The dataid must be set in $other.');
+        }
+    }
+}
diff --git a/mod/data/classes/event/record_updated.php b/mod/data/classes/event/record_updated.php
new file mode 100644 (file)
index 0000000..5ba249a
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * The mod_data record updated event.
+ *
+ * @property-read array $other {
+ *      Extra information about event.
+ *
+ *      @type int dataid the id of the data activity.
+ * }
+ *
+ * @package    mod_data
+ * @copyright  2014 Mark Nelson <markn@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_data\event;
+
+defined('MOODLE_INTERNAL') || die();
+
+class record_updated extends \core\event\base {
+
+    /**
+     * Init method.
+     *
+     * @return void
+     */
+    protected function init() {
+        $this->data['objecttable'] = 'data_records';
+        $this->data['crud'] = 'u';
+        $this->data['edulevel'] = self::LEVEL_TEACHING;
+    }
+
+    /**
+     * Return localised event name.
+     *
+     * @return string
+     */
+    public static function get_name() {
+        return get_string('eventrecordupdated', 'mod_data');
+    }
+
+    /**
+     * Returns description of what happened.
+     *
+     * @return string
+     */
+    public function get_description() {
+        return 'The data record ' . $this->objectid . ' belonging to the database activity ' . $this->other['dataid'] .
+            ' was updated by the user ' . $this->userid;
+    }
+
+    /**
+     * Get the legacy event log data.
+     *
+     * @return array
+     */
+    public function get_legacy_logdata() {
+        return array($this->courseid, 'data', 'update', 'view.php?d=' . $this->other['dataid'] . '&amp;rid=' . $this->objectid,
+            $this->other['dataid'], $this->contextinstanceid);
+    }
+
+    /**
+     * Custom validation.
+     *
+     * @throws \coding_exception when validation does not pass.
+     * @return void
+     */
+    protected function validate_data() {
+        parent::validate_data();
+
+        if (!isset($this->other['dataid'])) {
+            throw new \coding_exception('The dataid must be set in $other.');
+        }
+    }
+}
diff --git a/mod/data/classes/event/template_updated.php b/mod/data/classes/event/template_updated.php
new file mode 100644 (file)
index 0000000..e89424d
--- /dev/null
@@ -0,0 +1,88 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * The mod_data template updated event.
+ *
+ * @property-read array $other {
+ *      Extra information about event.
+ *
+ *      @type int dataid the id of the data activity.
+ * }
+ *
+ * @package    mod_data
+ * @copyright  2014 Mark Nelson <markn@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_data\event;
+
+defined('MOODLE_INTERNAL') || die();
+
+class template_updated extends \core\event\base {
+
+    /**
+     * Init method.
+     *
+     * @return void
+     */
+    protected function init() {
+        $this->data['crud'] = 'u';
+        $this->data['edulevel'] = self::LEVEL_OTHER;
+    }
+
+    /**
+     * Return localised event name.
+     *
+     * @return string
+     */
+    public static function get_name() {
+        return get_string('eventtemplateupdated', 'mod_data');
+    }
+
+    /**
+     * Returns description of what happened.
+     *
+     * @return string
+     */
+    public function get_description() {
+        return 'The template for the database activity ' . $this->other['dataid'] . ' was updated by the user ' . $this->userid;
+    }
+
+    /**
+     * Get the legacy event log data.
+     *
+     * @return array
+     */
+    public function get_legacy_logdata() {
+        return array($this->courseid, 'data', 'templates saved', 'templates.php?id=' . $this->contextinstanceid .
+            '&amp;d=' . $this->other['dataid'], $this->other['dataid'], $this->contextinstanceid);
+    }
+
+    /**
+     * Custom validation.
+     *
+     * @throws \coding_exception when validation does not pass.
+     * @return void
+     */
+    protected function validate_data() {
+        parent::validate_data();
+
+        if (!isset($this->other['dataid'])) {
+            throw new \coding_exception('The dataid must be set in $other.');
+        }
+    }
+}
diff --git a/mod/data/classes/event/template_viewed.php b/mod/data/classes/event/template_viewed.php
new file mode 100644 (file)
index 0000000..bcacde9
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * The mod_data templates viewed event.
+ *
+ * @property-read array $other {
+ *      Extra information about event.
+ *
+ *      @type int dataid the id of the data activity.
+ * }
+ *
+ * @package    mod_data
+ * @copyright  2014 Mark Nelson <markn@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_data\event;
+
+defined('MOODLE_INTERNAL') || die();
+
+class template_viewed extends \core\event\base {
+
+    /**
+     * Init method.
+     *
+     * @return void
+     */
+    protected function init() {
+        $this->data['crud'] = 'r';
+        $this->data['edulevel'] = self::LEVEL_OTHER;
+    }
+
+    /**
+     * Return localised event name.
+     *
+     * @return string
+     */
+    public static function get_name() {
+        return get_string('eventtemplateviewed', 'mod_data');
+    }
+
+    /**
+     * Returns description of what happened.
+     *
+     * @return string
+     */
+    public function get_description() {
+        return 'The template for the database activity with the id ' . $this->other['dataid'] . ' was viewed by the ' .
+            'user with the id ' . $this->userid;
+    }
+
+    /**
+     * Get the legacy event log data.
+     *
+     * @return array
+     */
+    public function get_legacy_logdata() {
+        return array($this->courseid, 'data', 'templates view', 'templates.php?id=' . $this->contextinstanceid .
+            '&amp;d=' . $this->other['dataid'], $this->other['dataid'], $this->contextinstanceid);
+    }
+
+    /**
+     * Custom validation.
+     *
+     * @throws \coding_exception when validation does not pass.
+     * @return void
+     */
+    protected function validate_data() {
+        parent::validate_data();
+
+        if (!isset($this->other['dataid'])) {
+            throw new \coding_exception('The dataid must be set in $other.');
+        }
+    }
+}
index 13727ae..0f04530 100644 (file)
@@ -186,7 +186,17 @@ if ($datarecord = data_submitted() and confirm_sesskey()) {
             }
         }
 
-        add_to_log($course->id, 'data', 'update', "view.php?d=$data->id&amp;rid=$rid", $data->id, $cm->id);
+        // Trigger an event for updating this record.
+        $event = \mod_data\event\record_updated::create(array(
+            'objectid' => $rid,
+            'context' => $context,
+            'courseid' => $course->id,
+            'other' => array(
+                'dataid' => $data->id
+            )
+        ));
+        $event->add_record_snapshot('data', $data);
+        $event->trigger();
 
         redirect($CFG->wwwroot.'/mod/data/view.php?d='.$data->id.'&rid='.$rid);
 
@@ -236,8 +246,6 @@ if ($datarecord = data_submitted() and confirm_sesskey()) {
                 }
             }
 
-            add_to_log($course->id, 'data', 'add', "view.php?d=$data->id&amp;rid=$recordid", $data->id, $cm->id);
-
             if (!empty($datarecord->saveandview)) {
                 redirect($CFG->wwwroot.'/mod/data/view.php?d='.$data->id.'&rid='.$recordid);
             }
index a24d628..210311a 100644 (file)
@@ -121,9 +121,6 @@ switch ($mode) {
             /// Update some templates
                 data_append_new_field_to_templates($data, $fieldinput->name);
 
-                add_to_log($course->id, 'data', 'fields add',
-                           "field.php?d=$data->id&amp;mode=display&amp;fid=$fid", $fid, $cm->id);
-
                 $displaynoticegood = get_string('fieldadded','data');
             }
         }
@@ -163,9 +160,6 @@ switch ($mode) {
             /// Update the templates.
                 data_replace_field_in_templates($data, $oldfieldname, $field->field->name);
 
-                add_to_log($course->id, 'data', 'fields update',
-                           "field.php?d=$data->id&amp;mode=display&amp;fid=$fid", $fid, $cm->id);
-
                 $displaynoticegood = get_string('fieldupdated','data');
             }
         }
@@ -194,9 +188,6 @@ switch ($mode) {
                         $DB->update_record('data', $rec);
                     }
 
-                    add_to_log($course->id, 'data', 'fields delete',
-                               "field.php?d=$data->id", $field->field->name, $cm->id);
-
                     $displaynoticegood = get_string('fielddeleted', 'data');
                 }
 
index de7c74b..8620a34 100644 (file)
@@ -39,7 +39,11 @@ $PAGE->set_pagelayout('incourse');
 
 $context = context_course::instance($course->id);
 
-add_to_log($course->id, "data", "view all", "index.php?id=$course->id", "");
+$params = array(
+    'context' => context_course::instance($course->id)
+);
+$event = \mod_data\event\course_module_instance_list_viewed::create($params);
+$event->trigger();
 
 $strname = get_string('name');
 $strdata = get_string('modulename','data');
index d0d9110..919d5c0 100644 (file)
@@ -119,6 +119,14 @@ $string['editordisable'] = 'Disable editor';
 $string['editorenable'] = 'Enable editor';
 $string['emptyadd'] = 'The Add template is empty, generating a default form...';
 $string['emptyaddform'] = 'You did not fill out any fields!';
+$string['eventfieldcreated'] = 'Field created';
+$string['eventfielddeleted'] = 'Field deleted';
+$string['eventfieldupdated'] = 'Field updated';
+$string['eventrecordcreated'] = 'Record created';
+$string['eventrecorddeleted'] = 'Record deleted';
+$string['eventrecordupdated'] = 'Record updated';
+$string['eventtemplateupdated'] = 'Template updated';
+$string['eventtemplateviewed'] = 'Templates viewed';
 $string['fileencoding'] = 'Encoding';
 $string['entries'] = 'Entries';
 $string['entrieslefttoadd'] = 'You must add {$a->entriesleft} more entry/entries in order to complete this activity';
index 8123cc8..4bf3478 100644 (file)
@@ -188,6 +188,18 @@ class data_field_base {     // Base class for Database Field Types (see field/*/
         }
 
         $this->field->id = $DB->insert_record('data_fields',$this->field);
+
+        // Trigger an event for creating this field.
+        $event = \mod_data\event\field_created::create(array(
+            'objectid' => $this->field->id,
+            'context' => $this->context,
+            'other' => array(
+                'fieldname' => $this->field->name,
+                'dataid' => $this->data->id
+            )
+        ));
+        $event->trigger();
+
         return true;
     }
 
@@ -202,6 +214,18 @@ class data_field_base {     // Base class for Database Field Types (see field/*/
         global $DB;
 
         $DB->update_record('data_fields', $this->field);
+
+        // Trigger an event for updating this field.
+        $event = \mod_data\event\field_updated::create(array(
+            'objectid' => $this->field->id,
+            'context' => $this->context,
+            'other' => array(
+                'fieldname' => $this->field->name,
+                'dataid' => $this->data->id
+            )
+        ));
+        $event->trigger();
+
         return true;
     }
 
@@ -215,9 +239,25 @@ class data_field_base {     // Base class for Database Field Types (see field/*/
         global $DB;
 
         if (!empty($this->field->id)) {
+            // Get the field before we delete it.
+            $field = $DB->get_record('data_fields', array('id' => $this->field->id));
+
             $this->delete_content();
             $DB->delete_records('data_fields', array('id'=>$this->field->id));
+
+            // Trigger an event for deleting this field.
+            $event = \mod_data\event\field_deleted::create(array(
+                'objectid' => $this->field->id,
+                'context' => $this->context,
+                'other' => array(
+                    'fieldname' => $this->field->name,
+                    'dataid' => $this->data->id
+                 )
+            ));
+            $event->add_record_snapshot('data_fields', $field);
+            $event->trigger();
         }
+
         return true;
     }
 
@@ -802,7 +842,19 @@ function data_add_record($data, $groupid=0){
     } else {
         $record->approved = 0;
     }
-    return $DB->insert_record('data_records', $record);
+    $record->id = $DB->insert_record('data_records', $record);
+
+    // Trigger an event for creating this record.
+    $event = \mod_data\event\record_created::create(array(
+        'objectid' => $record->id,
+        'context' => $context,
+        'other' => array(
+            'dataid' => $data->id
+        )
+    ));
+    $event->trigger();
+
+    return $record->id;
 }
 
 /**
@@ -3684,7 +3736,18 @@ function data_delete_record($recordid, $data, $courseid, $cmid) {
                 $DB->delete_records('data_content', array('recordid'=>$deleterecord->id));
                 $DB->delete_records('data_records', array('id'=>$deleterecord->id));
 
-                add_to_log($courseid, 'data', 'record delete', "view.php?id=$cmid", $data->id, $cmid);
+                // Trigger an event for deleting this record.
+                $event = \mod_data\event\record_deleted::create(array(
+                    'objectid' => $deleterecord->id,
+                    'context' => context_module::instance($cmid),
+                    'courseid' => $courseid,
+                    'other' => array(
+                        'dataid' => $deleterecord->dataid
+                    )
+                ));
+                $event->add_record_snapshot('data_records', $deleterecord);
+                $event->trigger();
+
                 return true;
             }
         }
index 8adce53..237ec21 100644 (file)
@@ -73,8 +73,16 @@ if (!$DB->count_records('data_fields', array('dataid'=>$data->id))) {      // Br
     redirect($CFG->wwwroot.'/mod/data/field.php?d='.$data->id);  // Redirect to field entry
 }
 
-add_to_log($course->id, 'data', 'templates view', "templates.php?id=$cm->id&amp;d=$data->id", $data->id, $cm->id);
-
+// Trigger an event for viewing templates.
+$event = \mod_data\event\template_viewed::create(array(
+    'context' => $context,
+    'courseid' => $course->id,
+    'other' => array(
+        'dataid' => $data->id
+    )
+));
+$event->add_record_snapshot('data', $data);
+$event->trigger();
 
 /// Print the page header
 
@@ -136,7 +144,16 @@ if (($mytemplate = data_submitted()) && confirm_sesskey()) {
             if (empty($disableeditor) && empty($enableeditor)) {
                 $DB->update_record('data', $newtemplate);
                 echo $OUTPUT->notification(get_string('templatesaved', 'data'), 'notifysuccess');
-                add_to_log($course->id, 'data', 'templates saved', "templates.php?id=$cm->id&amp;d=$data->id", $data->id, $cm->id);
+
+                // Trigger an event for saving the templates.
+                $event = \mod_data\event\template_updated::create(array(
+                    'context' => $context,
+                    'courseid' => $course->id,
+                    'other' => array(
+                        'dataid' => $data->id,
+                    )
+                ));
+                $event->trigger();
             }
         }
     }
diff --git a/mod/data/tests/events_test.php b/mod/data/tests/events_test.php
new file mode 100644 (file)
index 0000000..2a5c375
--- /dev/null
@@ -0,0 +1,341 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Events tests.
+ *
+ * @package mod_data
+ * @category test
+ * @copyright 2014 Mark Nelson <markn@moodle.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+
+class mod_data_events_testcase extends advanced_testcase {
+
+    /**
+     * Test set up.
+     *
+     * This is executed before running any test in this file.
+     */
+    public function setUp() {
+        $this->resetAfterTest();
+    }
+
+    /**
+     * Test the field created event.
+     */
+    public function test_field_created() {
+        $this->setAdminUser();
+
+        // Create a course we are going to add a data module to.
+        $course = $this->getDataGenerator()->create_course();
+
+        // The generator used to create a data module.
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
+
+        // Create a data module.
+        $data = $generator->create_instance(array('course' => $course->id));
+
+        // Now we want to create a field.
+        $field = data_get_field_new('text', $data);
+        $fielddata = new stdClass();
+        $fielddata->name = 'Test';
+        $fielddata->description = 'Test description';
+        $field->define_field($fielddata);
+
+        // Trigger and capture the event for creating a field.
+        $sink = $this->redirectEvents();
+        $field->insert_field();
+        $events = $sink->get_events();
+        $event = reset($events);
+
+        // Check that the event data is valid.
+        $this->assertInstanceOf('\mod_data\event\field_created', $event);
+        $this->assertEquals(context_module::instance($data->cmid), $event->get_context());
+        $expected = array($course->id, 'data', 'fields add', 'field.php?d=' . $data->id . '&amp;mode=display&amp;fid=' .
+            $field->field->id, $field->field->id, $data->cmid);
+        $this->assertEventLegacyLogData($expected, $event);
+    }
+
+    /**
+     * Test the field updated event.
+     */
+    public function test_field_updated() {
+        $this->setAdminUser();
+
+        // Create a course we are going to add a data module to.
+        $course = $this->getDataGenerator()->create_course();
+
+        // The generator used to create a data module.
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
+
+        // Create a data module.
+        $data = $generator->create_instance(array('course' => $course->id));
+
+        // Now we want to create a field.
+        $field = data_get_field_new('text', $data);
+        $fielddata = new stdClass();
+        $fielddata->name = 'Test';
+        $fielddata->description = 'Test description';
+        $field->define_field($fielddata);
+        $field->insert_field();
+
+        // Trigger and capture the event for updating the field.
+        $sink = $this->redirectEvents();
+        $field->update_field();
+        $events = $sink->get_events();
+        $event = reset($events);
+
+        // Check that the event data is valid.
+        $this->assertInstanceOf('\mod_data\event\field_updated', $event);
+        $this->assertEquals(context_module::instance($data->cmid), $event->get_context());
+        $expected = array($course->id, 'data', 'fields update', 'field.php?d=' . $data->id . '&amp;mode=display&amp;fid=' .
+            $field->field->id, $field->field->id, $data->cmid);
+        $this->assertEventLegacyLogData($expected, $event);
+    }
+
+    /**
+     * Test the field deleted event.
+     */
+    public function test_field_deleted() {
+        $this->setAdminUser();
+
+        // Create a course we are going to add a data module to.
+        $course = $this->getDataGenerator()->create_course();
+
+        // The generator used to create a data module.
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
+
+        // Create a data module.
+        $data = $generator->create_instance(array('course' => $course->id));
+
+        // Now we want to create a field.
+        $field = data_get_field_new('text', $data);
+        $fielddata = new stdClass();
+        $fielddata->name = 'Test';
+        $fielddata->description = 'Test description';
+        $field->define_field($fielddata);
+        $field->insert_field();
+
+        // Trigger and capture the event for deleting the field.
+        $sink = $this->redirectEvents();
+        $field->delete_field();
+        $events = $sink->get_events();
+        $event = reset($events);
+
+        // Check that the event data is valid.
+        $this->assertInstanceOf('\mod_data\event\field_deleted', $event);
+        $this->assertEquals(context_module::instance($data->cmid), $event->get_context());
+        $expected = array($course->id, 'data', 'fields delete', 'field.php?d=' . $data->id, $field->field->name, $data->cmid);
+        $this->assertEventLegacyLogData($expected, $event);
+    }
+
+    /**
+     * Test the record created event.
+     */
+    public function test_record_created() {
+        // Create a course we are going to add a data module to.
+        $course = $this->getDataGenerator()->create_course();
+
+        // The generator used to create a data module.
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
+
+        // Create a data module.
+        $data = $generator->create_instance(array('course' => $course->id));
+
+        // Trigger and capture the event for creating the record.
+        $sink = $this->redirectEvents();
+        $recordid = data_add_record($data);
+        $events = $sink->get_events();
+        $event = reset($events);
+
+        // Check that the event data is valid.
+        $this->assertInstanceOf('\mod_data\event\record_created', $event);
+        $this->assertEquals(context_module::instance($data->cmid), $event->get_context());
+        $expected = array($course->id, 'data', 'add', 'view.php?d=' . $data->id . '&amp;rid=' . $recordid,
+            $data->id, $data->cmid);
+        $this->assertEventLegacyLogData($expected, $event);
+    }
+
+    /**
+     * Test the record updated event.
+     *
+     * There is no external API for updating a record, so the unit test will simply create
+     * and trigger the event and ensure the legacy log data is returned as expected.
+     */
+    public function test_record_updated() {
+        // Create a course we are going to add a data module to.
+        $course = $this->getDataGenerator()->create_course();
+
+        // The generator used to create a data module.
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
+
+        // Create a data module.
+        $data = $generator->create_instance(array('course' => $course->id));
+
+        // Trigger an event for updating this record.
+        $event = \mod_data\event\record_updated::create(array(
+            'objectid' => 1,
+            'context' => context_module::instance($data->cmid),
+            'courseid' => $course->id,
+            'other' => array(
+                'dataid' => $data->id
+            )
+        ));
+
+        // Trigger and capture the event for updating the data record.
+        $sink = $this->redirectEvents();
+        $event->trigger();
+        $events = $sink->get_events();
+        $event = reset($events);
+
+        // Check that the event data is valid.
+        $this->assertInstanceOf('\mod_data\event\record_updated', $event);
+        $this->assertEquals(context_module::instance($data->cmid), $event->get_context());
+        $expected = array($course->id, 'data', 'update', 'view.php?d=' . $data->id . '&amp;rid=1', $data->id, $data->cmid);
+        $this->assertEventLegacyLogData($expected, $event);
+    }
+
+    /**
+     * Test the record deleted event.
+     */
+    public function test_record_deleted() {
+        global $DB;
+
+        // Create a course we are going to add a data module to.
+        $course = $this->getDataGenerator()->create_course();
+
+        // The generator used to create a data module.
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
+
+        // Create a data module.
+        $data = $generator->create_instance(array('course' => $course->id));
+
+        // Now we want to create a field.
+        $field = data_get_field_new('text', $data);
+        $fielddata = new stdClass();
+        $fielddata->name = 'Test';
+        $fielddata->description = 'Test description';
+        $field->define_field($fielddata);
+        $field->insert_field();
+
+        // Create data record.
+        $datarecords = new stdClass();
+        $datarecords->userid = '2';
+        $datarecords->dataid = $data->id;
+        $datarecords->id = $DB->insert_record('data_records', $datarecords);
+
+        // Create data content.
+        $datacontent = new stdClass();
+        $datacontent->fieldid = $field->field->id;
+        $datacontent->recordid = $datarecords->id;
+        $datacontent->id = $DB->insert_record('data_content', $datacontent);
+
+        // Trigger and capture the event for deleting the data record.
+        $sink = $this->redirectEvents();
+        data_delete_record($datarecords->id, $data, $course->id, $data->cmid);
+        $events = $sink->get_events();
+        $event = reset($events);
+
+        // Check that the event data is valid.
+        $this->assertInstanceOf('\mod_data\event\record_deleted', $event);
+        $this->assertEquals(context_module::instance($data->cmid), $event->get_context());
+        $expected = array($course->id, 'data', 'record delete', 'view.php?id=' . $data->cmid, $data->id, $data->cmid);
+        $this->assertEventLegacyLogData($expected, $event);
+    }
+
+    /**
+     * Test the template viewed event.
+     *
+     * There is no external API for viewing templates, so the unit test will simply create
+     * and trigger the event and ensure the legacy log data is returned as expected.
+     */
+    public function test_template_viewed() {
+        // Create a course we are going to add a data module to.
+        $course = $this->getDataGenerator()->create_course();
+
+        // The generator used to create a data module.
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
+
+        // Create a data module.
+        $data = $generator->create_instance(array('course' => $course->id));
+
+        // Trigger an event for updating this record.
+        $event = \mod_data\event\template_viewed::create(array(
+            'context' => context_module::instance($data->cmid),
+            'courseid' => $course->id,
+            'other' => array(
+                'dataid' => $data->id
+            )
+        ));
+
+        // Trigger and capture the event for updating the data record.
+        $sink = $this->redirectEvents();
+        $event->trigger();
+        $events = $sink->get_events();
+        $event = reset($events);
+
+        // Check that the event data is valid.
+        $this->assertInstanceOf('\mod_data\event\template_viewed', $event);
+        $this->assertEquals(context_module::instance($data->cmid), $event->get_context());
+        $expected = array($course->id, 'data', 'templates view', 'templates.php?id=' . $data->cmid . '&amp;d=' .
+            $data->id, $data->id, $data->cmid);
+        $this->assertEventLegacyLogData($expected, $event);
+    }
+
+    /**
+     * Test the template updated event.
+     *
+     * There is no external API for updating a template, so the unit test will simply create
+     * and trigger the event and ensure the legacy log data is returned as expected.
+     */
+    public function test_template_updated() {
+        // Create a course we are going to add a data module to.
+        $course = $this->getDataGenerator()->create_course();
+
+        // The generator used to create a data module.
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
+
+        // Create a data module.
+        $data = $generator->create_instance(array('course' => $course->id));
+
+        // Trigger an event for updating this record.
+        $event = \mod_data\event\template_updated::create(array(
+            'context' => context_module::instance($data->cmid),
+            'courseid' => $course->id,
+            'other' => array(
+                'dataid' => $data->id,
+            )
+        ));
+
+        // Trigger and capture the event for updating the data record.
+        $sink = $this->redirectEvents();
+        $event->trigger();
+        $events = $sink->get_events();
+        $event = reset($events);
+
+        // Check that the event data is valid.
+        $this->assertInstanceOf('\mod_data\event\template_updated', $event);
+        $this->assertEquals(context_module::instance($data->cmid), $event->get_context());
+        $expected = array($course->id, 'data', 'templates saved', 'templates.php?id=' . $data->cmid . '&amp;d=' .
+            $data->id, $data->id, $data->cmid);
+        $this->assertEventLegacyLogData($expected, $event);
+    }
+}
index 557ce4e..1454f90 100644 (file)
         set_user_preference('data_perpage_'.$data->id, $perpage);
     }
 
-    add_to_log($course->id, 'data', 'view', "view.php?id=$cm->id", $data->id, $cm->id);
-
+    $params = array(
+        'context' => $context,
+        'objectid' => $data->id
+    );
+    $event = \mod_data\event\course_module_viewed::create($params);
+    $event->add_record_snapshot('data', $data);
+    $event->trigger();
 
     $urlparams = array('d' => $data->id);
     if ($record) {
index fac06f4..97c9428 100644 (file)
@@ -160,7 +160,7 @@ $PAGE->set_title($feedback->name);
 
 //Adding the javascript module for the items dragdrop.
 if (count($feedbackitems) > 1) {
-    if ($do_show == 'edit' and $CFG->enableajax) {
+    if ($do_show == 'edit') {
         $PAGE->requires->strings_for_js(array(
                'pluginname',
                'move_item',
index b9655a7..aeb68e0 100644 (file)
@@ -18,8 +18,7 @@
 /**
  * Provides support for the conversion of moodle1 backup to the moodle2 format
  *
- * @package    mod
- * @subpackage folder
+ * @package    mod_folder
  * @copyright  2011 Andrew Davis <andrew@moodle.com>
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
index 8c6e636..eb40ca3 100644 (file)
 /**
  * Defines backup_folder_activity_task class
  *
- * @package     mod_folder
- * @category    backup
- * @copyright   2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
- * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package   mod_folder
+ * @category  backup
+ * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 defined('MOODLE_INTERNAL') || die();
index e9f593c..0fdd959 100644 (file)
 /**
  * Define all the backup steps that will be used by the backup_folder_activity_task
  *
- * @package    mod
- * @subpackage folder
- * @copyright  2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package   mod_folder
+ * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 defined('MOODLE_INTERNAL') || die();
index 3367948..48f50d2 100644 (file)
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 /**
- * @package moodlecore
+ * @package    mod_folder
  * @subpackage backup-moodle2
- * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @copyright  2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 defined('MOODLE_INTERNAL') || die();
index 052f81b..450f882 100644 (file)
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 /**
- * @package moodlecore
+ * @package    mod_folder
  * @subpackage backup-moodle2
- * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @copyright  2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 /**
index 19842e9..3c5f980 100644 (file)
  *   - lib.php/modulename_install() post installation hook
  *   - partially defaults.php
  *
- * @package    mod
- * @subpackage folder
- * @copyright  2009 Petr Skoda  {@link http://skodak.org}
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package   mod_folder
+ * @copyright 2009 Petr Skoda  {@link http://skodak.org}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 defined('MOODLE_INTERNAL') || die();
index 78ce2ea..7638e06 100644 (file)
  * Please do not forget to use upgrade_set_timeout()
  * before any action that may take longer time to finish.
  *
- * @package    mod
- * @subpackage folder
- * @copyright  2009 Petr Skoda  {@link http://skodak.org}
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package   mod_folder
+ * @copyright 2009 Petr Skoda  {@link http://skodak.org}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 defined('MOODLE_INTERNAL') || die();
index cec41ce..666e3fe 100644 (file)
 /**
  * Manage files in folder module instance
  *
- * @package    mod
- * @subpackage folder
- * @copyright  2010 Dongsheng Cai <dongsheng@moodle.com>
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package   mod_folder
+ * @copyright 2010 Dongsheng Cai <dongsheng@moodle.com>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 require('../../config.php');
index 309ae9f..90e018f 100644 (file)
 /**
  * A moodle form to manage folder files
  *
- * @package    mod
- * @subpackage folder
- * @copyright  2010 Dongsheng Cai <dongsheng@moodle.com>
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package   mod_folder
+ * @copyright 2010 Dongsheng Cai <dongsheng@moodle.com>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 defined('MOODLE_INTERNAL') || die();
index ea4a111..e28c99e 100644 (file)
 /**
  * List of file folders in course
  *
- * @package    mod
- * @subpackage folder
- * @copyright  2009 onwards Martin Dougiamas (http://dougiamas.com)
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package   mod_folder
+ * @copyright 2009 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 require('../../config.php');
index 6d94818..5a42a15 100644 (file)
 /**
  * Strings for component 'folder', language 'en', branch 'MOODLE_20_STABLE'
  *
- * @package    mod
- * @subpackage folder
- * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package   mod_folder
+ * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 $string['contentheader'] = 'Content';
index a1ed5fd..030c7e5 100644 (file)
 /**
  * Mandatory public API of folder module
  *
- * @package    mod
- * @subpackage folder
- * @copyright  2009 Petr Skoda  {@link http://skodak.org}
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package   mod_folder
+ * @copyright 2009 Petr Skoda  {@link http://skodak.org}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 defined('MOODLE_INTERNAL') || die();
index abf5ead..e59e516 100644 (file)
 /**
  * Private folder module utility functions
  *
- * @package    mod
- * @subpackage folder
- * @copyright  2009 Petr Skoda  {@link http://skodak.org}
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package   mod_folder
+ * @copyright 2009 Petr Skoda  {@link http://skodak.org}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 defined('MOODLE_INTERNAL') || die();
index 61fb49b..a5f96f7 100644 (file)
 /**
  * Folder configuration form
  *
- * @package    mod
- * @subpackage folder
- * @copyright  2009 Petr Skoda  {@link http://skodak.org}
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package   mod_folder
+ * @copyright 2009 Petr Skoda  {@link http://skodak.org}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 defined('MOODLE_INTERNAL') || die();
index c0faeb1..cf31a3d 100644 (file)
 /**
  * Folder module renderer
  *
- * @package    mod
- * @subpackage folder
- * @copyright  2009 Petr Skoda  {@link http://skodak.org}
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package   mod_folder
+ * @copyright 2009 Petr Skoda  {@link http://skodak.org}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 defined('MOODLE_INTERNAL') || die();
 
index 6ed8b4a..6178634 100644 (file)
 /**
  * Folder module admin settings and defaults
  *
- * @package    mod
- * @subpackage folder
- * @copyright  2009 Petr Skoda  {@link http://skodak.org}
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package   mod_folder
+ * @copyright 2009 Petr Skoda  {@link http://skodak.org}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 defined('MOODLE_INTERNAL') || die;
index 2d32c95..1bcb716 100644 (file)
 /**
  * Folder module version information
  *
- * @package    mod
- * @subpackage folder
- * @copyright  2009 Petr Skoda  {@link http://skodak.org}
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package   mod_folder
+ * @copyright 2009 Petr Skoda  {@link http://skodak.org}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 defined('MOODLE_INTERNAL') || die();
index abd195e..a30cbf0 100644 (file)
 /**
  * Folder module main user interface
  *
- * @package    mod
- * @subpackage folder
- * @copyright  2009 Petr Skoda  {@link http://skodak.org}
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package   mod_folder
+ * @copyright 2009 Petr Skoda  {@link http://skodak.org}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 require('../../config.php');
index 0943a97..61a2b01 100644 (file)
@@ -18,8 +18,7 @@
 /**
  * Provides support for the conversion of moodle1 backup to the moodle2 format
  *
- * @package    mod
- * @subpackage forum
+ * @package    mod_forum
  * @copyright  2011 Mark Nielsen <mark@moodlerooms.com>
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */