ajaxlib/require_js: MDL-16693 $PAGE->requires->... deprecates require_js etc.
authortjhunt <tjhunt>
Fri, 12 Jun 2009 12:13:07 +0000 (12:13 +0000)
committertjhunt <tjhunt>
Fri, 12 Jun 2009 12:13:07 +0000 (12:13 +0000)
There is a new implementation of require_js in lib/deprecatedlib.php,
based on $PAGE->requires.

There were a few other recently introduced functions in lib/weblib.php,
namely print_js_call, print_delayed_js_call, print_js_config and
standard_js_config. These have been removed, since they were never in
a stable branch, and all the places that used them have been changed
to use the newer $PAGE->requires->... methods.

get_require_js_code is also gone, and the evil places that were calling
it, even though it is an internal function, have been fixed.

Also, I made some minor improvements to the code I committed yesterday
for MDL-16695.

All that remains is to update all the places in core code that are
still using require_js.

(This commit also fixes the problem where the admin tree would not
start with the right categories expanded.)

36 files changed:
admin/report/capability/index.php
admin/report/spamcleaner/index.php
admin/roles/assign.php
admin/roles/lib.php
admin/xmldb/javascript.php
blocks/admin_tree/block_admin_tree.php
calendar/lib.php
course/completion.js
course/view.php
group/members.php
lib/ajax/ajaxlib.php
lib/ajax/simpletest/testajaxlib.php
lib/deprecatedlib.php
lib/filelib.php
lib/form/dateselector.php
lib/form/datetimeselector.php
lib/formslib.php
lib/moodlelib.php
lib/pagelib.php
lib/questionlib.php
lib/recaptchalib.php
lib/weblib.php
message/refresh.php
mod/chat/gui_ajax/index.php
mod/forum/lib.php
mod/quiz/accessrules.php
mod/quiz/attempt.php
mod/quiz/attemptlib.php
mod/quiz/edit.php
mod/quiz/quiz.js
mod/quiz/review.php
question/editlib.php
question/export.php
question/type/questiontype.php
repository/lib.php
user/selector/lib.php

index 1a6aab4..7256f8b 100644 (file)
@@ -38,8 +38,9 @@ if (empty($cleanedroleids)) {
 }
 
 // Include the required JavaScript.
-require_js(array('yui_yahoo','yui_event'));
-require_js('admin/report/capability/script.js');
+$PAGE->requires->yui_lib('event');
+$PAGE->requires->js('admin/report/capability/script.js');
+$PAGE->requires->js_function_call('capability_report.cap_filter_init', array(get_string('search')));
 
 // Log.
 add_to_log(SITEID, "admin", "report capability", "report/capability/index.php?capability=$capability", $capability);
