[ Index ]

MailPress 7.1

[ Index ]     [ Classes ]     [ Functions ]     [ Variables ]     [ Constants ]     [ Statistics ]    

title

Body

[close]

/mp-includes/js/codemirror/js/ -> codemirror.js (source)

   1  /* CodeMirror main module (http://codemirror.net/)
   2   *
   3   * Implements the CodeMirror constructor and prototype, which take care
   4   * of initializing the editor frame, and providing the outside interface.
   5   */
   6  
   7  // The CodeMirrorConfig object is used to specify a default
   8  // configuration. If you specify such an object before loading this
   9  // file, the values you put into it will override the defaults given
  10  // below. You can also assign to it after loading.
  11  var CodeMirrorConfig = window.CodeMirrorConfig || {};
  12  
  13  var CodeMirror = (function(){
  14    function setDefaults(object, defaults) {
  15      for (var option in defaults) {
  16        if (!object.hasOwnProperty(option))
  17          object[option] = defaults[option];
  18      }
  19    }
  20    function forEach(array, action) {
  21      for (var i = 0; i < array.length; i++)
  22        action(array[i]);
  23    }
  24  
  25    // These default options can be overridden by passing a set of
  26    // options to a specific CodeMirror constructor. See manual.html for
  27    // their meaning.
  28    setDefaults(CodeMirrorConfig, {
  29      stylesheet: [],
  30      path: "",
  31      parserfile: [],
  32      basefiles: ["util.js", "stringstream.js", "select.js", "undo.js", "editor.js", "tokenize.js"],
  33      iframeClass: null,
  34      passDelay: 200,
  35      passTime: 50,
  36      lineNumberDelay: 200,
  37      lineNumberTime: 50,
  38      continuousScanning: false,
  39      saveFunction: null,
  40      onChange: null,
  41      undoDepth: 50,
  42      undoDelay: 800,
  43      disableSpellcheck: true,
  44      textWrapping: true,
  45      readOnly: false,
  46      width: "",
  47      height: "300px",
  48      minHeight: 100,
  49      autoMatchParens: false,
  50      parserConfig: null,
  51      tabMode: "indent", // or "spaces", "default", "shift"
  52      enterMode: "indent", // or "keep", "flat"
  53      electricChars: true,
  54      reindentOnLoad: false,
  55      activeTokens: null,
  56      cursorActivity: null,
  57      lineNumbers: false,
  58      firstLineNumber: 1,
  59      indentUnit: 2,
  60      domain: null
  61    });
  62  
  63    function addLineNumberDiv(container, firstNum) {
  64      var nums = document.createElement("DIV"),
  65          scroller = document.createElement("DIV");
  66      nums.style.position = "absolute";
  67      nums.style.height = "100%";
  68      if (nums.style.setExpression) {
  69        try {nums.style.setExpression("height", "this.previousSibling.offsetHeight + 'px'");}
  70        catch(e) {} // Seems to throw 'Not Implemented' on some IE8 versions
  71      }
  72      nums.style.top = "0px";
  73      nums.style.left = "0px";
  74      nums.style.overflow = "hidden";
  75      container.appendChild(nums);
  76      scroller.className = "CodeMirror-line-numbers";
  77      nums.appendChild(scroller);
  78      scroller.innerHTML = "<div>" + firstNum + "</div>";
  79      return nums;
  80    }
  81  
  82    function frameHTML(options) {
  83      if (typeof options.parserfile == "string")
  84        options.parserfile = [options.parserfile];
  85      if (typeof options.basefiles == "string")
  86        options.basefiles = [options.basefiles];
  87      if (typeof options.stylesheet == "string")
  88        options.stylesheet = [options.stylesheet];
  89  
  90      var html = ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\"><html><head>"];
  91      // Hack to work around a bunch of IE8-specific problems.
  92      html.push("<meta http-equiv=\"X-UA-Compatible\" content=\"IE=EmulateIE7\"/>");
  93      forEach(options.stylesheet, function(file) {
  94        html.push("<link rel=\"stylesheet\" type=\"text/css\" href=\"" + file + "\"/>");
  95      });
  96      forEach(options.basefiles.concat(options.parserfile), function(file) {
  97        if (!/^https?:/.test(file)) file = options.path + file;
  98        html.push("<script type=\"text/javascript\" src=\"" + file + "\"><" + "/script>");
  99      });
 100      html.push("</head><body style=\"border-width: 0;\" class=\"editbox\" spellcheck=\"" +
 101                (options.disableSpellcheck ? "false" : "true") + "\"></body></html>");
 102      return html.join("");
 103    }
 104  
 105    var internetExplorer = document.selection && window.ActiveXObject && /MSIE/.test(navigator.userAgent);
 106  
 107    function CodeMirror(place, options) {
 108      // Use passed options, if any, to override defaults.
 109      this.options = options = options || {};
 110      setDefaults(options, CodeMirrorConfig);
 111  
 112      // Backward compatibility for deprecated options.
 113      if (options.dumbTabs) options.tabMode = "spaces";
 114      else if (options.normalTab) options.tabMode = "default";
 115  
 116      var frame = this.frame = document.createElement("IFRAME");
 117      if (options.iframeClass) frame.className = options.iframeClass;
 118      frame.frameBorder = 0;
 119      frame.style.border = "0";
 120      frame.style.width = '100%';
 121      frame.style.height = '100%';
 122      // display: block occasionally suppresses some Firefox bugs, so we
 123      // always add it, redundant as it sounds.
 124      frame.style.display = "block";
 125  
 126      var div = this.wrapping = document.createElement("DIV");
 127      div.style.position = "relative";
 128      div.className = "CodeMirror-wrapping";
 129      div.style.width = options.width;
 130      div.style.height = (options.height == "dynamic") ? options.minHeight + "px" : options.height;
 131      // This is used by Editor.reroutePasteEvent
 132      var teHack = this.textareaHack = document.createElement("TEXTAREA");
 133      div.appendChild(teHack);
 134      teHack.style.position = "absolute";
 135      teHack.style.left = "-10000px";
 136      teHack.style.width = "10px";
 137  
 138      // Link back to this object, so that the editor can fetch options
 139      // and add a reference to itself.
 140      frame.CodeMirror = this;
 141      if (options.domain && internetExplorer) {
 142        this.html = frameHTML(options);
 143        frame.src = "javascript:(function(){document.open();" +
 144          (options.domain ? "document.domain=\"" + options.domain + "\";" : "") +
 145          "document.write(window.frameElement.CodeMirror.html);document.close();})()";
 146      }
 147      else {
 148        frame.src = "javascript:;";
 149      }
 150  
 151      if (place.appendChild) place.appendChild(div);
 152      else place(div);
 153      div.appendChild(frame);
 154      if (options.lineNumbers) this.lineNumbers = addLineNumberDiv(div, options.firstLineNumber);
 155  
 156      this.win = frame.contentWindow;
 157      if (!options.domain || !internetExplorer) {
 158        this.win.document.open();
 159        this.win.document.write(frameHTML(options));
 160        this.win.document.close();
 161      }
 162    }
 163  
 164    CodeMirror.prototype = {
 165      init: function() {
 166        if (this.options.initCallback) this.options.initCallback(this);
 167        if (this.options.lineNumbers) this.activateLineNumbers();
 168        if (this.options.reindentOnLoad) this.reindent();
 169        if (this.options.height == "dynamic") this.setDynamicHeight();
 170      },
 171  
 172      getCode: function() {return this.editor.getCode();},
 173      setCode: function(code) {this.editor.importCode(code);},
 174      selection: function() {this.focusIfIE(); return this.editor.selectedText();},
 175      reindent: function() {this.editor.reindent();},
 176      reindentSelection: function() {this.focusIfIE(); this.editor.reindentSelection(null);},
 177  
 178      focusIfIE: function() {
 179        // in IE, a lot of selection-related functionality only works when the frame is focused
 180        if (this.win.select.ie_selection) this.focus();
 181      },
 182      focus: function() {
 183        this.win.focus();
 184        if (this.editor.selectionSnapshot) // IE hack
 185          this.win.select.setBookmark(this.win.document.body, this.editor.selectionSnapshot);
 186      },
 187      replaceSelection: function(text) {
 188        this.focus();
 189        this.editor.replaceSelection(text);
 190        return true;
 191      },
 192      replaceChars: function(text, start, end) {
 193        this.editor.replaceChars(text, start, end);
 194      },
 195      getSearchCursor: function(string, fromCursor, caseFold) {
 196        return this.editor.getSearchCursor(string, fromCursor, caseFold);
 197      },
 198  
 199      undo: function() {this.editor.history.undo();},
 200      redo: function() {this.editor.history.redo();},
 201      historySize: function() {return this.editor.history.historySize();},
 202      clearHistory: function() {this.editor.history.clear();},
 203  
 204      grabKeys: function(callback, filter) {this.editor.grabKeys(callback, filter);},
 205      ungrabKeys: function() {this.editor.ungrabKeys();},
 206  
 207      setParser: function(name, parserConfig) {this.editor.setParser(name, parserConfig);},
 208      setSpellcheck: function(on) {this.win.document.body.spellcheck = on;},
 209      setStylesheet: function(names) {
 210        if (typeof names === "string") names = [names];
 211        var activeStylesheets = {};
 212        var matchedNames = {};
 213        var links = this.win.document.getElementsByTagName("link");
 214        // Create hashes of active stylesheets and matched names.
 215        // This is O(n^2) but n is expected to be very small.
 216        for (var x = 0, link; link = links[x]; x++) {
 217          if (link.rel.indexOf("stylesheet") !== -1) {
 218            for (var y = 0; y < names.length; y++) {
 219              var name = names[y];
 220              if (link.href.substring(link.href.length - name.length) === name) {
 221                activeStylesheets[link.href] = true;
 222                matchedNames[name] = true;
 223              }
 224            }
 225          }
 226        }
 227        // Activate the selected stylesheets and disable the rest.
 228        for (var x = 0, link; link = links[x]; x++) {
 229          if (link.rel.indexOf("stylesheet") !== -1) {
 230            link.disabled = !(link.href in activeStylesheets);
 231          }
 232        }
 233        // Create any new stylesheets.
 234        for (var y = 0; y < names.length; y++) {
 235          var name = names[y];
 236          if (!(name in matchedNames)) {
 237            var link = this.win.document.createElement("link");
 238            link.rel = "stylesheet";
 239            link.type = "text/css";
 240            link.href = name;
 241            this.win.document.getElementsByTagName('head')[0].appendChild(link);
 242          }
 243        }
 244      },
 245      setTextWrapping: function(on) {
 246        if (on == this.options.textWrapping) return;
 247        this.win.document.body.style.whiteSpace = on ? "" : "nowrap";
 248        this.options.textWrapping = on;
 249        if (this.lineNumbers) {
 250          this.setLineNumbers(false);
 251          this.setLineNumbers(true);
 252        }
 253      },
 254      setIndentUnit: function(unit) {this.win.indentUnit = unit;},
 255      setUndoDepth: function(depth) {this.editor.history.maxDepth = depth;},
 256      setTabMode: function(mode) {this.options.tabMode = mode;},
 257      setEnterMode: function(mode) {this.options.enterMode = mode;},
 258      setLineNumbers: function(on) {
 259        if (on && !this.lineNumbers) {
 260          this.lineNumbers = addLineNumberDiv(this.wrapping);
 261          this.activateLineNumbers();
 262        }
 263        else if (!on && this.lineNumbers) {
 264          this.wrapping.removeChild(this.lineNumbers);
 265          this.wrapping.style.marginLeft = "";
 266          this.lineNumbers = null;
 267        }
 268      },
 269  
 270      cursorPosition: function(start) {this.focusIfIE(); return this.editor.cursorPosition(start);},
 271      firstLine: function() {return this.editor.firstLine();},
 272      lastLine: function() {return this.editor.lastLine();},
 273      nextLine: function(line) {return this.editor.nextLine(line);},
 274      prevLine: function(line) {return this.editor.prevLine(line);},
 275      lineContent: function(line) {return this.editor.lineContent(line);},
 276      setLineContent: function(line, content) {this.editor.setLineContent(line, content);},
 277      removeLine: function(line){this.editor.removeLine(line);},
 278      insertIntoLine: function(line, position, content) {this.editor.insertIntoLine(line, position, content);},
 279      selectLines: function(startLine, startOffset, endLine, endOffset) {
 280        this.win.focus();
 281        this.editor.selectLines(startLine, startOffset, endLine, endOffset);
 282      },
 283      nthLine: function(n) {
 284        var line = this.firstLine();
 285        for (; n > 1 && line !== false; n--)
 286          line = this.nextLine(line);
 287        return line;
 288      },
 289      lineNumber: function(line) {
 290        var num = 0;
 291        while (line !== false) {
 292          num++;
 293          line = this.prevLine(line);
 294        }
 295        return num;
 296      },
 297      jumpToLine: function(line) {
 298        if (typeof line == "number") line = this.nthLine(line);
 299        this.selectLines(line, 0);
 300        this.win.focus();
 301      },
 302      currentLine: function() { // Deprecated, but still there for backward compatibility
 303        return this.lineNumber(this.cursorLine());
 304      },
 305      cursorLine: function() {
 306        return this.cursorPosition().line;
 307      },
 308      cursorCoords: function(start) {return this.editor.cursorCoords(start);},
 309  
 310      activateLineNumbers: function() {
 311        var frame = this.frame, win = frame.contentWindow, doc = win.document, body = doc.body,
 312            nums = this.lineNumbers, scroller = nums.firstChild, self = this;
 313        var barWidth = null;
 314  
 315        function sizeBar() {
 316          if (frame.offsetWidth == 0) return;
 317          for (var root = frame; root.parentNode; root = root.parentNode){}
 318          if (!nums.parentNode || root != document || !win.Editor) {
 319            // Clear event handlers (their nodes might already be collected, so try/catch)
 320            try{clear();}catch(e){}
 321            clearInterval(sizeInterval);
 322            return;
 323          }
 324  
 325          if (nums.offsetWidth != barWidth) {
 326            barWidth = nums.offsetWidth;
 327            frame.parentNode.style.paddingLeft = barWidth + "px";
 328          }
 329        }
 330        function doScroll() {
 331          nums.scrollTop = body.scrollTop || doc.documentElement.scrollTop || 0;
 332        }
 333        // Cleanup function, registered by nonWrapping and wrapping.
 334        var clear = function(){};
 335        sizeBar();
 336        var sizeInterval = setInterval(sizeBar, 500);
 337  
 338        function ensureEnoughLineNumbers(fill) {
 339          var lineHeight = scroller.firstChild.offsetHeight;
 340          if (lineHeight == 0) return;
 341          var targetHeight = 50 + Math.max(body.offsetHeight, Math.max(frame.offsetHeight, body.scrollHeight || 0)),
 342              lastNumber = Math.ceil(targetHeight / lineHeight);
 343          for (var i = scroller.childNodes.length; i <= lastNumber; i++) {
 344            var div = document.createElement("DIV");
 345            div.appendChild(document.createTextNode(fill ? String(i + self.options.firstLineNumber) : "\u00a0"));
 346            scroller.appendChild(div);
 347          }
 348        }
 349  
 350        function nonWrapping() {
 351          function update() {
 352            ensureEnoughLineNumbers(true);
 353            doScroll();
 354          }
 355          self.updateNumbers = update;
 356          var onScroll = win.addEventHandler(win, "scroll", doScroll, true),
 357              onResize = win.addEventHandler(win, "resize", update, true);
 358          clear = function(){
 359            onScroll(); onResize();
 360            if (self.updateNumbers == update) self.updateNumbers = null;
 361          };
 362          update();
 363        }
 364  
 365        function wrapping() {
 366          var node, lineNum, next, pos, changes = [], styleNums = self.options.styleNumbers;
 367  
 368          function setNum(n, node) {
 369            // Does not typically happen (but can, if you mess with the
 370            // document during the numbering)
 371            if (!lineNum) lineNum = scroller.appendChild(document.createElement("DIV"));
 372            if (styleNums) styleNums(lineNum, node, n);
 373            // Changes are accumulated, so that the document layout
 374            // doesn't have to be recomputed during the pass
 375            changes.push(lineNum); changes.push(n);
 376            pos = lineNum.offsetHeight + lineNum.offsetTop;
 377            lineNum = lineNum.nextSibling;
 378          }
 379          function commitChanges() {
 380            for (var i = 0; i < changes.length; i += 2)
 381              changes[i].innerHTML = changes[i + 1];
 382            changes = [];
 383          }
 384          function work() {
 385            if (!scroller.parentNode || scroller.parentNode != self.lineNumbers) return;
 386  
 387            var endTime = new Date().getTime() + self.options.lineNumberTime;
 388            while (node) {
 389              setNum(next++, node.previousSibling);
 390              for (; node && !win.isBR(node); node = node.nextSibling) {
 391                var bott = node.offsetTop + node.offsetHeight;
 392                while (scroller.offsetHeight && bott - 3 > pos) setNum("&nbsp;");
 393              }
 394              if (node) node = node.nextSibling;
 395              if (new Date().getTime() > endTime) {
 396                commitChanges();
 397                pending = setTimeout(work, self.options.lineNumberDelay);
 398                return;
 399              }
 400            }
 401            while (lineNum) setNum(next++);
 402            commitChanges();
 403            doScroll();
 404          }
 405          function start(firstTime) {
 406            doScroll();
 407            ensureEnoughLineNumbers(firstTime);
 408            node = body.firstChild;
 409            lineNum = scroller.firstChild;
 410            pos = 0;
 411            next = self.options.firstLineNumber;
 412            work();
 413          }
 414  
 415          start(true);
 416          var pending = null;
 417          function update() {
 418            if (pending) clearTimeout(pending);
 419            if (self.editor.allClean()) start();
 420            else pending = setTimeout(update, 200);
 421          }
 422          self.updateNumbers = update;
 423          var onScroll = win.addEventHandler(win, "scroll", doScroll, true),
 424              onResize = win.addEventHandler(win, "resize", update, true);
 425          clear = function(){
 426            if (pending) clearTimeout(pending);
 427            if (self.updateNumbers == update) self.updateNumbers = null;
 428            onScroll();
 429            onResize();
 430          };
 431        }
 432        (this.options.textWrapping || this.options.styleNumbers ? wrapping : nonWrapping)();
 433      },
 434  
 435      setDynamicHeight: function() {
 436        var self = this, activity = self.options.cursorActivity, win = self.win, body = win.document.body,
 437            lineHeight = null, timeout = null, vmargin = 2 * self.frame.offsetTop;
 438        body.style.overflowY = "hidden";
 439        win.document.documentElement.style.overflowY = "hidden";
 440        this.frame.scrolling = "no";
 441  
 442        function updateHeight() {
 443          var trailingLines = 0, node = body.lastChild, computedHeight;
 444          while (node && win.isBR(node)) {
 445            if (!node.hackBR) trailingLines++;
 446            node = node.previousSibling;
 447          }
 448          if (node) {
 449            lineHeight = node.offsetHeight;
 450            computedHeight = node.offsetTop + (1 + trailingLines) * lineHeight;
 451          }
 452          else if (lineHeight) {
 453            computedHeight = trailingLines * lineHeight;
 454          }
 455          if (computedHeight)
 456            self.wrapping.style.height = Math.max(vmargin + computedHeight, self.options.minHeight) + "px";
 457        }
 458        setTimeout(updateHeight, 300);
 459        self.options.cursorActivity = function(x) {
 460          if (activity) activity(x);
 461          clearTimeout(timeout);
 462          timeout = setTimeout(updateHeight, 100);
 463        };
 464      }
 465    };
 466  
 467    CodeMirror.InvalidLineHandle = {toString: function(){return "CodeMirror.InvalidLineHandle";}};
 468  
 469    CodeMirror.replace = function(element) {
 470      if (typeof element == "string")
 471        element = document.getElementById(element);
 472      return function(newElement) {
 473        element.parentNode.replaceChild(newElement, element);
 474      };
 475    };
 476  
 477    CodeMirror.fromTextArea = function(area, options) {
 478      if (typeof area == "string")
 479        area = document.getElementById(area);
 480  
 481      options = options || {};
 482      if (area.style.width && options.width == null)
 483        options.width = area.style.width;
 484      if (area.style.height && options.height == null)
 485        options.height = area.style.height;
 486      if (options.content == null) options.content = area.value;
 487  
 488      if (area.form) {
 489        function updateField() {
 490          area.value = mirror.getCode();
 491        }
 492        if (typeof area.form.addEventListener == "function")
 493          area.form.addEventListener("submit", updateField, false);
 494        else
 495          area.form.attachEvent("onsubmit", updateField);
 496        var realSubmit = area.form.submit;
 497        function wrapSubmit() {
 498          updateField();
 499          // Can't use realSubmit.apply because IE6 is too stupid
 500          area.form.submit = realSubmit;
 501          area.form.submit();
 502          area.form.submit = wrapSubmit;
 503        }
 504        area.form.submit = wrapSubmit;
 505      }
 506  
 507      function insert(frame) {
 508        if (area.nextSibling)
 509          area.parentNode.insertBefore(frame, area.nextSibling);
 510        else
 511          area.parentNode.appendChild(frame);
 512      }
 513  
 514      area.style.display = "none";
 515      var mirror = new CodeMirror(insert, options);
 516      mirror.toTextArea = function() {
 517        area.parentNode.removeChild(mirror.wrapping);
 518        area.style.display = "";
 519        if (area.form) {
 520          area.form.submit = realSubmit;
 521          if (typeof area.form.removeEventListener == "function")
 522            area.form.removeEventListener("submit", updateField, false);
 523          else
 524            area.form.detachEvent("onsubmit", updateField);
 525        }
 526      };
 527  
 528      return mirror;
 529    };
 530  
 531    CodeMirror.isProbablySupported = function() {
 532      // This is rather awful, but can be useful.
 533      var match;
 534      if (window.opera)
 535        return Number(window.opera.version()) >= 9.52;
 536      else if (/Apple Computers, Inc/.test(navigator.vendor) && (match = navigator.userAgent.match(/Version\/(\d+(?:\.\d+)?)\./)))
 537        return Number(match[1]) >= 3;
 538      else if (document.selection && window.ActiveXObject && (match = navigator.userAgent.match(/MSIE (\d+(?:\.\d*)?)\b/)))
 539        return Number(match[1]) >= 6;
 540      else if (match = navigator.userAgent.match(/gecko\/(\d{8})/i))
 541        return Number(match[1]) >= 20050901;
 542      else if (match = navigator.userAgent.match(/AppleWebKit\/(\d+)/))
 543        return Number(match[1]) >= 525;
 544      else
 545        return null;
 546    };
 547  
 548    return CodeMirror;
 549  })();


Generated: Mon Mar 11 18:33:33 2019 Cross-referenced by PHPXref 0.7.1