MDL-35819 Improve performance of help tooltip
authorAndrew Robert Nicols <andrew.nicols@luns.net.uk>
Wed, 21 Nov 2012 09:31:41 +0000 (09:31 +0000)
committerAndrew Robert Nicols <andrew.nicols@luns.net.uk>
Thu, 22 Nov 2012 11:45:34 +0000 (11:45 +0000)
Rather than using an event handler for each help link, we add the
'helpicon' class to them and delegate the display function.

In order for this to work, we modify the way that Y.io fetches the help to
use the intended target of the anchor rather than a value provided in the
add call. We also no longer modify this URL and instead add the ajaxurl
parameter to it using the Y.io data parameter.

This change is backwards compatible with people calling it without using
the help icon renderer.

lib/javascript-static.js
lib/outputrenderers.php

index 8c274cd..bb63a99 100644 (file)
@@ -1413,14 +1413,20 @@ M.util.help_popups = {
 M.util.help_icon = {
     Y : null,
     instance : null,
-    add : function(Y, properties) {
-        this.Y = Y;
-        properties.node = Y.one('#'+properties.id);
-        if (properties.node) {
-            properties.node.on('click', this.display, this, properties);
+    initialised : false,
+    setup : function(Y) {
+        if (this.initialised) {
+            // Exit early if we have already completed setup
+            return;
         }
+        this.Y = Y;
+        Y.one('body').delegate('click', this.display, 'span.helplink a', this);
+        this.initialised = true;
     },
-    display : function(event, args) {
+    add : function(Y, properties) {
+        this.setup(Y);
+    },
+    display : function(event) {
         event.preventDefault();
         if (M.util.help_icon.instance === null) {
             var Y = M.util.help_icon.Y;
@@ -1450,7 +1456,7 @@ M.util.help_icon = {
                         //  Hide the menu if the user clicks outside of its content
                         boundingBox.get("ownerDocument").on("mousedown", function (event) {
                             var oTarget = event.target;
-                            var menuButton = Y.one("#"+args.id);
+                            var menuButton = this.helplink;
 
                             if (!oTarget.compareTo(menuButton) &&
                                 !menuButton.contains(oTarget) &&
@@ -1467,28 +1473,24 @@ M.util.help_icon = {
                         this.overlay.hide();
                     },
 
-                    display : function(event, args) {
-                        if (Y.one('html').get('dir') == 'rtl') {
-                            var overlayPosition = [Y.WidgetPositionAlign.TR, Y.WidgetPositionAlign.LC];
+                    display : function(event) {
+                        var overlayPosition;
+                        this.helplink = event.target.ancestor('span.helplink a', true);
+                        if (Y.one('html').get('dir') === 'rtl') {
+                            overlayPosition = [Y.WidgetPositionAlign.TR, Y.WidgetPositionAlign.LC];
                         } else {
-                            var overlayPosition = [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.RC];
+                            overlayPosition = [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.RC];
                         }
 
-                        this.helplink = args.node;
-
                         this.overlay.set('bodyContent', Y.Node.create('<img src="'+M.cfg.loadingicon+'" class="spinner" />'));
-                        this.overlay.set("align", {node:args.node, points: overlayPosition});
-
-                        var fullurl = args.url;
-                        if (!args.url.match(/https?:\/\//)) {
-                            fullurl = M.cfg.wwwroot + args.url;
-                        }
-
-                        var ajaxurl = fullurl + '&ajax=1';
+                        this.overlay.set("align", {node:this.helplink, points: overlayPosition});
 
                         var cfg = {
                             method: 'get',
                             context : this,
+                            data : {
+                                ajax : 1
+                            },
                             on: {
                                 success: function(id, o, node) {
                                     this.display_callback(o.responseText);
@@ -1503,7 +1505,7 @@ M.util.help_icon = {
                             }
                         };
 
-                        Y.io(ajaxurl, cfg);
+                        Y.io(this.helplink.get('href'), cfg);
                         this.overlay.show();
                     },
 
@@ -1519,10 +1521,10 @@ M.util.help_icon = {
                 };
                 help_content_overlay.init();
                 M.util.help_icon.instance = help_content_overlay;
-                M.util.help_icon.instance.display(event, args);
+                M.util.help_icon.instance.display(event);
             });
         } else {
-            M.util.help_icon.instance.display(event, args);
+            M.util.help_icon.instance.display(event);
         }
     },
     init : function(Y) {
index 1a0df04..b1083a9 100644 (file)
@@ -1804,11 +1804,9 @@ class core_renderer extends renderer_base {
         $title = get_string('helpprefix2', '', trim($title, ". \t"));
 
         $attributes = array('href'=>$url, 'title'=>$title, 'aria-haspopup' => 'true');
-        $id = html_writer::random_id('helpicon');
-        $attributes['id'] = $id;
         $output = html_writer::tag('a', $output, $attributes);
 
-        $this->page->requires->js_init_call('M.util.help_icon.add', array(array('id'=>$id, 'url'=>$url->out(false))));
+        $this->page->requires->js_init_call('M.util.help_icon.setup');
         $this->page->requires->string_for_js('close', 'form');
 
         // and finally span