@@ -77,7 +78,6 @@ choose_from_menu($capabilitychoices, 'capability', $capability, 'choose', '', ''
 echo '<p><label for="menuroles"> ' . get_string('roleslabel', 'report_capability') . '</label></p>';
 choose_from_menu($rolechoices, 'roles[]', $selectedroleids, '', '', '', false, false, 0, '', true, true);
 echo '<p><input type="submit" id="settingssubmit" value="' . get_string('getreport', 'report_capability') . '" /></p>';
-print_js_call('capability_report.cap_filter_init', array(get_string('search')));
 echo '</form>';
 print_box_end();
 
index 7bd2d36..d9eb693 100755 (executable)
@@ -32,8 +32,6 @@ $autokeywords = array(
 require_once('../../../config.php');
 require_once($CFG->libdir.'/adminlib.php');
 
-require_js(array('yui_dom-event', 'yui_connection', 'yui_json'));
-
 $keyword = optional_param('keyword', '', PARAM_RAW);
 $autodetect = optional_param('autodetect', '', PARAM_RAW);
 $del = optional_param('del', '', PARAM_RAW);
@@ -44,6 +42,8 @@ $id = optional_param('id', '', PARAM_INT);
 
 require_login();
 admin_externalpage_setup('reportspamcleaner');
+$PAGE->requires->yui_lib('json');
+$PAGE->requires->yui_lib('connection');
 
 // Implement some AJAX calls 
 
index daa5d26..afcb700 100755 (executable)
@@ -32,8 +32,6 @@
 
     require_once(dirname(__FILE__) . '/../../config.php');
     require_once($CFG->dirroot . '/' . $CFG->admin . '/roles/lib.php');
-    require_js(array('yui_yahoo', 'yui_dom', 'yui_event'));
-    require_js($CFG->admin . '/roles/roles.js');
 
     define("MAX_USERS_TO_LIST_PER_ROLE", 10);
 
     }
 
 /// Print the header and tabs
+    $PAGE->requires->yui_lib('dom-event');
+    $PAGE->requires->js($CFG->admin . '/roles/roles.js');
     if ($context->contextlevel == CONTEXT_USER) {
         $user = $DB->get_record('user', array('id'=>$userid));
         $fullname = fullname($user, has_capability('moodle/site:viewfullnames', $context));
 </div></form>
 
 <?php
-        print_js_call('init_add_assign_page');
+        $PAGE->requires->js_function_call('init_add_assign_page');
 
         if (!empty($errors)) {
             $msg = '<p>';
index d59a418..5aec111 100644 (file)
@@ -121,10 +121,10 @@ abstract class capability_table_base {
     /// End of the table.
             echo "</tbody>\n</table>\n";
             if (count($this->capabilities) > capability_table_base::NUM_CAPS_FOR_SEARCH) {
-                global $CFG;
-                require_js(array('yui_yahoo', 'yui_dom', 'yui_event'));
-                require_js($CFG->admin . '/roles/roles.js');
-                print_js_call('cap_table_filter.init',
+                global $CFG, $PAGE;
+                $PAGE->requires->yui_lib('dom-event');
+                $PAGE->requires->js($CFG->admin . '/roles/roles.js');
+                $PAGE->requires->js_function_call('cap_table_filter.init',
                         array($this->id, get_string('filter'), get_string('clear')));
             }
     }
index d7b986f..483eec1 100644 (file)
     }
 
 /// We use this globals to be able to generate the proper JavaScripts
-    global $standard_javascript;
+    global $standard_javascript, $PAGE;
 
 /// Load XMLDB javascript needed to handle some forms
     $action = optional_param('action', '', PARAM_ALPHAEXT);
     $postaction = optional_param('postaction', '', PARAM_ALPHAEXT);
 /// If the js exists, load it
     if ($action) {
-        $file    = $CFG->dirroot . '/'.$CFG->admin.'/xmldb/actions/' . $action . '/' . $action . '.js';
-        $wwwfile = $CFG->wwwroot . '/'.$CFG->admin.'/xmldb/actions/' . $action . '/' . $action . '.js';
+        $script = $CFG->admin . '/xmldb/actions/' . $action . '/' . $action . '.js';
+        $file = $CFG->dirroot . '/' . $script;
         if (file_exists($file) && is_readable($file)) {
-            require_js($wwwfile);
-        } else {
+            $PAGE->requires->js($script);
+        } else if ($postaction) {
         /// Try to load the postaction javascript if exists
-            if ($postaction) {
-                $file    = $CFG->dirroot . '/'.$CFG->admin.'/xmldb/actions/' . $postaction . '/' . $postaction . '.js';
-                $wwwfile = $CFG->wwwroot . '/'.$CFG->admin.'/xmldb/actions/' . $postaction . '/' . $postaction . '.js';
-                if (file_exists($file) && is_readable($file)) {
-                    require_js($wwwfile);
-                }
+            $script = $CFG->admin . '/xmldb/actions/' . $postaction . '/' . $postaction . '.js';
+            $file = $CFG->dirroot . '/' . $script;
+            if (file_exists($file) && is_readable($file)) {
+                $PAGE->requires->js($script);
             }
         }
     }
index 5ac22c0..79551eb 100644 (file)
@@ -5,9 +5,10 @@ class block_admin_tree extends block_base {
     var $currentdepth;
     var $divcounter;
     var $tempcontent;
-    var $pathtosection;
-    var $expandjavascript;
     var $destination;
+    var $section = null;
+    var $pathtosection = array();
+    var $expandnodes = array();
 
     function init() {
         $this->title = get_string('administrationsite');
@@ -15,10 +16,8 @@ class block_admin_tree extends block_base {
         $this->currentdepth = 0;
         $this->divcounter = 1;
         $this->tempcontent = '';
-        // TODO
-        $this->section = (isset($this->page->section) ? $this->page->section : '');
-        $this->pathtosection = array();
-        $this->expandnodes = array();
+        global $PAGE; // TODO change this when there is a proper way for blocks to get stuff into head.
+        $PAGE->requires->yui_lib('event');
     }
 
     function applicable_formats() {
@@ -119,6 +118,7 @@ class block_admin_tree extends block_base {
         require_once($CFG->libdir.'/adminlib.php');
         $adminroot = admin_get_root(false, false); // settings not required - only pages
 
+        $this->section = $this->page->url->param('section');
         if ($current = $adminroot->locate($this->section, true)) {
             $this->pathtosection = $current->path;
             array_pop($this->pathtosection);
@@ -133,13 +133,13 @@ class block_admin_tree extends block_base {
         }
 
         if ($this->tempcontent !== '') {
-            require_js(array('yui_yahoo','yui_event'));
-            require_js('blocks/admin_tree/admintree.js');
+            $this->page->requires->js('blocks/admin_tree/admintree.js');
+            $this->page->requires->js_function_call('admin_tree.init',
+                    array($this->divcounter - 1, $this->expandnodes, $CFG->pixpath,
+                    get_string('folderopened'), get_string('folderclosed')));
+
             $this->content = new object();
             $this->content->text = '<div class="admintree">' . $this->tempcontent . "</div>\n";
-            $this->content->text .= print_js_call('admin_tree.init',
-                    array($this->divcounter - 1, $this->expandnodes, $CFG->pixpath,
-                    get_string('folderopened'), get_string('folderclosed')), true);
 
             // only do search if you have moodle/site:config
             if (has_capability('moodle/site:config',get_context_instance(CONTEXT_SYSTEM)) ) {
index b784147..37d890f 100644 (file)
@@ -1178,8 +1178,11 @@ function calendar_session_vars($course=null) {
 }
 
 function calendar_overlib_html() {
-    require_js('calendar/overlib.cfg.php');
-    return '<div id="overDiv" style="position: absolute; visibility: hidden; z-index:1000;"></div>';
+    global $PAGE;
+    $output = '';
+    $output .= $PAGE->requires->js('calendar/overlib.cfg.php')->asap();
+    $output .= '<div id="overDiv" style="position: absolute; visibility: hidden; z-index:1000;"></div>';
+    return $output;
 }
 
 function calendar_set_referring_course($courseid) {
index 0651343..a593f44 100644 (file)
@@ -1,7 +1,3 @@
-var completion_strsaved, completion_strtitley, completion_strtitlen, 
-  completion_stralty, completion_straltn;
-var completion_wwwroot;
-
 function completion_init() {
   // Check the reload-forcing
   var changeDetector=document.getElementById('completion_dynamic_change');
@@ -90,9 +86,7 @@ function completion_toggle(e) {
   YAHOO.util.Event.preventDefault(e);
   // By setting completion_wwwroot you can cause it to use absolute path 
   // otherwise script assumes it is called from somewhere in /course
-  var target=completion_wwwroot 
-    ? completion_wwwroot+'/course/togglecompletion.php' 
-    : 'togglecompletion.php';
+  var target = moodle_cfg.wwwroot + '/course/togglecompletion.php';
   YAHOO.util.Connect.asyncRequest('POST',target,
       {success:completion_handle_response,failure:completion_handle_failure,scope:this},
       'id='+this.cmid+'&completionstate='+this.otherState+'&fromajax=1');
index 478a0b0..54dae4d 100644 (file)
                                                              // Course-based switches
 
             if (ajaxenabled($CFG->ajaxtestedbrowsers)) {     // Browser, user and site-based switches
-                
-                require_js(array('yui_yahoo',
-                                 'yui_dom',
-                                 'yui_event',
-                                 'yui_dragdrop',
-                                 'yui_connection',
-                                 'ajaxcourse_blocks',
-                                 'ajaxcourse_sections'));
-                
-                if (debugging('', DEBUG_DEVELOPER)) {
-                    require_js(array('yui_logger'));
-
-                    $bodytags = 'onload = "javascript:
-                    show_logger = function() {
-                        var logreader = new YAHOO.widget.LogReader();
-                        logreader.newestOnTop = false;
-                        logreader.setTitle(\'Moodle Debug: YUI Log Console\');
-                    };
-                    show_logger();
-                    "';
-                }
+                $PAGE->requires->yui_lib('dragdrop');
+                $PAGE->requires->yui_lib('connection');
+                $PAGE->requires->js('lib/ajax/block_classes.js');
+                $PAGE->requires->js('lib/ajax/section_classes.js');
 
                 // Okay, global variable alert. VERY UGLY. We need to create
                 // this object here before the <blockname>_print_block()
 
     $CFG->blocksdrag = $useajax;   // this will add a new class to the header so we can style differently
 
+    $completion = new completion_info($course);
+    if ($completion->is_enabled() && ajaxenabled()) {
+        $PAGE->requires->yui_lib('connection');
+        $PAGE->requires->js('course/completion.js');
+        $PAGE->requires->data_for_js('completion_strsaved', get_string('saved', 'completion'));
+        $PAGE->requires->data_for_js('completion_strtitley', get_string('completion-title-manual-y', 'completion'));
+        $PAGE->requires->data_for_js('completion_strtitlen', get_string('completion-title-manual-n', 'completion'));
+        $PAGE->requires->data_for_js('completion_stralty', get_string('completion-alt-manual-y', 'completion'));
+        $PAGE->requires->data_for_js('completion_straltn', get_string('completion-alt-manual-n', 'completion'));
+    }
+
     // The "Editing On" button will be appearing only in the "main" course screen
     // (i.e., no breadcrumbs other than the default one added inside this function)
     $buttons = switchroles_form($course->id);
     print_header($title, $course->fullname, $navigation, '', '', true,
                  $buttons, user_login_string($course, $USER), false, $bodytags);
 
-    $completion=new completion_info($course);
-    if($completion->is_enabled() && ajaxenabled()) {
-        require_js(array('yui_yahoo','yui_event','yui_connection','yui_dom'));
-        // Need to do this after the header because it requires the YUI stuff
-        // to be loaded already
-        require_js('course/completion.js');
-        print_js_config(array(
-            'completion_strsaved' => get_string('saved','completion'),
-            'completion_strtitley' => get_string('completion-title-manual-y','completion'),
-            'completion_strtitlen' => get_string('completion-title-manual-n','completion'),
-            'completion_stralty' => get_string('completion-alt-manual-y','completion'),
-            'completion_straltn' => get_string('completion-alt-manual-n','completion'),
-        ));
+    if ($completion->is_enabled() && ajaxenabled()) {
         // 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 12fbcf6..fe2a2a8 100644 (file)
@@ -12,7 +12,6 @@ require_once(dirname(__FILE__) . '/../config.php');
 require_once(dirname(__FILE__) . '/lib.php');
 require_once($CFG->dirroot . '/user/selector/lib.php');
 require_once($CFG->dirroot . '/course/lib.php');
-require_js('group/clientlib.js');
 
 $groupid = required_param('group', PARAM_INT);
 
@@ -82,6 +81,8 @@ $navlinks[] = array('name' => $strgroups, 'link' => "$CFG->wwwroot/group/index.p
 $navlinks[] = array('name' => $stradduserstogroup, 'link' => null, 'type' => 'misc');
 $navigation = build_navigation($navlinks);
 
+$PAGE->requires->js('group/clientlib.js');
+$PAGE->requires->js_function_call('init_add_remove_members_page');
 print_header("$course->shortname: $strgroups", $course->fullname, $navigation, '', '', true, '', user_login_string($course, $USER));
 check_theme_arrows();
 ?>
@@ -123,6 +124,5 @@ check_theme_arrows();
 </div>
 
 <?php
-    print_js_call('init_add_remove_members_page');
     print_footer($course);
 ?>
index e0aeaa2..da07735 100644 (file)
@@ -49,6 +49,10 @@ function setup_core_javascript(page_requirements_manager $requires) {
     }
     $requires->data_for_js('moodle_cfg', $config)->in_head();
 
+    if (debugging('', DEBUG_DEVELOPER)) {
+        $requires->yui_lib('logger');
+    }
+
     // Note that, as a short-cut, the code 
     // $js = "document.body.className += ' jsenabled';\n";
     // is hard-coded in @see{page_requirements_manager::get_top_of_body_code}.
@@ -95,6 +99,10 @@ class page_requirements_manager {
      * @param $jsfile The path to the .js file, relative to $CFG->dirroot / $CFG->wwwroot.
      *      No leading slash. For example 'mod/mymod/customscripts.js';
      * @param boolean $fullurl This parameter is intended for internal use only.
+     *      However, in exceptional circumstances you may wish to use it to link
+     *      to JavaScript on another server. For example, lib/recaptchalib.php has to
+     *      do this. This really should only be done in exceptional circumstances. This
+     *      may change in the future without warning.
      *      (If true, $jsfile is treaded as a full URL, not relative $CFG->wwwroot.)
      * @return required_js A required_js object. This allows you to control when the
      *      link to the script is output by calling methods like ->asap() or
@@ -125,6 +133,8 @@ class page_requirements_manager {
      *
      * If the YUI library you ask for requires one or more CSS files, and if
      * &lt;head> has already been printed, then an exception will be thrown.
+     * Therefore, you are strongly advised to request all the YUI libraries you
+     * will need before the call to print_header.
      *
      * Even if a particular library is requested more than once (perhaps as a dependancy
      * of other libraries) it will only be linked to once.
@@ -162,7 +172,7 @@ class page_requirements_manager {
         global $CFG;
 
         if ($this->headdone) {
-            throw new coding_exception('Cannot require a CSS file after <head> has been printed.', $stylesheet);
+            throw new coding_exception('Cannot require a CSS file after &lt;head> has been printed.', $stylesheet);
         }
         if (!$fullurl) {
             if (!file_exists($CFG->dirroot . '/' . $stylesheet)) {
@@ -207,14 +217,15 @@ class page_requirements_manager {
      * one link will be output).
      *
      * @param string $function the name of the JavaScritp function to call. Can
-     *      be a compound name like 'YAHOO.util.Event.addListener'.
+     *      be a compound name like 'YAHOO.util.Event.addListener'. Can also be
+     *      used to create and object by using a 'function name' like 'new user_selector'.
      * @param array $arguments and array of arguments to be passed to the function.
      *      When generating the function call, this will be escaped using json_encode,
      *      so passing objects and arrays should work.
      * @return required_js_function_call A required_js_function_call object.
      *      This allows you to control when the link to the script is output by
-     *      calling methods like ->asap(), ->in_head(), ->at_top_of_body() or
-     *      ->on_dom_ready() methods.
+     *      calling methods like ->asap(), ->in_head(), ->at_top_of_body(),
+     *      ->on_dom_ready() or ->after_delay() methods.
      */
     public function js_function_call($function, $arguments = array()) {
         $requirement = new required_js_function_call($this, $function, $arguments);
@@ -324,6 +335,7 @@ class page_requirements_manager {
      * @return string the HTML code to to inside the &lt;head> tag.
      */
     public function get_head_code() {
+        setup_core_javascript($this);
         $output = $this->get_linked_resources_code(self::WHEN_IN_HEAD);
         $js = $this->get_javascript_code(self::WHEN_IN_HEAD);
         $output .= ajax_generate_script_tag($js);
@@ -353,7 +365,10 @@ class page_requirements_manager {
     public function get_end_code() {
         $output = $this->get_linked_resources_code(self::WHEN_AT_END);
 
-        array_unshift($this->requiredjscode, new required_data_for_js($this, 'mstr', $this->stringsforjs));
+        if (!empty($this->stringsforjs)) {
+            array_unshift($this->requiredjscode, new required_data_for_js($this, 'mstr', $this->stringsforjs));
+        }
+
         $js = $this->get_javascript_code(self::WHEN_AT_END);
 
         $ondomreadyjs = $this->get_javascript_code(self::WHEN_ON_DOM_READY, '    ');
@@ -502,7 +517,7 @@ class required_js extends linked_requirement {
     }
 
     public function get_html() {
-        return '<script type="text/javascript"  src="' . $this->url . '"></script>' . "\n";
+        return ajax_get_link_to_script($this->url);
     }
 
     /**
@@ -591,7 +606,6 @@ class required_js extends linked_requirement {
  */
 class required_yui_lib extends linked_requirement {
     protected $jss = array();
-    protected $cssurls;
 
     /**
      * Constructor. Normally instances of this class should not be created
@@ -606,16 +620,12 @@ class required_yui_lib extends linked_requirement {
         parent::__construct($manager, '');
         $this->when = page_requirements_manager::WHEN_AT_END;
 
-        list($jsurls, $this->cssurls) = ajax_resolve_yui_lib($libname);
+        list($jsurls, $cssurls) = ajax_resolve_yui_lib($libname);
         foreach ($jsurls as $jsurl) {
             $this->jss[] = $manager->js($jsurl, true);
         }
-        foreach ($this->cssurls as $cssurl) {
-            $manager->css($cssurl, true);
-        }
-        if (!empty($this->cssurls)) {
-            global $PAGE;
-            $page->add_body_class('yui-skin-sam');
+        foreach ($cssurls as $cssurl) {
+            //$manager->css($cssurl, true);
         }
     }
 
@@ -645,7 +655,7 @@ class required_yui_lib extends linked_requirement {
 
         $ouput = '';
         foreach ($this->jss as $requiredjs) {
-            $ouput .= $requiredjs->immediately();
+            $ouput .= $requiredjs->asap();
         }
         $this->mark_done();
         return $ouput;
@@ -667,7 +677,7 @@ class required_yui_lib extends linked_requirement {
 
         $this->when = page_requirements_manager::WHEN_IN_HEAD;
         foreach ($this->jss as $requiredjs) {
-            $ouput .= $requiredjs->in_head();
+            $requiredjs->in_head();
         }
     }
 
@@ -850,6 +860,7 @@ abstract class required_js_code extends requirement_base {
 class required_js_function_call extends required_js_code {
     protected $function;
     protected $arguments;
+    protected $delay = 0;
 
     /**
      * Constructor. Normally the class and its subclasses should not be created
@@ -874,7 +885,11 @@ class required_js_function_call extends required_js_code {
         foreach ($this->arguments as $arg) {
             $quotedargs[] = json_encode($arg);
         }
-        return $this->function . '(' . implode(', ', $quotedargs) . ");\n";
+        $js = $this->function . '(' . implode(', ', $quotedargs) . ');';
+        if ($this->delay) {
+            $js = 'setTimeout(function() { ' . $js . ' }, ' . ($this->delay * 1000) . ');';
+        }
+        return $js . "\n";
     }
 
     /**
@@ -890,6 +905,20 @@ class required_js_function_call extends required_js_code {
         $this->manager->yui_lib('event');
         $this->when = page_requirements_manager::WHEN_ON_DOM_READY;
     }
+
+    /**
+     * Indicate that this function should be called a certain number of seconds
+     * after the page has finished loading. (More exactly, a number of seconds
+     * after the onDomReady event fires.)
+     *
+     * @param integer $seconds the number of seconds delay.
+     */
+    public function after_delay($seconds) {
+        if ($seconds) {
+            $this->on_dom_ready();
+        }
+        $this->delay = $seconds;
+    }
 }
 
 
@@ -943,8 +972,12 @@ class required_data_for_js extends required_js_code {
  * @return string HTML, the code wrapped in <script> tags.
  */
 function ajax_generate_script_tag($js) {
-    return '<script type="text/javascript">' . "\n//<![CDATA[\n" .
-            $js . "//]]>\n</script>\n";
+    if ($js) {
+        return '<script type="text/javascript">' . "\n//<![CDATA[\n" .
+                $js . "//]]>\n</script>\n";
+    } else {
+        return '';
+    }
 }
 
 
@@ -1102,98 +1135,12 @@ function ajax_resolve_yui_lib($libname) {
 }
 
 /**
- * Get the path to a JavaScript library.
- * @param $libname - the name of the library whose path we need.
- * @return string
+ * Return the HTML required to link to a JavaScript file.
+ * @param $url the URL of a JavaScript file.
+ * @return string the required HTML.
  */
-function ajax_get_lib($libname) {
-    global $CFG, $HTTPSPAGEREQUIRED;
-
-    $libpath = '';
-    $external_yui = false;
-
-    $translatelist = array(
-            'yui_yahoo' => '/lib/yui/yahoo/yahoo-min.js',
-            'yui_animation' => '/lib/yui/animation/animation-min.js',
-            'yui_autocomplete' => '/lib/yui/autocomplete/autocomplete-min.js',
-            'yui_button' => '/lib/yui/button/button-min.js',
-            'yui_calendar' => '/lib/yui/calendar/calendar-min.js',
-            'yui_charts' => '/lib/yui/charts/charts-min.js',
-            'yui_colorpicker' => '/lib/yui/colorpicker/colorpicker-min.js',
-            'yui_connection' => '/lib/yui/connection/connection-min.js',
-            'yui_container' => '/lib/yui/container/container-min.js',
-            'yui_cookie' => '/lib/yui/cookie/cookie-min.js',
-            'yui_datasource' => '/lib/yui/datasource/datasource-min.js',
-            'yui_datatable' => '/lib/yui/datatable/datatable-min.js',
-            'yui_dom' => '/lib/yui/dom/dom-min.js',
-            'yui_dom-event' => '/lib/yui/yahoo-dom-event/yahoo-dom-event.js',
-            'yui_dragdrop' => '/lib/yui/dragdrop/dragdrop-min.js',
-            'yui_editor' => '/lib/yui/editor/editor-min.js',
-            'yui_element' => '/lib/yui/element/element-min.js',
-            'yui_event' => '/lib/yui/event/event-min.js',
-            'yui_get' => '/lib/yui/get/get-min.js',
-            'yui_history' => '/lib/yui/history/history-min.js',
-            'yui_imagecropper' => '/lib/yui/imagecropper/imagecropper-min.js',
-            'yui_imageloader' => '/lib/yui/imageloader/imageloader-min.js',
-            'yui_json' => '/lib/yui/json/json-min.js',
-            'yui_layout' => '/lib/yui/layout/layout-min.js',
-            'yui_logger' => '/lib/yui/logger/logger-min.js',
-            'yui_menu' => '/lib/yui/menu/menu-min.js',
-            'yui_profiler' => '/lib/yui/profiler/profiler-min.js',
-            'yui_profilerviewer' => '/lib/yui/profilerviewer/profilerviewer-min.js',
-            'yui_resize' => '/lib/yui/resize/resize-min.js',
-            'yui_selector' => '/lib/yui/selector/selector-min.js',
-            'yui_simpleeditor' => '/lib/yui/editor/simpleeditor-min.js',
-            'yui_slider' => '/lib/yui/slider/slider-min.js',
-            'yui_tabview' => '/lib/yui/tabview/tabview-min.js',
-            'yui_treeview' => '/lib/yui/treeview/treeview-min.js',
-            'yui_uploader' => '/lib/yui/uploader/uploader-min.js',
-            'yui_utilities' => '/lib/yui/utilities/utilities.js',
-            'yui_yuiloader' => '/lib/yui/yuiloader/yuiloader-min.js',
-            'yui_yuitest' => '/lib/yui/yuitest/yuitest-min.js',
-            'ajaxcourse_blocks' => '/lib/ajax/block_classes.js',
-            'ajaxcourse_sections' => '/lib/ajax/section_classes.js',
-            'ajaxcourse' => '/lib/ajax/ajaxcourse.js'
-            );
-
-    if (!empty($HTTPSPAGEREQUIRED)) {
-        $wwwroot = $CFG->httpswwwroot;
-    } else {
-        $wwwroot = $CFG->wwwroot;
-    }
-
-    if (array_key_exists($libname, $translatelist)) {
-        // If this is a YUI file and we are using external libraries
-        if (substr($libname, 0, 3) == 'yui' && !empty($CFG->useexternalyui)) {
-            $external_yui = true;
-            // Get current version
-            include($CFG->libdir.'/yui/version.php');
-            $libpath = 'http://yui.yahooapis.com/'.$yuiversion.'/build/'.substr($translatelist[$libname], 9);
-        } else {
-            $libpath = $wwwroot . $translatelist[$libname];
-        }
-
-        // If we are in developer debug mode, use the non-compressed version of YUI for easier debugging.
-        if (debugging('', DEBUG_DEVELOPER)) {
-            $libpath = str_replace('-min.js', '.js', $libpath);
-        }
-
-    } else if (preg_match('/^https?:/', $libname)) {
-        $libpath = $libname;
-
-    } else {
-        $libpath = $wwwroot . '/' . $libname;
-    }
-
-    // Make sure the file exists if it is local.
-    if ($external_yui === false) {
-        $testpath = str_replace($wwwroot, $CFG->dirroot, $libpath);
-        if (!file_exists($testpath)) {
-            throw new moodle_exception('unknownjsinrequirejs', '', '', $libpath);
-        }
-    }
-
-    return $libpath;
+function ajax_get_link_to_script($url) {
+    return '<script type="text/javascript"  src="' . $url . '"></script>' . "\n";
 }
 
 
index 003e19b..cc66682 100644 (file)
@@ -391,25 +391,16 @@ class page_requirements_manager_test extends ajaxlib_unit_test_base {
 class ajax_test extends ajaxlib_unit_test_base {
 
     function test_ajax_generate_script_tag() {
-        $html = ajax_generate_script_tag('');
+        $html = ajax_generate_script_tag('var x = 1;');
         $this->assertContains($html, '<script type="text/javascript">');
         $this->assertContains($html, '<![CDATA[');
         $this->assertContains($html, ']]>');
         $this->assertContains($html, '</script>');
     }
 
-    function test_ajax_get_lib() {
-        global $CFG;
-        $olddebug = $CFG->debug;
-        $CFG->debug = DEBUG_DEVELOPER;
-        $this->assertEqual(ajax_get_lib('yui_yahoo'), $CFG->wwwroot . '/lib/yui/yahoo/yahoo.js');
-        $CFG->debug = DEBUG_MINIMAL;
-        $this->assertEqual(ajax_get_lib('yui_yahoo'), $CFG->wwwroot . '/lib/yui/yahoo/yahoo-min.js');
-        $CFG->debug = $olddebug;
-        $this->assertEqual(ajax_get_lib('lib/javascript-static.js'), $CFG->wwwroot . '/lib/javascript-static.js');
-        $this->assertEqual(ajax_get_lib($CFG->wwwroot . '/lib/javascript-static.js'), $CFG->wwwroot . '/lib/javascript-static.js');
-        $this->expectException();
-        ajax_get_lib('a_file_that_does_not_exist.js');
+    function test_ajax_generate_script_tag_no_output_when_no_code() {
+        $html = ajax_generate_script_tag('');
+        $this->assertEqual($html, '');
     }
 }
 
index 3657be8..d79062b 100644 (file)
@@ -1684,3 +1684,38 @@ function table_column($table, $oldfield, $field, $type='integer', $size='10',
 function use_html_editor($name='', $editorhidebuttons='', $id='') {
     error('use_html_editor() not available anymore');
 }
+
+/**
+ * The old method that was used to include JavaScript libraries.
+ * Please use $PAGE->requires->js() or $PAGE->requires->yui_lib() instead.
+ *
+ * @param mixed $lib The library or libraries to load (a string or array of strings)
+ *      There are three way to specify the library:
+ *      1. a shorname like 'yui_yahoo'. This translates into a call to $PAGE->requires->yui_lib('yahoo')->asap();
+ *      2. the path to the library relative to wwwroot, for example 'lib/javascript-static.js'
+ *      3. (legacy) a full URL like $CFG->wwwroot . '/lib/javascript-static.js'.
+ *      2. and 3. lead to a call $PAGE->requires->js('/lib/javascript-static.js').
+ */
+function require_js($lib) {
+    global $CFG, $PAGE;
+    // Add the lib to the list of libs to be loaded, if it isn't already
+    // in the list.
+    if (is_array($lib)) {
+        foreach($lib as $singlelib) {
+            require_js($singlelib);
+        }
+        return;
+    }
+
+    // TODO uncomment this once we have eliminated the remaining calls to require_js from core.
+    //debugging('Call to deprecated function require_js. Please use $PAGE->requires->js() ' .
+    //        'or $PAGE->requires->yui_lib() instead.', DEBUG_DEVELOPER);
+
+    if (strpos($lib, 'yui_') === 0) {
+        echo $PAGE->requires->yui_lib(substr($lib, 4))->asap();
+    } else if (preg_match('/^https?:/', $lib)) {
+        echo $PAGE->requires->js(str_replace($CFG->wwwroot, '', $lib))->asap();
+    } else {
+        echo $PAGE->requires->js($lib)->asap();
+    }
+}
index 18d6121..6de2142 100644 (file)
@@ -1874,7 +1874,7 @@ function file_modify_html_header($text) {
     $ufo = '';
     if (filter_is_enabled('filter/mediaplugin')) {
         // this script is needed by most media filter plugins.
-        $ufo = get_require_js_code(array($CFG->wwwroot . '/lib/ufo.js'));
+        $ufo = ajax_get_link_to_script($CFG->wwwroot . '/lib/ufo.js');
     }
 
     preg_match('/\<head\>|\<HEAD\>/', $text, $matches);
index 9aa9e45..f940586 100644 (file)
@@ -82,6 +82,7 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group
                 }
             }
         }
+        form_init_date_js();
     }
 
     // }}}
@@ -179,7 +180,6 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group
 
     function toHtml()
     {
-        form_init_date_js();
         include_once('HTML/QuickForm/Renderer/Default.php');
         $renderer =& new HTML_QuickForm_Renderer_Default();
         $renderer->setElementTemplate('{element}');
index e9d480f..d1feef1 100644 (file)
@@ -82,6 +82,7 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{
                 }
             }
         }
+        form_init_date_js();
     }
 
     // }}}
@@ -197,7 +198,6 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{
 
     function toHtml()
     {
-        form_init_date_js();
         include_once('HTML/QuickForm/Renderer/Default.php');
         $renderer =& new HTML_QuickForm_Renderer_Default();
         $renderer->setElementTemplate('{element}');
index 4b7fa99..ef5352c 100644 (file)
@@ -62,20 +62,17 @@ if ($CFG->debug >= DEBUG_ALL){
 }
 
 /**
- * @global object
+ * 
  * @staticvar bool $done
- * @todo This is NOT xhtml strict, we will need something like require_css() 
  */
 function form_init_date_js() {
-    global $CFG;
+    global $PAGE;
     static $done = false;
     if (!$done) {
-        //TODO: this is NOT xhtml strict, we will need something like require_css() 
-        echo '<style type="text/css">';
-        echo '@import "' . $CFG->httpswwwroot . '/lib/yui/assets/skins/sam/calendar.css";';
-        echo '</style>';
-        require_js(array('yui_yahoo', 'yui_dom', 'yui_event', 'yui_calendar', 'yui_container'));
-        print_delayed_js_call(1, 'init_date_selectors', array(get_string('firstdayofweek')));
+        $PAGE->requires->yui_lib('calendar');
+        $PAGE->requires->yui_lib('container');
+        $PAGE->requires->js_function_call('init_date_selectors',
+                array(get_string('firstdayofweek')));
         $done = true;
     }
 }
index 756748e..f378bf3 100644 (file)
@@ -8433,7 +8433,7 @@ function moodle_request_shutdown() {
  * @return string Javascript code
  */
 function message_popup_window() {
-    global $USER, $DB;
+    global $USER, $DB, $PAGE;
 
     $popuplimit = 30;     // Minimum seconds between popups
 
@@ -8446,9 +8446,8 @@ function message_popup_window() {
                 if (get_user_preferences('message_showmessagewindow', 1) == 1) {
                     if ($DB->count_records_select('message', 'useridto = ? AND timecreated > ?', array($USER->id, $USER->message_lastpopup))) {
                         $USER->message_lastpopup = time();
-                        return print_js_call('openpopup', array('/message/index.php', 'message',
-                                'menubar=0,location=0,scrollbars,status,resizable,width=400,height=500',
-                                0), true);
+                        $PAGE->requires->js_function_call('openpopup', array('/message/index.php', 'message',
+                                'menubar=0,location=0,scrollbars,status,resizable,width=400,height=500', 0));
                     }
                 }
             }
index 5f62baf..1ed204d 100644 (file)
@@ -301,7 +301,6 @@ class moodle_page {
         global $CFG;
         if (is_null($this->_requires)) {
             $this->_requires = new page_requirements_manager();
-            setup_core_javascript($this->_requires);
         }
         return $this->_requires;
     }
@@ -662,6 +661,7 @@ class moodle_page {
         $this->add_body_classes(get_browser_version_classes());
         $this->add_body_class('dir-' . get_string('thisdirection'));
         $this->add_body_class('lang-' . current_language());
+        $this->add_body_class('yui-skin-sam'); // Make YUI happy, if it is used.
 
         $this->add_body_class($this->url_to_class_name($CFG->wwwroot));
 
index d93bba5..425fd51 100644 (file)
@@ -2110,7 +2110,7 @@ function question_format_grade($cmoptions, $grade) {
  * to get from PHP.
  */
 function question_init_qenginejs_script() {
-    global $CFG;
+    global $CFG, $PAGE;
     $config = array(
         'pixpath' => $CFG->pixpath,
         'wwwroot' => $CFG->wwwroot,
@@ -2119,7 +2119,7 @@ function question_init_qenginejs_script() {
         'flaggedalt' => get_string('flagged', 'question'),
         'unflaggedalt' => get_string('notflagged', 'question'),
     );
-    return print_js_config($config, 'qengine_config', true);
+    $PAGE->requires->data_for_js('qengine_config', $config);
 }
 
 /// FUNCTIONS THAT SIMPLY WRAP QUESTIONTYPE METHODS //////////////////////////////////
index 1b508c9..795e4aa 100644 (file)
@@ -143,7 +143,7 @@ function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false) {
     $strgetanaudiocaptcha = get_string('getanaudiocaptcha', 'auth');
     $strgetanimagecaptcha = get_string('getanimagecaptcha', 'auth');
 
-    $return = get_require_js_code(array($server . '/challenge?k=' . $pubkey . $errorpart));
+    $page->requires->js($server . '/challenge?k=' . $pubkey . $errorpart, true);
     $return .= '<noscript>
         <div id="recaptcha_widget_noscript">
         <div id="recaptcha_image_noscript"><img src="' . $image_url . '" alt="reCAPTCHA"/></div>';
index 7666657..8600455 100644 (file)
@@ -67,13 +67,6 @@ define('FORMAT_MARKDOWN', '4');   // Markdown-formatted text http://daringfireba
 define('TRUSTTEXT', '#####TRUSTTEXT#####');
 
 
-/**
- * Javascript related defines
- */
-define('REQUIREJS_BEFOREHEADER', 0);
-define('REQUIREJS_INHEADER',     1);
-define('REQUIREJS_AFTERHEADER',  2);
-
 /**
  * Allowed tags - string of html tags that can be tested against for safe html tags
  * @global string $ALLOWED_TAGS
@@ -369,12 +362,15 @@ class moodle_url {
      * @param string $paramname name
      * @param string $param Param value. Defaults to null. If null then return value of param 'name'
      * @return void|string If $param was null then the value of $paramname was returned
+     *      (null is returned if that param does not exist).
      */
     public function param($paramname, $param = null) {
         if (!is_null($param)) {
             $this->params = array($paramname => $param) + $this->params;
-        } else {
+        } else if (array_key_exists($paramname, $this->params)) {
             return $this->params[$paramname];
+        } else {
+            return null;
         }
     }
 
@@ -734,7 +730,8 @@ function close_window($delay = 0, $reloadopener = false) {
         $function = 'close_window';
     }
     echo '<p class="centerpara">' . get_string('windowclosing') . '</p>';
-    print_delayed_js_call($delay, $function);
+
+    $PAGE->requires->js_function_call($function)->after_delay($delay);
 
     print_footer('empty');
     exit;
@@ -2062,18 +2059,17 @@ function replace_smilies(&$text) {
  * @global object
  * @return string HTML for a list of smilies.
  */
-function get_emoticons_list_for_help_file(){
-    global $CFG, $SESSION;
+function get_emoticons_list_for_help_file() {
+    global $CFG, $SESSION, $PAGE;
     if (empty($CFG->emoticons)) {
         return '';
     }
 
-    require_js(array('yui_yahoo', 'yui_event'));
     $items = explode('{;}', $CFG->emoticons);
     $output = '<ul id="emoticonlist">';
     foreach ($items as $item) {
         $item = explode('{:}', $item);
-        $output .= '<li><img src="' . $CFG->pixpath.'/s/' . $item[1] . '.gif" alt="' .
+        $output .= '<li><img src="' . $CFG->pixpath . '/s/' . $item[1] . '.gif" alt="' .
                 $item[0] . '" /><code>' . $item[0] . '</code></li>';
     }
     $output .= '</ul>';
@@ -2085,7 +2081,8 @@ function get_emoticons_list_for_help_file(){
         $fieldname = 'message';
     }
 
-    $output .= print_js_call('emoticons_help.init', array($formname, $fieldname, 'emoticonlist'), true);
+    $PAGE->requires->yui_lib('event');
+    $PAGE->requires->js_function_call('emoticons_help.init', array($formname, $fieldname, 'emoticonlist'));
     return $output;
 
 }
@@ -2405,10 +2402,7 @@ function print_header ($title='', $heading='', $navigation='', $focus='',
     }
 
     $meta = $meta."\n".$metapage;
-
-    $meta .= "\n".require_js('',1);
-
-    $meta .= standard_js_config();
+    $meta .= $PAGE->requires->get_head_code();
 
 /// Set up some navigation variables
 
@@ -2568,8 +2562,7 @@ function print_header ($title='', $heading='', $navigation='', $focus='',
     }
 
     // Add in any extra JavaScript libraries that occurred during the header
-    $output .= require_js('', 2);
-    $output .= print_js_call('moodle_initialise_body', array(), true);
+    $output .= $PAGE->requires->get_top_of_body_code();
 
     $PAGE->set_state(moodle_page::STATE_IN_BODY);
 
@@ -2580,252 +2573,6 @@ function print_header ($title='', $heading='', $navigation='', $focus='',
     }
 }
 
-/**
- * Used to include JavaScript libraries.
- *
- * When the $lib parameter is given, the function will ensure that the
- * named library or libraries is loaded onto the page - either in the
- * HTML <head>, just after the header, or at an arbitrary later point in
- * the page, depending on where this function is called.
- *
- * Libraries will not be included more than once, so this works like
- * require_once in PHP.
- *
- * There are two special-case calls to this function from print_header which are
- * internal to weblib and use the second $extracthtml parameter:
- * $extracthtml = 1: this is used before printing the header.
- *      It returns the script tag code that should go inside the <head>.
- * $extracthtml = 2: this is used after printing the header and handles any
- *      require_js calls that occurred within the header itself.
- *
- * @global object
- * @staticvar array $loadlib
- * @staticvar int $state Defaults to REQUIREJS_BEFOREHEADER
- * @staticvar string $latecode
- * @uses REQUIREJS_BEFOREHEADER
- * @uses REQUIREJS_INHEADER
- * @uses REQUIREJS_AFTERHEADER
- * @param mixed $lib The library or libraries to load (a string or array of strings)
- *      There are three way to specify the library:
- *      1. a shorname like 'yui_yahoo'. The list of recognised values is in lib/ajax/ajaxlib.php
- *      2. the path to the library relative to wwwroot, for example 'lib/javascript-static.js'
- *      3. (legacy) a full URL like $CFG->wwwroot . '/lib/javascript-static.js'.
- * @param int $extracthtml Private. For internal weblib use only.
- * @return mixed No return value (except when doing the internal $extracthtml
- *      calls, when it returns html code).
- */
-function require_js($lib, $extracthtml = 0) {
-    global $CFG;
-    static $loadlibs = array();
-
-    static $state = REQUIREJS_BEFOREHEADER;
-    static $latecode = '';
-
-    if (!empty($lib)) {
-        // Add the lib to the list of libs to be loaded, if it isn't already
-        // in the list.
-        if (is_array($lib)) {
-            foreach($lib as $singlelib) {
-                require_js($singlelib);
-            }
-        } else {
-            $libpath = ajax_get_lib($lib);
-            if (array_search($libpath, $loadlibs) === false) {
-                $loadlibs[] = $libpath;
-
-                // For state other than 0 we need to take action as well as just
-                // adding it to loadlibs
-                if($state != REQUIREJS_BEFOREHEADER) {
-                    // Get the script statement for this library
-                    $scriptstatement=get_require_js_code(array($libpath));
-
-                    if($state == REQUIREJS_AFTERHEADER) {
-                        // After the header, print it immediately
-                        print $scriptstatement;
-                    } else {
-                        // Haven't finished the header yet. Add it after the
-                        // header
-                        $latecode .= $scriptstatement;
-                    }
-                }
-            }
-        }
-    } else if($extracthtml==1) {
-        if($state !== REQUIREJS_BEFOREHEADER) {
-            debugging('Incorrect state in require_js (expected BEFOREHEADER): be careful not to call with empty $lib (except in print_header)');
-        } else {
-            $state = REQUIREJS_INHEADER;
-        }
-
-        return get_require_js_code($loadlibs);
-    } else if($extracthtml==2) {
-        if($state !== REQUIREJS_INHEADER) {
-            debugging('Incorrect state in require_js (expected INHEADER): be careful not to call with empty $lib (except in print_header)');
-            return '';
-        } else {
-            $state = REQUIREJS_AFTERHEADER;
-            return $latecode;
-        }
-    } else {
-        debugging('Unexpected value for $extracthtml');
-    }
-}
-
-/**
- * Should not be called directly - use require_js. This function obtains the code
- * (script tags) needed to include JavaScript libraries.
- *
- * @global object
- * @param array $loadlibs Array of library files to include
- * @return string HTML code to include them
- */
-function get_require_js_code($loadlibs) {
-    global $CFG;
-    // Return the html needed to load the JavaScript files defined in
-    // our list of libs to be loaded.
-    $output = '';
-    foreach ($loadlibs as $loadlib) {
-        $output .= '<script type="text/javascript" ';
-        $output .= " src=\"$loadlib\"></script>\n";
-        if ($loadlib == $CFG->wwwroot.'/lib/yui/logger/logger-min.js') {
-            // Special case, we need the CSS too.
-            $output .= '<link type="text/css" rel="stylesheet" ';
-            $output .= " href=\"{$CFG->wwwroot}/lib/yui/logger/assets/logger.css\" />\n";
-        }
-    }
-    return $output;
-}
-
-/**
- * Generate the HTML for calling a javascript funtion. You often need to do this
- * if you have your javascript in an external file, and need to call one function
- * to initialise it.
- *
- * You can pass in an optional list of arguments, which are properly escaped for
- * you using the json_encode function.
- *
- * @param string $function the name of the JavaScript function to call.
- * @param array $args an optional list of arguments to the function call.
- * @param boolean $return if true, return the HTML code, otherwise output it.
- * @return string|void string if $return is true, otherwise nothing.
- */
-function print_js_call($function, $args = array(), $return = false) {
-    $quotedargs = array();
-    foreach ($args as $arg) {
-        $quotedargs[] = json_encode($arg);
-    }
-    $html = '';
-    $html .= '<script type="text/javascript">//<![CDATA[' . "\n";
-    $html .= $function . '(' . implode(', ', $quotedargs) . ");\n";
-    $html .= "//]]></script>\n";
-    if ($return) {
-        return $html;
-    } else {
-        echo $html;
-    }
-}
-
-/**
- * Generate the HTML for calling a javascript funtion after a time delay.
- * In other respects, this function is the same as print_js_call.
- *
- * @param integer $delay the desired delay in seconds.
- * @param string $function the name of the JavaScript function to call.
- * @param array $args an optional list of arguments to the function call.
- * @param boolean $return if true, return the HTML code, otherwise output it.
- * @return string|void string if $return is true, otherwise nothing.
- */
-function print_delayed_js_call($delay, $function, $args = array(), $return = false) {
-    $quotedargs = array();
-    foreach ($args as $arg) {
-        $quotedargs[] = json_encode($arg);
-    }
-    $html = '';
-    $html .= '<script type="text/javascript">//<![CDATA[' . "\n";
-    $html .= 'setTimeout(function() {' . $function . '(' .
-            implode(', ', $quotedargs) . ');}, ' . ($delay * 1000) . ");\n";
-    $html .= "//]]></script>\n";
-    if ($return) {
-        return $html;
-    } else {
-        echo $html;
-    }
-}
-
-/**
- * Create a Javascript config object for use in code
- *
- * Sometimes you need access to some values in your JavaScript that you can only
- * get from PHP code. You can handle this by generating your JS in PHP, but a
- * better idea is to write static javascrip code that reads some configuration
- * variable, and then just output the configuration variables from PHP using
- * this function.
- *
- * For example, look at the code in question_init_qenginejs_script() in
- * lib/questionlib.php. It writes out a bunch of $settings like
- * 'pixpath' => $CFG->pixpath, with $prefix = 'qengine_config'. This gets output
- * in print_header, then the code in question/qengine.js can access these variables
- * as qengine_config.pixpath, and so on.
- *
- * This method will also work without a prefix, but it is better to avoid that
- * we don't want to add more things than necessary to the global JavaScript scope.
- *
- * This method automatically wrapps the values in quotes, and addslashes_js them.
- *
- * @param array $settings the values you want to write out, as variablename => value.
- * @param string $prefix a namespace prefix to use in the JavaScript.
- * @param boolean $return if true, return the HTML code, otherwise output it.
- * @return mixed string if $return is true, otherwise nothing.
- */
-function print_js_config($settings = array(), $prefix='', $return = false) {
-    $html = '';
-    $html .= '<script type="text/javascript">//<![CDATA[' . "\n";
-
-    // Have to treat the prefix and no prefix cases separately.
-    if ($prefix) {
-        // Recommended way, only one thing in global scope.
-        $html .= "var $prefix = " . json_encode($settings) . "\n";
-
-    } else {
-        // Old fashioned way.
-        foreach ($settings as $name => $value) {
-            $html .= "var $name = '" . addslashes_js($value) . "'\n";
-        }
-    }
-
-    // Finish off and return/output.
-    $html .= "//]]></script>\n";
-    if ($return) {
-        return $html;
-    } else {
-        echo $html;
-    }
-}
-
-/**
- * This function generates the code that defines the standard moodle_cfg object.
- *
- * This object has a number of fields that are values that various pieces of
- * JavaScript code need access too. For example $CFG->wwwroot and $CFG->pixpath.
- *
- * @global object
- * @uses DEBUG_DEVELOPER
- * @return string a <script> tag that defines the moodle_cfg object.
- */
-function standard_js_config() {
-    global $CFG;
-    $config = array(
-        'wwwroot' => $CFG->httpswwwroot, // Yes, really.
-        'pixpath' => $CFG->pixpath,
-        'modpixpath' => $CFG->modpixpath,
-        'sesskey' => sesskey(),
-    );
-    if (debugging('', DEBUG_DEVELOPER)) {
-        $config['developerdebug'] = true;
-    }
-    return print_js_config($config, 'moodle_cfg', true);
-}
-
 /**
  * Debugging aid: serve page as 'application/xhtml+xml' where possible,
  *     and substitute the XHTML strict document type.
@@ -3059,6 +2806,9 @@ function print_footer($course=NULL, $usercourse=NULL, $return=false) {
     $output = ob_get_contents();
     ob_end_clean();
 
+    // Put the end of page <script> tags just inside </body> to maintain validity.
+    $output = str_replace('</body>', $PAGE->requires->get_end_code() . '</body>', $output); 
+
     $PAGE->set_state(moodle_page::STATE_DONE);
 
     if ($return) {
@@ -4223,10 +3973,10 @@ function print_collapsible_region($contents, $classes, $id, $caption, $userpref
  * @return string|void if $return is false, returns nothing, otherwise returns a string of HTML.
  */
 function print_collapsible_region_start($classes, $id, $caption, $userpref = false, $default = false, $return = false) {
-    global $CFG;
+    global $CFG, $PAGE;
 
     // Include required JavaScript libraries.
-    require_js(array('yui_yahoo', 'yui_dom-event', 'yui_event', 'yui_animation'));
+    $PAGE->requires->yui_lib('animation');
 
     // Work out the initial state.
     if (is_string($userpref)) {
@@ -4247,7 +3997,8 @@ function print_collapsible_region_start($classes, $id, $caption, $userpref = fal
     $output .= '<div id="' . $id . '_caption" class="collapsibleregioncaption">';
     $output .= $caption . ' ';
     $output .= '</div><div id="' . $id . '_inner" class="collapsibleregioninner">';
-    $output .= print_js_call('new collapsible_region', array($id, $userpref, get_string('clicktohideshow')), true);
+    $PAGE->requires->js_function_call('new collapsible_region',
+            array($id, $userpref, get_string('clicktohideshow')));
 
     if ($return) {
         return $output;
@@ -5119,8 +4870,8 @@ function print_table($table, $return=false) {
     $output .= '</table>'."\n";
 
     if ($table->rotateheaders && can_use_rotated_text()) {
-        require_js(array('yui_yahoo','yui_event','yui_dom'));
-        require_js('course/report/progress/textrotate.js');
+        $PAGE->requires->yui_lib('event');
+        $PAGE->requires->js('course/report/progress/textrotate.js');
     }
 
     if ($return) {
@@ -6478,7 +6229,7 @@ function redirect($url, $message='', $delay=-1) {
         @header('Location: '.$url);
         //another way for older browsers and already sent headers (eg trailing whitespace in config.php)
         echo '<meta http-equiv="refresh" content="'. $delay .'; url='. $encodedurl .'" />';
-        print_js_call('document.location.replace', array($url));
+        echo $PAGE->requires->js_function_call('document.location.replace', array($url))->asap();
         die;
     }
 
@@ -6498,7 +6249,7 @@ function redirect($url, $message='', $delay=-1) {
     echo '</div>';
 
     if (!$errorprinted) {
-        print_delayed_js_call($delay, 'document.location.replace', array($url));
+        $PAGE->requires->js_function_call('document.location.replace', array($url))->after_delay($delay);
     }
 
     $CFG->docroot = false; // to prevent the link to moodle docs from being displayed on redirect page.
index 1c978ad..69a4f38 100644 (file)
     }
 
     // Javascript for Mozilla to cope with the redirect bug from editor being on in this page
-    print_delayed_js_call($wait, 'document.location.replace', array(
-            "refresh.php?id=$userid&name=" . urlencode($userfullname) . "&wait=$wait"));
-    echo '</body>'."\n";
-    echo '</html>'."\n";
+    echo '<script type="text/javascript">//<![CDATA[' . "\n";
+    echo 'setTimeout(function() { document.location.replace(' .
+            json_encode("refresh.php?id=$userid&name=" . urlencode($userfullname) .
+            "&wait=$wait") . ');}, ' . ($wait * 1000) . ");\n";
+    echo "//]]></script>\n";
+    echo "</body>\n";
+    echo "</html>\n";
 ?>
index 210fcf8..e47281d 100644 (file)
@@ -64,10 +64,10 @@ $str_userlist  = get_string('userlist',  'chat');
 <link rel="stylesheet" type="text/css" href="<?php echo $CFG->httpswwwroot;?>/lib/yui/resize/assets/skins/sam/resize.css" />
 <link rel="stylesheet" type="text/css" href="<?php echo $CFG->httpswwwroot;?>/lib/yui/layout/assets/skins/sam/layout.css" />
 <link rel="stylesheet" type="text/css" href="<?php echo $CFG->httpswwwroot;?>/lib/yui/button/assets/skins/sam/button.css" />
-<?php
-print_js_config(array('home'=>$CFG->httpswwwroot.'/mod/chat/view.php?id='.$cm->id, 'userid'=>$USER->id, 'sid'=>$chat_sid,'timer'=>5000, 'chat_lasttime'=>0,'chat_lastrow'=>null,'header_title'=>$str_chat,'chatroom_name'=>$str_title), 'chat_cfg');
-print_js_config(array('send'=>$str_send, 'sending'=>$str_sending, 'inputarea'=>$str_inputarea, 'userlist'=>$str_userlist), 'chat_lang');
-?>
+<script type="text/javascript">
+var chat_cfg = <?php echo json_encode(array('home'=>$CFG->httpswwwroot.'/mod/chat/view.php?id='.$cm->id, 'userid'=>$USER->id, 'sid'=>$chat_sid,'timer'=>5000, 'chat_lasttime'=>0,'chat_lastrow'=>null,'header_title'=>$str_chat,'chatroom_name'=>$str_title)); ?>;
+var chat_lang = <?php echo json_encode(array('send'=>$str_send, 'sending'=>$str_sending, 'inputarea'=>$str_inputarea, 'userlist'=>$str_userlist)); ?>;
+</script>
 <script type="text/javascript" src="<?php echo $CFG->httpswwwroot;?>/lib/yui/yahoo-dom-event/yahoo-dom-event.js"></script>
 <script type="text/javascript" src="<?php echo $CFG->httpswwwroot;?>/lib/yui/element/element-min.js"></script>
 <script type="text/javascript" src="<?php echo $CFG->httpswwwroot;?>/lib/yui/dragdrop/dragdrop-min.js"></script>
index d617fd9..b0de7c6 100644 (file)
@@ -5714,7 +5714,7 @@ function forum_print_latest_discussions($course, $forum, $maxdiscussions=-1, $di
  */
 function forum_print_discussion($course, $cm, $forum, $discussion, $post, $mode, $canreply=NULL, $canrate=false) {
 
-    global $USER, $CFG, $DB;
+    global $USER, $CFG, $DB, $PAGE;
 
     if (!empty($USER->id)) {
         $ownpost = ($USER->id == $post->userid);
@@ -5835,7 +5835,7 @@ function forum_print_discussion($course, $cm, $forum, $discussion, $post, $mode,
             echo '<div class="ratingsubmit">';
             echo '<input type="submit" id="forumpostratingsubmit" value="'.get_string('sendinratings', 'forum').'" />';
             if (ajaxenabled() && !empty($CFG->forum_ajaxrating)) { /// AJAX enabled, standard submission form
-                print_js_call('init_rate_ajax');
+                $PAGE->requires->js_function_call('init_rate_ajax');
             }
             if ($forum->scale < 0) {
                 if ($scale = $DB->get_record("scale", array("id" => abs($forum->scale)))) {
index aebcad7..3a548d6 100644 (file)
@@ -169,7 +169,8 @@ class quiz_access_manager {
         /// Make sure the timer starts just above zero. If $timeleft was <= 0, then
         /// this will just have the effect of causing the quiz to be submitted immediately.
             $timerstartvalue = max($timeleft, 1);
-            print_js_call('quiz_timer.initialise', array(get_string('timesup','quiz'), $timerstartvalue));
+            $PAGE->requires->js_function_call('quiz_timer.initialise',
+                    array(get_string('timesup', 'quiz'), $timerstartvalue));
         }
     }
 
@@ -231,7 +232,7 @@ class quiz_access_manager {
                 $delay = 0;
             }
             print_box_end();
-            print_js_call('quiz_secure_window.close', array($url, $delay));
+            $PAGE->requires->js_function_call('quiz_secure_window.close', array($url, $delay));
             print_footer('empty');
             die();
         } else {
index 01c5df5..f429e77 100644 (file)
@@ -77,8 +77,7 @@
 /// Print the quiz page ////////////////////////////////////////////////////////
 
     // Print the page header
-    require_js(array('yui_yahoo','yui_event'));
-    require_js('mod/quiz/quiz.js');
+    $PAGE->requires->yui_lib('event');
     $title = get_string('attempt', 'quiz', $attemptobj->get_attempt_number());
     $headtags = $attemptobj->get_html_head_contributions($page);
     if ($accessmanager->securewindow_required($attemptobj->is_preview_user())) {
     // Start the form
     echo '<form id="responseform" method="post" action="', $attemptobj->processattempt_url(),
             '" enctype="multipart/form-data" accept-charset="utf-8">', "\n";
+
+    // A quiz page with a lot of questions can take a long time to load, and we
+    // want the protection afforded by init_quiz_form immediately, so include the
+    // JS now.
+    echo $PAGE->requires->yui_lib('event')->asap();
+    echo $PAGE->requires->js('mod/quiz/quiz.js')->asap();
+    echo $PAGE->requires->js_function_call('init_quiz_form')->asap();
     echo '<div>';
-    print_js_call('init_quiz_form');
 
 /// Print the navigation panel in a left column.
     print_container_start();
index e2de834..d8f8644 100644 (file)
@@ -889,10 +889,12 @@ abstract class quiz_nav_panel_base {
     }
 
     protected function get_question_buttons() {
+        global $PAGE;
         $html = '<div class="qn_buttons">' . "\n";
         foreach ($this->attemptobj->get_question_iterator() as $number => $question) {
-            $html .= $this->get_question_button($number, $question) . "\n" .
-                    $this->get_button_update_script($question) . "\n";
+            $html .= $this->get_question_button($number, $question) . "\n";
+            $PAGE->requires->js_function_call('quiz_init_nav_button',
+                    array($this->get_button_id($question), $question->id));
         }
         $html .= "</div>\n";
         return $html;
@@ -903,11 +905,6 @@ abstract class quiz_nav_panel_base {
         return 'quiznavbutton' . $question->id;
     }
 
-    protected function get_button_update_script($question) {
-        return print_js_call('quiz_init_nav_button',
-                array($this->get_button_id($question), $question->id), true);
-    }
-
     abstract protected function get_question_button($number, $question);
 
     abstract protected function get_end_bits();
index 46a16e8..744dcbc 100644 (file)
@@ -456,8 +456,8 @@ $numberoflisteners = max(quiz_number_of_pages($quiz->questions), 1);
 for ($pageiter = 1; $pageiter <= $numberoflisteners; $pageiter++) {
     $quizeditconfig->dialoglisteners[] = 'addrandomdialoglaunch_' . $pageiter;
 }
-print_js_config($quizeditconfig, 'quiz_edit_config');
-require_js('mod/quiz/edit.js');
+$PAGE->requires->data_for_js('quiz_edit_config', $quizeditconfig);
+$PAGE->requires->js('mod/quiz/edit.js');
 
 // Print the tabs.
 $currenttab = 'edit';
index 8d45ddd..5d7b3f8 100644 (file)
@@ -210,7 +210,7 @@ quiz_secure_window = {
             quiz_secure_window.close_next_url = url;
         }
         if (delay > 0) {
-            setTimeout(function() {quiz_secure_window.close('eval (x)', 0);}, delay*1000);
+            setTimeout(function() {quiz_secure_window.close('', 0);}, delay*1000);
         } else {
             if (window.opener) {
                 window.opener.document.location.reload();
index d6e61da..2922389 100644 (file)
                 get_string('saveflags', 'question') . '" />' .
                 "</div>\n" .
                 "\n</div></form>\n";
-        print_js_call('question_flag_changer.init_flag_save_form', array('savingflagssubmit'));
+        $PAGE->requires->js_function_call('question_flag_changer.init_flag_save_form', array('savingflagssubmit'));
     }
 
 /// Print a link to the next page.
index d549481..f5d2323 100644 (file)
@@ -401,10 +401,11 @@ class question_bank_checkbox_column extends question_bank_column_base {
     }
 
     protected function display_content($question, $rowclasses) {
+        global $PAGE;
         echo '<input title="' . $this->strselect . '" type="checkbox" name="q' .
                 $question->id . '" id="checkq' . $question->id . '" value="1"/>';
         if ($this->firstrow) {
-            print_js_call('question_bank.init_checkbox_column', array(get_string('selectall'),
+            $PAGE->requires->js_function_call('question_bank.init_checkbox_column', array(get_string('selectall'),
                     get_string('deselectall'), 'checkq' . $question->id));
             $this->firstrow = false;
         }
@@ -782,7 +783,7 @@ class question_bank_view {
     protected $sqlparams;
 
     public function __construct($contexts, $pageurl, $course, $cm = null) {
-        global $CFG;
+        global $CFG, $PAGE;
 
         $this->contexts = $contexts;
         $this->baseurl = $pageurl;
@@ -809,6 +810,8 @@ class question_bank_view {
         $this->init_column_types();
         $this->init_columns($this->wanted_columns());
         $this->init_sort();
+
+        $PAGE->requires->yui_lib('dom-event');
     }
 
     protected function wanted_columns() {
@@ -1831,9 +1834,8 @@ function require_login_in_context($contextorid = null){
  * the qtype radio buttons.
  */
 function print_choose_qtype_to_add_form($hiddenparams) {
-    global $CFG, $QTYPES;
-    require_js(array('yui_yahoo','yui_dom','yui_event'));
-    require_js('question/qbank.js');
+    global $CFG, $QTYPES, $PAGE;
+    $PAGE->requires->js('question/qbank.js');
     echo '<div id="chooseqtypehead" class="hd">' . "\n";
     print_heading(get_string('chooseqtypetoadd', 'question'), '', 3);
     echo "</div>\n";
@@ -1867,7 +1869,7 @@ function print_choose_qtype_to_add_form($hiddenparams) {
     echo '<input type="submit" id="chooseqtypecancel" name="addcancel" value="' . get_string('cancel') . '" />' . "\n";
     echo "</div></form>\n";
     echo "</div>\n";
-    print_js_call('qtype_chooser.init', array('chooseqtype'));
+    $PAGE->requires->js_function_call('qtype_chooser.init', array('chooseqtype'));
 }
 
 /**
index 24b5de9..3ad786f 100644 (file)
             $efile = get_file_url($filename, null, 'questionfile');
             echo '<p><div class="boxaligncenter">' .
                     get_string('yourfileshoulddownload', 'question', $efile) . '</div></p>';
-            print_delayed_js_call(1, 'document.location.replace', array($efile));
+            $PAGE->requires->js_function_call('document.location.replace', array($efile))->after_delay(1);
         }
 
         print_continue('edit.php?' . $thispageurl->get_query_string());
index 630822d..43571ba 100644 (file)
@@ -975,7 +975,7 @@ class default_questiontype {
      * @param integer $flagsoption the option that says whether flags should be displayed.
      */
     protected function print_question_flag($question, $state, $flagsoption) {
-        global $CFG;
+        global $CFG, $PAGE;
         switch ($flagsoption) {
             case QUESTION_FLAGSSHOWN:
                 $flagcontent = $this->get_question_flag_tag($state->flagged);
@@ -991,12 +991,12 @@ class default_questiontype {
                 $aid = $state->attempt;
                 $qid = $state->question;
                 $checksum = question_get_toggleflag_checksum($aid, $qid, $qsid);
-                $postdata = "qsid=$qsid&amp;aid=$aid&amp;qid=$qid&amp;checksum=$checksum&amp;sesskey=" . sesskey();
+                $postdata = "qsid=$qsid&aid=$aid&qid=$qid&checksum=$checksum&sesskey=" . sesskey();
                 $flagcontent = '<input type="checkbox" id="' . $id . '" name="' . $id .
                         '" value="1" ' . $checked . ' />' . 
                         '<label id="' . $id . 'label" for="' . $id . '">' . $this->get_question_flag_tag(
-                        $state->flagged, $id . 'img') . '</label>' . "\n" .
-                        print_js_call('question_flag_changer.init_flag', array($id, $postdata), true);
+                        $state->flagged, $id . 'img') . '</label>' . "\n";
+                $PAGE->requires->js_function_call('question_flag_changer.init_flag', array($id, $postdata));
                 break;
             default:
                 $flagcontent = '';
index 6744e7c..14f1054 100644 (file)
@@ -1721,6 +1721,7 @@ function repository_setup_default_plugins() {
     }
     return true;
 }
+
 /**
  * Return javascript to create file picker to browse repositories
  * @global object $CFG
@@ -1885,18 +1886,19 @@ EOD;
         $lang['popup']     = get_string('popup', 'repository');
         $lang['upload']    = get_string('upload', 'repository').'...';
         $lang['uploading'] = get_string('uploading', 'repository');
-        // fp_lang includes language strings
-        $js .= print_js_config($lang, 'fp_lang', true);
+        $lang = json_encode($lang);
 
         $options = array();
         $context = get_system_context();
         $options['contextid'] = $context->id;
+        $options = json_encode($options);
         // fp_config includes filepicker options
-        $js .= print_js_config($options, 'fp_config', true);
 
         $accepted_file_ext = json_encode($ft->get_file_ext($accepted_filetypes));
         $js .= <<<EOD
 <script type="text/javascript">
+var fp_lang = $lang;
+var fp_config = $options;
 file_extensions.image = $image_file_ext;
 file_extensions.media = $video_file_ext;
 </script>
index 0844249..5c8d105 100644 (file)
@@ -81,7 +81,7 @@ abstract class user_selector_base {
      * You must be able to clone a userselector by doing new get_class($us)($us->get_name(), $us->get_options());
      */
     public function __construct($name, $options = array()) {
-        global $CFG;
+        global $CFG, $PAGE;
 
         // Initialise member variables from constructor arguments.
         $this->name = $name;
@@ -105,8 +105,10 @@ abstract class user_selector_base {
         $this->searchanywhere = $this->initialise_option('userselector_searchanywhere', $this->searchanywhere);
 
         // Required JavaScript code.
-        require_js(array('yui_yahoo', 'yui_event', 'yui_json', 'yui_connection', 'yui_datasource'));
-        require_js('user/selector/script.js');
+        $PAGE->requires->yui_lib('json');
+        $PAGE->requires->yui_lib('connection');
+        $PAGE->requires->yui_lib('datasource');
+        $PAGE->requires->js('user/selector/script.js');
     }
 
     /**
@@ -181,6 +183,8 @@ abstract class user_selector_base {
      * @return mixed if $return is true, returns the HTML as a string, otherwise returns nothing.
      */
     public function display($return = false) {
+        global $PAGE;
+
         // Get the list of requested users.
         $search = optional_param($this->name . '_searchtext', '', PARAM_RAW);
         if (optional_param($this->name . '_clearbutton', false, PARAM_BOOL)) {
@@ -220,7 +224,8 @@ abstract class user_selector_base {
             $output .= $this->option_checkbox('autoselectunique', $this->autoselectunique, get_string('userselectorautoselectunique'));
             $output .= $this->option_checkbox('searchanywhere', $this->searchanywhere, get_string('userselectorsearchanywhere'));
             $output .= print_collapsible_region_end(true);
-            $output .= print_js_call('new user_selector_options_tracker', array(), true);
+
+            $PAGE->requires->js_function_call('new user_selector_options_tracker');
             user_selector_base::$searchoptionsoutput = true;
         }
         $output .= "</div>\n</div>\n\n";
@@ -621,7 +626,7 @@ abstract class user_selector_base {
      * @return any HTML needed here.
      */
     protected function initialise_javascript($search) {
-        global $USER;
+        global $USER, $PAGE;
         $output = '';
 
         // Put the options into the session, to allow search.php to respond to the ajax requests.
@@ -630,7 +635,7 @@ abstract class user_selector_base {
         $USER->userselectors[$hash] = $options;
 
         // Initialise the selector.
-        $output .= print_js_call('new user_selector', array($this->name, $hash, $this->extrafields,
+        $PAGE->requires->js_function_call('new user_selector', array($this->name, $hash, $this->extrafields,
                 $search, get_string('previouslyselectedusers', '', '%%SEARCHTERM%%'),
                 get_string('nomatchingusers', '', '%%SEARCHTERM%%'), get_string('none')), true);