[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/editor/atto/plugins/equation/yui/src/button/js/ -> button.js (source)

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


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