[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yui/build/moodle-core-tooltip/ -> moodle-core-tooltip-debug.js (source)

   1  YUI.add('moodle-core-tooltip', function (Y, NAME) {
   2  
   3  /**
   4   * Provides the base tooltip class.
   5   *
   6   * @module moodle-core-tooltip
   7   */
   8  
   9  /**
  10   * A base class for a tooltip.
  11   *
  12   * @param {Object} config Object literal specifying tooltip configuration properties.
  13   * @class M.core.tooltip
  14   * @constructor
  15   * @extends M.core.dialogue
  16   */
  17  function TOOLTIP(config) {
  18      if (!config) {
  19          config = {};
  20      }
  21  
  22      // Override the default options provided by the parent class.
  23      if (typeof config.draggable === 'undefined') {
  24          config.draggable = true;
  25      }
  26  
  27      if (typeof config.constrain === 'undefined') {
  28          config.constrain = true;
  29      }
  30  
  31      TOOLTIP.superclass.constructor.apply(this, [config]);
  32  }
  33  
  34  var SELECTORS = {
  35          CLOSEBUTTON: '.closebutton'
  36      },
  37  
  38      CSS = {
  39          PANELTEXT: 'tooltiptext'
  40      },
  41      RESOURCES = {
  42          WAITICON: {
  43              pix: 'i/loading_small',
  44              component: 'moodle'
  45          }
  46      },
  47      ATTRS = {};
  48  
  49  /**
  50   * Static property provides a string to identify the JavaScript class.
  51   *
  52   * @property NAME
  53   * @type String
  54   * @static
  55   */
  56  TOOLTIP.NAME = 'moodle-core-tooltip';
  57  
  58  /**
  59   * Static property used to define the CSS prefix applied to tooltip dialogues.
  60   *
  61   * @property CSS_PREFIX
  62   * @type String
  63   * @static
  64   */
  65  TOOLTIP.CSS_PREFIX = 'moodle-dialogue';
  66  
  67  /**
  68   * Static property used to define the default attribute configuration for the Tooltip.
  69   *
  70   * @property ATTRS
  71   * @type String
  72   * @static
  73   */
  74  TOOLTIP.ATTRS = ATTRS;
  75  
  76  /**
  77   * The initial value of the header region before the content finishes loading.
  78   *
  79   * @attribute initialheadertext
  80   * @type String
  81   * @default ''
  82   * @writeOnce
  83   */
  84  ATTRS.initialheadertext = {
  85      value: ''
  86  };
  87  
  88  /**
  89    * The initial value of the body region before the content finishes loading.
  90    *
  91    * The supplid string will be wrapped in a div with the CSS.PANELTEXT class and a standard Moodle spinner
  92    * appended.
  93    *
  94    * @attribute initialbodytext
  95    * @type String
  96    * @default ''
  97    * @writeOnce
  98    */
  99  ATTRS.initialbodytext = {
 100      value: '',
 101      setter: function(content) {
 102          var parentnode,
 103              spinner;
 104          parentnode = Y.Node.create('<div />')
 105              .addClass(CSS.PANELTEXT);
 106  
 107          spinner = Y.Node.create('<img />')
 108              .setAttribute('src', M.util.image_url(RESOURCES.WAITICON.pix, RESOURCES.WAITICON.component))
 109              .addClass('spinner');
 110  
 111          if (content) {
 112              // If we have been provided with content, add it to the parent and make
 113              // the spinner appear correctly inline
 114              parentnode.set('text', content);
 115              spinner.addClass('iconsmall');
 116          } else {
 117              // If there is no loading message, just make the parent node a lightbox
 118              parentnode.addClass('content-lightbox');
 119          }
 120  
 121          parentnode.append(spinner);
 122          return parentnode;
 123      }
 124  };
 125  
 126  /**
 127   * The initial value of the footer region before the content finishes loading.
 128   *
 129   * If a value is supplied, it will be wrapped in a <div> first.
 130   *
 131   * @attribute initialfootertext
 132   * @type String
 133   * @default ''
 134   * @writeOnce
 135   */
 136  ATTRS.initialfootertext = {
 137      value: null,
 138      setter: function(content) {
 139          if (content) {
 140              return Y.Node.create('<div />')
 141                  .set('text', content);
 142          }
 143      }
 144  };
 145  
 146  /**
 147   * The function which handles setting the content of the title region.
 148   * The specified function will be called with a context of the tooltip instance.
 149   *
 150   * The default function will simply set the value of the title to object.heading as returned by the AJAX call.
 151   *
 152   * @attribute headerhandler
 153   * @type Function|String|null
 154   * @default set_header_content
 155   */
 156  ATTRS.headerhandler = {
 157      value: 'set_header_content'
 158  };
 159  
 160  /**
 161   * The function which handles setting the content of the body region.
 162   * The specified function will be called with a context of the tooltip instance.
 163   *
 164   * The default function will simply set the value of the body area to a div containing object.text as returned
 165   * by the AJAX call.
 166   *
 167   * @attribute bodyhandler
 168   * @type Function|String|null
 169   * @default set_body_content
 170   */
 171  ATTRS.bodyhandler = {
 172      value: 'set_body_content'
 173  };
 174  
 175  /**
 176   * The function which handles setting the content of the footer region.
 177   * The specified function will be called with a context of the tooltip instance.
 178   *
 179   * By default, the footer is not set.
 180   *
 181   * @attribute footerhandler
 182   * @type Function|String|null
 183   * @default null
 184   */
 185  ATTRS.footerhandler = {
 186      value: null
 187  };
 188  
 189  /**
 190   * The function which handles modifying the URL that was clicked on.
 191   *
 192   * The default function rewrites '.php' to '_ajax.php'.
 193   *
 194   * @attribute urlmodifier
 195   * @type Function|String|null
 196   * @default null
 197   */
 198  ATTRS.urlmodifier = {
 199      value: null
 200  };
 201  
 202  /**
 203   * Set the Y.Cache object to use.
 204   *
 205   * By default a new Y.Cache object will be created for each instance of the tooltip.
 206   *
 207   * In certain situations, where multiple tooltips may share the same cache, it may be preferable to
 208   * seed this cache from the calling method.
 209   *
 210   * @attribute textcache
 211   * @type Y.Cache|null
 212   * @default null
 213   */
 214  ATTRS.textcache = {
 215      value: null
 216  };
 217  
 218  /**
 219   * Set the default size of the Y.Cache object.
 220   *
 221   * This is only used if no textcache is specified.
 222   *
 223   * @attribute textcachesize
 224   * @type Number
 225   * @default 10
 226   */
 227  ATTRS.textcachesize = {
 228      value: 10
 229  };
 230  
 231  Y.extend(TOOLTIP, M.core.dialogue, {
 232      // The bounding box.
 233      bb: null,
 234  
 235      // Any event listeners we may need to cancel later.
 236      listenevents: [],
 237  
 238      // Cache of objects we've already retrieved.
 239      textcache: null,
 240  
 241      // The align position. This differs for RTL languages so we calculate once and store.
 242      alignpoints: [
 243          Y.WidgetPositionAlign.TL,
 244          Y.WidgetPositionAlign.RC
 245      ],
 246  
 247      initializer: function() {
 248          // Set the initial values for the handlers.
 249          // These cannot be set in the attributes section as context isn't present at that time.
 250          if (!this.get('headerhandler')) {
 251              this.set('headerhandler', this.set_header_content);
 252          }
 253          if (!this.get('bodyhandler')) {
 254              this.set('bodyhandler', this.set_body_content);
 255          }
 256          if (!this.get('footerhandler')) {
 257              this.set('footerhandler', function() {});
 258          }
 259          if (!this.get('urlmodifier')) {
 260              this.set('urlmodifier', this.modify_url);
 261          }
 262  
 263          // Set up the dialogue with initial content.
 264          this.setAttrs({
 265              headerContent: this.get('initialheadertext'),
 266              bodyContent: this.get('initialbodytext'),
 267              footerContent: this.get('initialfootertext')
 268          });
 269  
 270          // Hide and then render the dialogue.
 271          this.hide();
 272          this.render();
 273  
 274          // Hook into a few useful areas.
 275          this.bb = this.get('boundingBox');
 276  
 277          // Add an additional class to the boundingbox to allow tooltip-specific style to be
 278          // set.
 279          this.bb.addClass('moodle-dialogue-tooltip');
 280  
 281          // Change the alignment if this is an RTL language.
 282          if (window.right_to_left()) {
 283              this.alignpoints = [
 284                  Y.WidgetPositionAlign.TR,
 285                  Y.WidgetPositionAlign.LC
 286              ];
 287          }
 288  
 289          // Set up the text cache if it's not set up already.
 290          if (!this.get('textcache')) {
 291              this.set('textcache', new Y.Cache({
 292                  // Set a reasonable maximum cache size to prevent memory growth.
 293                  max: this.get('textcachesize')
 294              }));
 295          }
 296  
 297          // Disable the textcache when in developerdebug.
 298          if (M.cfg.developerdebug) {
 299              this.get('textcache').set('max', 0);
 300          }
 301  
 302          return this;
 303      },
 304  
 305      /**
 306       * Display the tooltip for the clicked link.
 307       *
 308       * The anchor for the clicked link is used.
 309       *
 310       * @method display_panel
 311       * @param {EventFacade} e The event from the clicked link. This is used to determine the clicked URL.
 312       */
 313      display_panel: function(e) {
 314          var clickedlink, thisevent, ajaxurl, config, cacheentry;
 315  
 316          // Prevent the default click action and prevent the event triggering anything else.
 317          e.preventDefault();
 318  
 319          // Cancel any existing listeners and close the panel if it's already open.
 320          this.cancel_events();
 321  
 322          // Grab the clickedlink - this contains the URL we fetch and we align the panel to it.
 323          clickedlink = e.target.ancestor('a', true);
 324  
 325          // Reset the initial text to a spinner while we retrieve the text.
 326          this.setAttrs({
 327              headerContent: this.get('initialheadertext'),
 328              bodyContent: this.get('initialbodytext'),
 329              footerContent: this.get('initialfootertext')
 330          });
 331  
 332          // Now that initial setup has begun, show the panel.
 333          this.show(e);
 334  
 335          // Align with the link that was clicked.
 336          this.align(clickedlink, this.alignpoints);
 337  
 338          // Add some listen events to close on.
 339          thisevent = this.bb.delegate('click', this.close_panel, SELECTORS.CLOSEBUTTON, this);
 340          this.listenevents.push(thisevent);
 341  
 342          thisevent = Y.one('body').on('key', this.close_panel, 'esc', this);
 343          this.listenevents.push(thisevent);
 344  
 345          // Listen for mousedownoutside events - clickoutside is broken on IE.
 346          thisevent = this.bb.on('mousedownoutside', this.close_panel, this);
 347          this.listenevents.push(thisevent);
 348  
 349          // Modify the URL as required.
 350          ajaxurl = Y.bind(this.get('urlmodifier'), this, clickedlink.get('href'))();
 351  
 352          cacheentry = this.get('textcache').retrieve(ajaxurl);
 353          if (cacheentry) {
 354              // The data from this help call was already cached so use that and avoid an AJAX call.
 355              this._set_panel_contents(cacheentry.response);
 356          } else {
 357              // Retrieve the actual help text we should use.
 358              config = {
 359                  method: 'get',
 360                  context: this,
 361                  sync: false,
 362                  on: {
 363                      complete: function(tid, response) {
 364                          this._set_panel_contents(response.responseText, ajaxurl);
 365                      }
 366                  }
 367              };
 368  
 369              Y.io(ajaxurl, config);
 370          }
 371      },
 372  
 373      _set_panel_contents: function(response, ajaxurl) {
 374          var responseobject;
 375  
 376          // Attempt to parse the response into an object.
 377          try {
 378              responseobject = Y.JSON.parse(response);
 379              if (responseobject.error) {
 380                  this.close_panel();
 381                  Y.use('moodle-core-notification-ajaxexception', function() {
 382                      return new M.core.ajaxException(responseobject).show();
 383                  });
 384                  return this;
 385              }
 386          } catch (error) {
 387              this.close_panel();
 388              Y.use('moodle-core-notification-exception', function() {
 389                  return new M.core.exception(error).show();
 390              });
 391              return this;
 392          }
 393  
 394          // Set the contents using various handlers.
 395          // We must use Y.bind to ensure that the correct context is used when the default handlers are overridden.
 396          Y.bind(this.get('headerhandler'), this, responseobject)();
 397          Y.bind(this.get('bodyhandler'), this, responseobject)();
 398          Y.bind(this.get('footerhandler'), this, responseobject)();
 399  
 400          if (ajaxurl) {
 401              // Ensure that this data is added to the cache.
 402              this.get('textcache').add(ajaxurl, response);
 403          }
 404  
 405          this.get('buttons').header[0].focus();
 406      },
 407  
 408      set_header_content: function(responseobject) {
 409          this.set('headerContent', responseobject.heading);
 410      },
 411  
 412      set_body_content: function(responseobject) {
 413          var bodycontent = Y.Node.create('<div />')
 414              .set('innerHTML', responseobject.text)
 415              .setAttribute('role', 'alert')
 416              .addClass(CSS.PANELTEXT);
 417          this.set('bodyContent', bodycontent);
 418      },
 419  
 420      modify_url: function(url) {
 421          return url.replace(/\.php\?/, '_ajax.php?');
 422      },
 423  
 424      close_panel: function(e) {
 425          // Hide the panel first.
 426          this.hide(e);
 427  
 428          // Cancel the listeners that we added in display_panel.
 429          this.cancel_events();
 430  
 431          // Prevent any default click that the close button may have.
 432          if (e) {
 433              e.preventDefault();
 434          }
 435      },
 436  
 437      cancel_events: function() {
 438          // Detach all listen events to prevent duplicate triggers.
 439          var thisevent;
 440          while (this.listenevents.length) {
 441              thisevent = this.listenevents.shift();
 442              thisevent.detach();
 443          }
 444      }
 445  });
 446  
 447  Y.Base.modifyAttrs(TOOLTIP, {
 448      /**
 449       * Whether the widget should be modal or not.
 450       *
 451       * Moodle override: We override this for tooltip to default it to false.
 452       *
 453       * @attribute Modal
 454       * @type Boolean
 455       * @default false
 456       */
 457      modal: {
 458          value: false
 459      },
 460  
 461      focusOnPreviousTargetAfterHide: {
 462          value: true
 463      }
 464  });
 465  
 466  M.core = M.core || {};
 467  M.core.tooltip = M.core.tooltip = TOOLTIP;
 468  
 469  
 470  }, '@VERSION@', {
 471      "requires": [
 472          "base",
 473          "node",
 474          "io-base",
 475          "moodle-core-notification-dialogue",
 476          "json-parse",
 477          "widget-position",
 478          "widget-position-align",
 479          "event-outside",
 480          "cache-base"
 481      ]
 482  });


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1