[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/ -> moodle-atto_equation-button.js (source)

   1  YUI.add('moodle-atto_equation-button', function (Y, NAME) {
   2  
   3  // This file is part of Moodle - http://moodle.org/
   4  //
   5  // Moodle is free software: you can redistribute it and/or modify
   6  // it under the terms of the GNU General Public License as published by
   7  // the Free Software Foundation, either version 3 of the License, or
   8  // (at your option) any later version.
   9  //
  10  // Moodle is distributed in the hope that it will be useful,
  11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13  // GNU General Public License for more details.
  14  //
  15  // You should have received a copy of the GNU General Public License
  16  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  17  
  18  /**
  19   * @package    atto_equation
  20   * @copyright  2013 Damyon Wiese  <damyon@moodle.com>
  21   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  22   */
  23  
  24  /**
  25   * Atto text editor equation plugin.
  26   */
  27  
  28  /**
  29   * Atto equation editor.
  30   *
  31   * @namespace M.atto_equation
  32   * @class Button
  33   * @extends M.editor_atto.EditorPlugin
  34   */
  35  var COMPONENTNAME = 'atto_equation',
  36      LOGNAME = 'atto_equation',
  37      CSS = {
  38          EQUATION_TEXT: 'atto_equation_equation',
  39          EQUATION_PREVIEW: 'atto_equation_preview',
  40          SUBMIT: 'atto_equation_submit',
  41          LIBRARY: 'atto_equation_library',
  42          LIBRARY_GROUPS: 'atto_equation_groups',
  43          LIBRARY_GROUP_PREFIX: 'atto_equation_group'
  44      },
  45      SELECTORS = {
  46          LIBRARY: '.' + CSS.LIBRARY,
  47          LIBRARY_GROUP: '.' + CSS.LIBRARY_GROUPS + ' > div > div',
  48          EQUATION_TEXT: '.' + CSS.EQUATION_TEXT,
  49          EQUATION_PREVIEW: '.' + CSS.EQUATION_PREVIEW,
  50          SUBMIT: '.' + CSS.SUBMIT,
  51          LIBRARY_BUTTON: '.' + CSS.LIBRARY + ' button'
  52      },
  53      DELIMITERS = {
  54          START: '\\(',
  55          END: '\\)'
  56      },
  57      TEMPLATES = {
  58          FORM: '' +
  59              '<form class="atto_form">' +
  60                  '{{{library}}}' +
  61                  '<label for="{{elementid}}_{{CSS.EQUATION_TEXT}}">{{{get_string "editequation" component texdocsurl}}}</label>' +
  62                  '<textarea class="fullwidth {{CSS.EQUATION_TEXT}}" ' +
  63                          'id="{{elementid}}_{{CSS.EQUATION_TEXT}}" rows="8"></textarea><br/>' +
  64                  '<label for="{{elementid}}_{{CSS.EQUATION_PREVIEW}}">{{get_string "preview" component}}</label>' +
  65                  '<div describedby="{{elementid}}_cursorinfo" class="well well-small fullwidth {{CSS.EQUATION_PREVIEW}}" ' +
  66                          'id="{{elementid}}_{{CSS.EQUATION_PREVIEW}}"></div>' +
  67                  '<div id="{{elementid}}_cursorinfo">{{get_string "cursorinfo" component}}</div>' +
  68                  '<div class="mdl-align">' +
  69                      '<br/>' +
  70                      '<button class="{{CSS.SUBMIT}}">{{get_string "saveequation" component}}</button>' +
  71                  '</div>' +
  72              '</form>',
  73          LIBRARY: '' +
  74              '<div class="{{CSS.LIBRARY}}">' +
  75                  '<ul>' +
  76                      '{{#each library}}' +
  77                          '<li><a href="#{{../elementid}}_{{../CSS.LIBRARY_GROUP_PREFIX}}_{{@key}}">' +
  78                              '{{get_string groupname ../component}}' +
  79                          '</a></li>' +
  80                      '{{/each}}' +
  81                  '</ul>' +
  82                  '<div class="{{CSS.LIBRARY_GROUPS}}">' +
  83                      '{{#each library}}' +
  84                          '<div id="{{../elementid}}_{{../CSS.LIBRARY_GROUP_PREFIX}}_{{@key}}">' +
  85                              '<div role="toolbar">' +
  86                              '{{#split "\n" elements}}' +
  87                                  '<button tabindex="-1" data-tex="{{this}}" aria-label="{{this}}" title="{{this}}">' +
  88                                      '{{../../DELIMITERS.START}}{{this}}{{../../DELIMITERS.END}}' +
  89                                  '</button>' +
  90                              '{{/split}}' +
  91                              '</div>' +
  92                          '</div>' +
  93                      '{{/each}}' +
  94                  '</div>' +
  95              '</div>'
  96      };
  97  
  98  Y.namespace('M.atto_equation').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], {
  99  
 100      /**
 101       * The selection object returned by the browser.
 102       *
 103       * @property _currentSelection
 104       * @type Range
 105       * @default null
 106       * @private
 107       */
 108      _currentSelection: null,
 109  
 110      /**
 111       * The cursor position in the equation textarea.
 112       *
 113       * @property _lastCursorPos
 114       * @type Number
 115       * @default 0
 116       * @private
 117       */
 118      _lastCursorPos: 0,
 119  
 120      /**
 121       * A reference to the dialogue content.
 122       *
 123       * @property _content
 124       * @type Node
 125       * @private
 126       */
 127      _content: null,
 128  
 129      /**
 130       * The source equation we are editing in the text.
 131       *
 132       * @property _sourceEquation
 133       * @type Object
 134       * @private
 135       */
 136      _sourceEquation: null,
 137  
 138      /**
 139       * A reference to the tab focus set on each group.
 140       *
 141       * The keys are the IDs of the group, the value is the Node on which the focus is set.
 142       *
 143       * @property _groupFocus
 144       * @type Object
 145       * @private
 146       */
 147      _groupFocus: null,
 148  
 149      /**
 150       * Regular Expression patterns used to pick out the equations in a String.
 151       *
 152       * @property _equationPatterns
 153       * @type Array
 154       * @private
 155       */
 156      _equationPatterns: [
 157          // We use space or not space because . does not match new lines.
 158          // $$ blah $$.
 159          /\$\$([\S\s]+?)\$\$/,
 160          // E.g. "\( blah \)".
 161          /\\\(([\S\s]+?)\\\)/,
 162          // E.g. "\[ blah \]".
 163          /\\\[([\S\s]+?)\\\]/,
 164          // E.g. "[tex] blah [/tex]".
 165          /\[tex\]([\S\s]+?)\[\/tex\]/
 166      ],
 167  
 168      initializer: function() {
 169          this._groupFocus = {};
 170  
 171          // If there is a tex filter active - enable this button.
 172          if (this.get('texfilteractive')) {
 173              // Add the button to the toolbar.
 174              this.addButton({
 175                  icon: 'e/math',
 176                  callback: this._displayDialogue
 177              });
 178  
 179              // We need custom highlight logic for this button.
 180              this.get('host').on('atto:selectionchanged', function() {
 181                  if (this._resolveEquation()) {
 182                      this.highlightButtons();
 183                  } else {
 184                      this.unHighlightButtons();
 185                  }
 186              }, this);
 187  
 188              // We need to convert these to a non dom node based format.
 189              this.editor.all('tex').each(function(texNode) {
 190                  var replacement = Y.Node.create('<span>' +
 191                          DELIMITERS.START + ' ' + texNode.get('text') + ' ' + DELIMITERS.END +
 192                          '</span>');
 193                  texNode.replace(replacement);
 194              });
 195          }
 196  
 197      },
 198  
 199      /**
 200       * Display the equation editor.
 201       *
 202       * @method _displayDialogue
 203       * @private
 204       */
 205      _displayDialogue: function() {
 206          this._currentSelection = this.get('host').getSelection();
 207  
 208          if (this._currentSelection === false) {
 209              return;
 210          }
 211  
 212          // This needs to be done before the dialogue is opened because the focus will shift to the dialogue.
 213          var equation = this._resolveEquation();
 214  
 215          var dialogue = this.getDialogue({
 216              headerContent: M.util.get_string('pluginname', COMPONENTNAME),
 217              focusAfterHide: true,
 218              width: 600,
 219              focusOnShowSelector: SELECTORS.EQUATION_TEXT
 220          });
 221  
 222          var content = this._getDialogueContent();
 223          dialogue.set('bodyContent', content);
 224  
 225          var library = content.one(SELECTORS.LIBRARY);
 226  
 227          var tabview = new Y.TabView({
 228              srcNode: library
 229          });
 230  
 231          tabview.render();
 232          dialogue.show();
 233          // Notify the filters about the modified nodes.
 234          require(['core/event'], function(event) {
 235              event.notifyFilterContentUpdated(dialogue.get('boundingBox').getDOMNode());
 236          });
 237  
 238          if (equation) {
 239              content.one(SELECTORS.EQUATION_TEXT).set('text', equation);
 240          }
 241          this._updatePreview(false);
 242      },
 243  
 244      /**
 245       * If there is selected text and it is part of an equation,
 246       * extract the equation (and set it in the form).
 247       *
 248       * @method _resolveEquation
 249       * @private
 250       * @return {String|Boolean} The equation or false.
 251       */
 252      _resolveEquation: function() {
 253  
 254          // Find the equation in the surrounding text.
 255          var selectedNode = this.get('host').getSelectionParentNode(),
 256              selection = this.get('host').getSelection(),
 257              text,
 258              returnValue = false;
 259  
 260          // Prevent resolving equations when we don't have focus.
 261          if (!this.get('host').isActive()) {
 262              return false;
 263          }
 264  
 265          // Note this is a document fragment and YUI doesn't like them.
 266          if (!selectedNode) {
 267              return false;
 268          }
 269  
 270          // We don't yet have a cursor selection somehow so we can't possible be resolving an equation that has selection.
 271          if (!selection || selection.length === 0) {
 272              return false;
 273          }
 274  
 275          this.sourceEquation = null;
 276  
 277          selection = selection[0];
 278  
 279          text = Y.one(selectedNode).get('text');
 280  
 281          // For each of these patterns we have a RegExp which captures the inner component of the equation but also
 282          // includes the delimiters.
 283          // We first run the RegExp adding the global flag ("g"). This ignores the capture, instead matching the entire
 284          // equation including delimiters and returning one entry per match of the whole equation.
 285          // We have to deal with multiple occurences of the same equation in a String so must be able to loop on the
 286          // match results.
 287          Y.Array.find(this._equationPatterns, function(pattern) {
 288              // For each pattern in turn, find all whole matches (including the delimiters).
 289              var patternMatches = text.match(new RegExp(pattern.source, "g"));
 290  
 291              if (patternMatches && patternMatches.length) {
 292                  // This pattern matches at least once. See if this pattern matches our current position.
 293                  // Note: We return here to break the Y.Array.find loop - any truthy return will stop any subsequent
 294                  // searches which is the required behaviour of this function.
 295                  return Y.Array.find(patternMatches, function(match) {
 296                      // Check each occurrence of this match.
 297                      var startIndex = 0;
 298                      while (text.indexOf(match, startIndex) !== -1) {
 299                          // Determine whether the cursor is in the current occurrence of this string.
 300                          // Note: We do not support a selection exceeding the bounds of an equation.
 301                          var startOuter = text.indexOf(match, startIndex),
 302                              endOuter = startOuter + match.length,
 303                              startMatch = (selection.startOffset >= startOuter && selection.startOffset < endOuter),
 304                              endMatch = (selection.endOffset <= endOuter && selection.endOffset > startOuter);
 305  
 306                          if (startMatch && endMatch) {
 307                              // This match is in our current position - fetch the innerMatch data.
 308                              var innerMatch = match.match(pattern);
 309                              if (innerMatch && innerMatch.length) {
 310                                  // We need the start and end of the inner match for later.
 311                                  var startInner = text.indexOf(innerMatch[1], startOuter),
 312                                      endInner = startInner + innerMatch[1].length;
 313  
 314                                  // We'll be returning the inner match for use in the editor itself.
 315                                  returnValue = innerMatch[1];
 316  
 317                                  // Save all data for later.
 318                                  this.sourceEquation = {
 319                                      // Outer match data.
 320                                      startOuterPosition: startOuter,
 321                                      endOuterPosition: endOuter,
 322                                      outerMatch: match,
 323  
 324                                      // Inner match data.
 325                                      startInnerPosition: startInner,
 326                                      endInnerPosition: endInner,
 327                                      innerMatch: innerMatch
 328                                  };
 329  
 330                                  // This breaks out of both Y.Array.find functions.
 331                                  return true;
 332                              }
 333                          }
 334  
 335                          // Update the startIndex to match the end of the current match so that we can continue hunting
 336                          // for further matches.
 337                          startIndex = endOuter;
 338                      }
 339                  }, this);
 340              }
 341          }, this);
 342  
 343          // We trim the equation when we load it and then add spaces when we save it.
 344          if (returnValue !== false) {
 345              returnValue = returnValue.trim();
 346          }
 347          return returnValue;
 348      },
 349  
 350      /**
 351       * Handle insertion of a new equation, or update of an existing one.
 352       *
 353       * @method _setEquation
 354       * @param {EventFacade} e
 355       * @private
 356       */
 357      _setEquation: function(e) {
 358          var input,
 359              selectedNode,
 360              text,
 361              value,
 362              host,
 363              newText;
 364  
 365          host = this.get('host');
 366  
 367          e.preventDefault();
 368          this.getDialogue({
 369              focusAfterHide: null
 370          }).hide();
 371  
 372          input = e.currentTarget.ancestor('.atto_form').one('textarea');
 373  
 374          value = input.get('value');
 375          if (value !== '') {
 376              host.setSelection(this._currentSelection);
 377  
 378              if (this.sourceEquation) {
 379                  // Replace the equation.
 380                  selectedNode = Y.one(host.getSelectionParentNode());
 381                  text = selectedNode.get('text');
 382                  value = ' ' + value + ' ';
 383                  newText = text.slice(0, this.sourceEquation.startInnerPosition) +
 384                              value +
 385                              text.slice(this.sourceEquation.endInnerPosition);
 386  
 387                  selectedNode.set('text', newText);
 388              } else {
 389                  // Insert the new equation.
 390                  value = DELIMITERS.START + ' ' + value + ' ' + DELIMITERS.END;
 391                  host.insertContentAtFocusPoint(value);
 392              }
 393  
 394              // Clean the YUI ids from the HTML.
 395              this.markUpdated();
 396          }
 397      },
 398  
 399      /**
 400       * Smart throttle, only call a function every delay milli seconds,
 401       * and always run the last call. Y.throttle does not work here,
 402       * because it calls the function immediately, the first time, and then
 403       * ignores repeated calls within X seconds. This does not guarantee
 404       * that the last call will be executed (which is required here).
 405       *
 406       * @param {function} fn
 407       * @param {Number} delay Delay in milliseconds
 408       * @method _throttle
 409       * @private
 410       */
 411      _throttle: function(fn, delay) {
 412          var timer = null;
 413          return function() {
 414              var context = this, args = arguments;
 415              clearTimeout(timer);
 416              timer = setTimeout(function() {
 417                fn.apply(context, args);
 418              }, delay);
 419          };
 420      },
 421  
 422      /**
 423       * Update the preview div to match the current equation.
 424       *
 425       * @param {EventFacade} e
 426       * @method _updatePreview
 427       * @private
 428       */
 429      _updatePreview: function(e) {
 430          var textarea = this._content.one(SELECTORS.EQUATION_TEXT),
 431              equation = textarea.get('value'),
 432              url,
 433              currentPos = textarea.get('selectionStart'),
 434              prefix = '',
 435              cursorLatex = '\\Downarrow ',
 436              isChar,
 437              params;
 438  
 439          if (e) {
 440              e.preventDefault();
 441          }
 442  
 443          // Move the cursor so it does not break expressions.
 444          // Start at the very beginning.
 445          if (!currentPos) {
 446              currentPos = 0;
 447          }
 448  
 449          // First move back to the beginning of the line.
 450          while (equation.charAt(currentPos) === '\\' && currentPos >= 0) {
 451              currentPos -= 1;
 452          }
 453          isChar = /[a-zA-Z\{\}]/;
 454          if (currentPos !== 0) {
 455              // Now match to the end of the line.
 456              while (isChar.test(equation.charAt(currentPos)) &&
 457                     currentPos < equation.length &&
 458                     isChar.test(equation.charAt(currentPos - 1))) {
 459                  currentPos += 1;
 460              }
 461          }
 462          // Save the cursor position - for insertion from the library.
 463          this._lastCursorPos = currentPos;
 464          equation = prefix + equation.substring(0, currentPos) + cursorLatex + equation.substring(currentPos);
 465  
 466          equation = DELIMITERS.START + ' ' + equation + ' ' + DELIMITERS.END;
 467          // Make an ajax request to the filter.
 468          url = M.cfg.wwwroot + '/lib/editor/atto/plugins/equation/ajax.php';
 469          params = {
 470              sesskey: M.cfg.sesskey,
 471              contextid: this.get('contextid'),
 472              action: 'filtertext',
 473              text: equation
 474          };
 475  
 476          Y.io(url, {
 477              context: this,
 478              data: params,
 479              timeout: 500,
 480              on: {
 481                  complete: this._loadPreview
 482              }
 483          });
 484      },
 485  
 486      /**
 487       * Load returned preview text into preview
 488       *
 489       * @param {String} id
 490       * @param {EventFacade} e
 491       * @method _loadPreview
 492       * @private
 493       */
 494      _loadPreview: function(id, preview) {
 495          var previewNode = this._content.one(SELECTORS.EQUATION_PREVIEW);
 496  
 497          if (preview.status === 200) {
 498              previewNode.setHTML(preview.responseText);
 499  
 500              // Notify the filters about the modified nodes.
 501              require(['core/event'], function(event) {
 502                  event.notifyFilterContentUpdated(previewNode.getDOMNode());
 503              });
 504          }
 505      },
 506  
 507      /**
 508       * Return the dialogue content for the tool, attaching any required
 509       * events.
 510       *
 511       * @method _getDialogueContent
 512       * @return {Node}
 513       * @private
 514       */
 515      _getDialogueContent: function() {
 516          var library = this._getLibraryContent(),
 517              throttledUpdate = this._throttle(this._updatePreview, 500),
 518              template = Y.Handlebars.compile(TEMPLATES.FORM);
 519  
 520          this._content = Y.Node.create(template({
 521              elementid: this.get('host').get('elementid'),
 522              component: COMPONENTNAME,
 523              library: library,
 524              texdocsurl: this.get('texdocsurl'),
 525              CSS: CSS
 526          }));
 527  
 528          // Sets the default focus.
 529          this._content.all(SELECTORS.LIBRARY_GROUP).each(function(group) {
 530              // The first button gets the focus.
 531              this._setGroupTabFocus(group, group.one('button'));
 532              // Sometimes the filter adds an anchor in the button, no tabindex on that.
 533              group.all('button a').setAttribute('tabindex', '-1');
 534          }, this);
 535  
 536          // Keyboard navigation in groups.
 537          this._content.delegate('key', this._groupNavigation, 'down:37,39', SELECTORS.LIBRARY_BUTTON, this);
 538  
 539          this._content.one(SELECTORS.SUBMIT).on('click', this._setEquation, this);
 540          this._content.one(SELECTORS.EQUATION_TEXT).on('valuechange', throttledUpdate, this);
 541          this._content.one(SELECTORS.EQUATION_TEXT).on('mouseup', throttledUpdate, this);
 542          this._content.one(SELECTORS.EQUATION_TEXT).on('keyup', throttledUpdate, this);
 543          this._content.delegate('click', this._selectLibraryItem, SELECTORS.LIBRARY_BUTTON, this);
 544  
 545          return this._content;
 546      },
 547  
 548      /**
 549       * Callback handling the keyboard navigation in the groups of the library.
 550       *
 551       * @param {EventFacade} e The event.
 552       * @method _groupNavigation
 553       * @private
 554       */
 555      _groupNavigation: function(e) {
 556          e.preventDefault();
 557  
 558          var current = e.currentTarget,
 559              parent = current.get('parentNode'), // This must be the <div> containing all the buttons of the group.
 560              buttons = parent.all('button'),
 561              direction = e.keyCode !== 37 ? 1 : -1,
 562              index = buttons.indexOf(current),
 563              nextButton;
 564  
 565          if (index < 0) {
 566              index = 0;
 567          }
 568  
 569          index += direction;
 570          if (index < 0) {
 571              index = buttons.size() - 1;
 572          } else if (index >= buttons.size()) {
 573              index = 0;
 574          }
 575          nextButton = buttons.item(index);
 576  
 577          this._setGroupTabFocus(parent, nextButton);
 578          nextButton.focus();
 579      },
 580  
 581      /**
 582       * Sets tab focus for the group.
 583       *
 584       * @method _setGroupTabFocus
 585       * @param {Node} button The node that focus should now be set to.
 586       * @private
 587       */
 588      _setGroupTabFocus: function(parent, button) {
 589          var parentId = parent.generateID();
 590  
 591          // Unset the previous entry.
 592          if (typeof this._groupFocus[parentId] !== 'undefined') {
 593              this._groupFocus[parentId].setAttribute('tabindex', '-1');
 594          }
 595  
 596          // Set on the new entry.
 597          this._groupFocus[parentId] = button;
 598          button.setAttribute('tabindex', 0);
 599          parent.setAttribute('aria-activedescendant', button.generateID());
 600      },
 601  
 602      /**
 603       * Reponse to button presses in the TeX library panels.
 604       *
 605       * @method _selectLibraryItem
 606       * @param {EventFacade} e
 607       * @return {string}
 608       * @private
 609       */
 610      _selectLibraryItem: function(e) {
 611          var tex = e.currentTarget.getAttribute('data-tex'),
 612          oldValue,
 613          newValue,
 614          input,
 615          focusPoint = 0;
 616  
 617          e.preventDefault();
 618  
 619          // Set the group focus on the button.
 620          this._setGroupTabFocus(e.currentTarget.get('parentNode'), e.currentTarget);
 621  
 622          input = e.currentTarget.ancestor('.atto_form').one('textarea');
 623  
 624          oldValue = input.get('value');
 625  
 626          newValue = oldValue.substring(0, this._lastCursorPos);
 627          if (newValue.charAt(newValue.length - 1) !== ' ') {
 628              newValue += ' ';
 629          }
 630          newValue += tex;
 631          focusPoint = newValue.length;
 632  
 633          if (oldValue.charAt(this._lastCursorPos) !== ' ') {
 634              newValue += ' ';
 635          }
 636          newValue += oldValue.substring(this._lastCursorPos, oldValue.length);
 637  
 638          input.set('value', newValue);
 639          input.focus();
 640  
 641          var realInput = input.getDOMNode();
 642          if (typeof realInput.selectionStart === "number") {
 643              // Modern browsers have selectionStart and selectionEnd to control the cursor position.
 644              realInput.selectionStart = realInput.selectionEnd = focusPoint;
 645          } else if (typeof realInput.createTextRange !== "undefined") {
 646              // Legacy browsers (IE<=9) use createTextRange().
 647              var range = realInput.createTextRange();
 648              range.moveToPoint(focusPoint);
 649              range.select();
 650          }
 651          // Focus must be set before updating the preview for the cursor box to be in the correct location.
 652          this._updatePreview(false);
 653      },
 654  
 655      /**
 656       * Return the HTML for rendering the library of predefined buttons.
 657       *
 658       * @method _getLibraryContent
 659       * @return {string}
 660       * @private
 661       */
 662      _getLibraryContent: function() {
 663          var template = Y.Handlebars.compile(TEMPLATES.LIBRARY),
 664              library = this.get('library'),
 665              content = '';
 666  
 667          // Helper to iterate over a newline separated string.
 668          Y.Handlebars.registerHelper('split', function(delimiter, str, options) {
 669              var parts,
 670                  current,
 671                  out;
 672              if (typeof delimiter === "undefined" || typeof str === "undefined") {
 673                  return '';
 674              }
 675  
 676              out = '';
 677              parts = str.trim().split(delimiter);
 678              while (parts.length > 0) {
 679                  current = parts.shift().trim();
 680                  out += options.fn(current);
 681              }
 682  
 683              return out;
 684          });
 685          content = template({
 686              elementid: this.get('host').get('elementid'),
 687              component: COMPONENTNAME,
 688              library: library,
 689              CSS: CSS,
 690              DELIMITERS: DELIMITERS
 691          });
 692  
 693          var url = M.cfg.wwwroot + '/lib/editor/atto/plugins/equation/ajax.php';
 694          var params = {
 695              sesskey: M.cfg.sesskey,
 696              contextid: this.get('contextid'),
 697              action: 'filtertext',
 698              text: content
 699          };
 700  
 701          var preview = Y.io(url, {
 702              sync: true,
 703              data: params,
 704              method: 'POST'
 705          });
 706  
 707          if (preview.status === 200) {
 708              content = preview.responseText;
 709          }
 710          return content;
 711      }
 712  }, {
 713      ATTRS: {
 714          /**
 715           * Whether the TeX filter is currently active.
 716           *
 717           * @attribute texfilteractive
 718           * @type Boolean
 719           */
 720          texfilteractive: {
 721              value: false
 722          },
 723  
 724          /**
 725           * The contextid to use when generating this preview.
 726           *
 727           * @attribute contextid
 728           * @type String
 729           */
 730          contextid: {
 731              value: null
 732          },
 733  
 734          /**
 735           * The content of the example library.
 736           *
 737           * @attribute library
 738           * @type object
 739           */
 740          library: {
 741              value: {}
 742          },
 743  
 744          /**
 745           * The link to the Moodle Docs page about TeX.
 746           *
 747           * @attribute texdocsurl
 748           * @type string
 749           */
 750          texdocsurl: {
 751              value: null
 752          }
 753  
 754      }
 755  });
 756  
 757  
 758  }, '@VERSION@', {
 759      "requires": [
 760          "moodle-editor_atto-plugin",
 761          "moodle-core-event",
 762          "io",
 763          "event-valuechange",
 764          "tabview",
 765          "array-extras"
 766      ]
 767  });


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