diff --git a/extras/PandoraFMS_android_console/src/pandorafms/pandorafmsandroidconsole/ConnectionCustomToast.java b/extras/PandoraFMS_android_console/src/pandorafms/pandorafmsandroidconsole/ConnectionCustomToast.java
index 432f14d14a..8540370a2b 100644
--- a/extras/PandoraFMS_android_console/src/pandorafms/pandorafmsandroidconsole/ConnectionCustomToast.java
+++ b/extras/PandoraFMS_android_console/src/pandorafms/pandorafmsandroidconsole/ConnectionCustomToast.java
@@ -2,7 +2,7 @@
Pandora FMS - http://pandorafms.com
==================================================
-Copyright (c) 2005-2011 Artica Soluciones Tecnologicas
+Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
Please see http://pandorafms.org for full contribution list
This program is free software; you can redistribute it and/or
diff --git a/extras/PandoraFMS_android_console/src/pandorafms/pandorafmsandroidconsole/Help.java b/extras/PandoraFMS_android_console/src/pandorafms/pandorafmsandroidconsole/Help.java
index dc01edb419..32d73a7fa8 100644
--- a/extras/PandoraFMS_android_console/src/pandorafms/pandorafmsandroidconsole/Help.java
+++ b/extras/PandoraFMS_android_console/src/pandorafms/pandorafmsandroidconsole/Help.java
@@ -2,7 +2,7 @@
Pandora FMS - http://pandorafms.com
==================================================
-Copyright (c) 2005-2011 Artica Soluciones Tecnologicas
+Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
Please see http://pandorafms.org for full contribution list
This program is free software; you can redistribute it and/or
diff --git a/extras/PandoraFMS_android_console/src/pandorafms/pandorafmsandroidconsole/Options.java b/extras/PandoraFMS_android_console/src/pandorafms/pandorafmsandroidconsole/Options.java
index ddba7ed373..2cd8542fa0 100644
--- a/extras/PandoraFMS_android_console/src/pandorafms/pandorafmsandroidconsole/Options.java
+++ b/extras/PandoraFMS_android_console/src/pandorafms/pandorafmsandroidconsole/Options.java
@@ -2,7 +2,7 @@
Pandora FMS - http://pandorafms.com
==================================================
-Copyright (c) 2005-2011 Artica Soluciones Tecnologicas
+Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
Please see http://pandorafms.org for full contribution list
This program is free software; you can redistribute it and/or
diff --git a/extras/PandoraFMS_android_console/src/pandorafms/pandorafmsandroidconsole/PandoraWebView.java b/extras/PandoraFMS_android_console/src/pandorafms/pandorafmsandroidconsole/PandoraWebView.java
index 60a401b088..13e28af1ea 100644
--- a/extras/PandoraFMS_android_console/src/pandorafms/pandorafmsandroidconsole/PandoraWebView.java
+++ b/extras/PandoraFMS_android_console/src/pandorafms/pandorafmsandroidconsole/PandoraWebView.java
@@ -2,7 +2,7 @@
Pandora FMS - http://pandorafms.com
==================================================
-Copyright (c) 2005-2011 Artica Soluciones Tecnologicas
+Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
Please see http://pandorafms.org for full contribution list
This program is free software; you can redistribute it and/or
diff --git a/extras/android-event-viewer/app/src/main/AndroidManifest.xml b/extras/android-event-viewer/app/src/main/AndroidManifest.xml
index bdd70a163e..56e27364eb 100644
--- a/extras/android-event-viewer/app/src/main/AndroidManifest.xml
+++ b/extras/android-event-viewer/app/src/main/AndroidManifest.xml
@@ -2,7 +2,7 @@
'.__('Selected'), '', $item);
$line = implode($separator, $item);
diff --git a/pandora_console/include/graphs/flot/pandora.flot.js b/pandora_console/include/graphs/flot/pandora.flot.js
index 87ecf4b33f..b2d9ee8824 100644
--- a/pandora_console/include/graphs/flot/pandora.flot.js
+++ b/pandora_console/include/graphs/flot/pandora.flot.js
@@ -230,21 +230,6 @@ function pandoraFlotPieCustom(
);
}
var legends = $("#" + graph_id + " .legendLabel");
- var j = 0;
- legends.each(function() {
- //$(this).css("width", $(this).width());
- $(this).css("font-size", font_size + "pt");
- $(this).removeClass("legendLabel");
- $(this).addClass(font);
- $(this).text(legend[j]);
- j++;
- });
-
- if ($('input[name="custom_graph"]').val()) {
- $(".legend>div").css("right", $(".legend>div").height() * -1);
- $(".legend>table").css("right", $(".legend>div").height() * -1);
- }
- //$('.legend>table').css('border',"1px solid #E2E2E2");
if (background_color == "transparent") {
$(".legend>table").css("background-color", "");
@@ -508,7 +493,12 @@ $.fn.HUseTooltip = function() {
// var y = item.datapoint[1];
var color = item.series.color;
- showTooltip(pos.pageX, pos.pageY, color, "" + x + "");
+ showTooltip(
+ item.pageX,
+ item.pageY,
+ color,
+ "" + x + ""
+ );
}
} else {
$("#tooltip").remove();
diff --git a/pandora_console/include/graphs/functions_d3.php b/pandora_console/include/graphs/functions_d3.php
index 8719531abc..7bc835a456 100644
--- a/pandora_console/include/graphs/functions_d3.php
+++ b/pandora_console/include/graphs/functions_d3.php
@@ -2,7 +2,7 @@
// Pandora FMS - http://pandorafms.com
// ==================================================
-// Copyright (c) 2005-2011 Artica Soluciones Tecnologicas
+// Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
// Please see http://pandorafms.org for full contribution list
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
diff --git a/pandora_console/include/graphs/functions_flot.php b/pandora_console/include/graphs/functions_flot.php
index 81c9cc79cf..2e6981027b 100644
--- a/pandora_console/include/graphs/functions_flot.php
+++ b/pandora_console/include/graphs/functions_flot.php
@@ -2,7 +2,7 @@
// Copyright (c) 2007-2008 Sancho Lerena, slerena@gmail.com
// Copyright (c) 2008 Esteban Sanchez, estebans@artica.es
-// Copyright (c) 2007-2011 Artica, info@artica.es
+// Copyright (c) 2007-2021 Artica, info@artica.es
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License
// (LGPL) as published by the Free Software Foundation; version 2
diff --git a/pandora_console/include/graphs/functions_gd.php b/pandora_console/include/graphs/functions_gd.php
index 10f566185d..cb2a6735e2 100755
--- a/pandora_console/include/graphs/functions_gd.php
+++ b/pandora_console/include/graphs/functions_gd.php
@@ -1,7 +1,7 @@
No assigned agent
Disabled events |
- |
- |
+ |
+ |
With assigned agent
Disabled events |
- |
- |
+ |
+ |
No assigned agent
Activated events |
- |
- |
+ |
+ |
With assigned agent
Activated events |
- |
- |
+ |
+ |
Not managed |
@@ -58,8 +58,8 @@ Addresses will be shown as icons, large or small. This icons will render the fol
If an IP address is not managed, you can only view if is responding or not. |
- |
- |
+ |
+ |
Not assigned |
diff --git a/pandora_console/include/help/es/help_ipam.php b/pandora_console/include/help/es/help_ipam.php
index c03158f6ec..f312b6ec25 100755
--- a/pandora_console/include/help/es/help_ipam.php
+++ b/pandora_console/include/help/es/help_ipam.php
@@ -31,23 +31,23 @@ Cada dirección tendrá un icono grande que nos aportará información:
Sin agente asignado
Eventos desactivados |
- |
- |
+ |
+ |
Con agente asignado
Eventos desactivados |
- |
- |
+ |
+ |
Sin agente asignado
Eventos activados |
- |
- |
+ |
+ |
Con agente asignado
Eventos activados |
- |
- |
+ |
+ |
Sin administrar |
@@ -59,8 +59,8 @@ Cada dirección tendrá un icono grande que nos aportará información:
Independientemente de la configuración, si el host no está administrado solo se diferenciará entre si está vivo y no responde |
- |
- |
+ |
+ |
No asignado |
diff --git a/pandora_console/include/help/ja/help_ipam.php b/pandora_console/include/help/ja/help_ipam.php
index 28cac820b8..87ffbe9c47 100644
--- a/pandora_console/include/help/ja/help_ipam.php
+++ b/pandora_console/include/help/ja/help_ipam.php
@@ -31,23 +31,23 @@ IP 管ç†ã¯ã€ エージェントã§è¨å®šã—
エージェント未割当
イベント無効 |
- |
- |
+ |
+ |
エージェント割当済
イベント無効 |
- |
- |
+ |
+ |
エージェント未割当
イベント有効 |
- |
- |
+ |
+ |
エージェント割当済
イベント有効 |
- |
- |
+ |
+ |
æœªç®¡ç† |
@@ -59,8 +59,8 @@ IP 管ç†ã¯ã€ エージェントã§è¨å®šã—
IP アドレスãŒç®¡ç†ã•ã‚Œã¦ã„ãªã„å ´åˆã€å¿œç”ãŒã‚ã‚‹ã‹ã©ã†ã‹ã ã‘を見るã“ã¨ãŒã§ãã¾ã™ã€‚ |
- |
- |
+ |
+ |
未割当 |
diff --git a/pandora_console/include/include_graph_dependencies.php b/pandora_console/include/include_graph_dependencies.php
index 947f8a5f6f..a21fb0b53e 100644
--- a/pandora_console/include/include_graph_dependencies.php
+++ b/pandora_console/include/include_graph_dependencies.php
@@ -2,7 +2,7 @@
// Pandora FMS - http://pandorafms.com
// ==================================================
-// Copyright (c) 2005-2011 Artica Soluciones Tecnologicas
+// Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
// Please see http://pandorafms.org for full contribution list
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License
diff --git a/pandora_console/include/javascript/ace/ace.js b/pandora_console/include/javascript/ace/ace.js
new file mode 100644
index 0000000000..fd2353db05
--- /dev/null
+++ b/pandora_console/include/javascript/ace/ace.js
@@ -0,0 +1,25468 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Distributed under the BSD license:
+ *
+ * Copyright (c) 2010, Ajax.org B.V.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Ajax.org B.V. nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * Define a module along with a payload
+ * @param module a name for the payload
+ * @param payload a function to call with (require, exports, module) params
+ */
+
+(function() {
+ var ACE_NAMESPACE = "ace";
+
+ var global = (function() {
+ return this;
+ })();
+ if (!global && typeof window != "undefined") global = window; // strict mode
+
+ if (!ACE_NAMESPACE && typeof requirejs !== "undefined") return;
+
+ var define = function(module, deps, payload) {
+ if (typeof module !== "string") {
+ if (define.original) define.original.apply(this, arguments);
+ else {
+ console.error("dropping module because define wasn't a string.");
+ console.trace();
+ }
+ return;
+ }
+ if (arguments.length == 2) payload = deps;
+ if (!define.modules[module]) {
+ define.payloads[module] = payload;
+ define.modules[module] = null;
+ }
+ };
+
+ define.modules = {};
+ define.payloads = {};
+
+ /**
+ * Get at functionality define()ed using the function above
+ */
+ var _require = function(parentId, module, callback) {
+ if (typeof module === "string") {
+ var payload = lookup(parentId, module);
+ if (payload != undefined) {
+ callback && callback();
+ return payload;
+ }
+ } else if (Object.prototype.toString.call(module) === "[object Array]") {
+ var params = [];
+ for (var i = 0, l = module.length; i < l; ++i) {
+ var dep = lookup(parentId, module[i]);
+ if (dep == undefined && require.original) return;
+ params.push(dep);
+ }
+ return (callback && callback.apply(null, params)) || true;
+ }
+ };
+
+ var require = function(module, callback) {
+ var packagedModule = _require("", module, callback);
+ if (packagedModule == undefined && require.original)
+ return require.original.apply(this, arguments);
+ return packagedModule;
+ };
+
+ var normalizeModule = function(parentId, moduleName) {
+ // normalize plugin requires
+ if (moduleName.indexOf("!") !== -1) {
+ var chunks = moduleName.split("!");
+ return (
+ normalizeModule(parentId, chunks[0]) +
+ "!" +
+ normalizeModule(parentId, chunks[1])
+ );
+ }
+ // normalize relative requires
+ if (moduleName.charAt(0) == ".") {
+ var base = parentId
+ .split("/")
+ .slice(0, -1)
+ .join("/");
+ moduleName = base + "/" + moduleName;
+
+ while (moduleName.indexOf(".") !== -1 && previous != moduleName) {
+ var previous = moduleName;
+ moduleName = moduleName
+ .replace(/\/\.\//, "/")
+ .replace(/[^\/]+\/\.\.\//, "");
+ }
+ }
+ return moduleName;
+ };
+
+ /**
+ * Internal function to lookup moduleNames and resolve them by calling the
+ * definition function if needed.
+ */
+ var lookup = function(parentId, moduleName) {
+ moduleName = normalizeModule(parentId, moduleName);
+
+ var module = define.modules[moduleName];
+ if (!module) {
+ module = define.payloads[moduleName];
+ if (typeof module === "function") {
+ var exports = {};
+ var mod = {
+ id: moduleName,
+ uri: "",
+ exports: exports,
+ packaged: true
+ };
+
+ var req = function(module, callback) {
+ return _require(moduleName, module, callback);
+ };
+
+ var returnValue = module(req, exports, mod);
+ exports = returnValue || mod.exports;
+ define.modules[moduleName] = exports;
+ delete define.payloads[moduleName];
+ }
+ module = define.modules[moduleName] = exports || module;
+ }
+ return module;
+ };
+
+ function exportAce(ns) {
+ var root = global;
+ if (ns) {
+ if (!global[ns]) global[ns] = {};
+ root = global[ns];
+ }
+
+ if (!root.define || !root.define.packaged) {
+ define.original = root.define;
+ root.define = define;
+ root.define.packaged = true;
+ }
+
+ if (!root.require || !root.require.packaged) {
+ require.original = root.require;
+ root.require = require;
+ root.require.packaged = true;
+ }
+ }
+
+ exportAce(ACE_NAMESPACE);
+})();
+
+ace.define("ace/lib/regexp", ["require", "exports", "module"], function(
+ require,
+ exports,
+ module
+) {
+ "use strict";
+
+ var real = {
+ exec: RegExp.prototype.exec,
+ test: RegExp.prototype.test,
+ match: String.prototype.match,
+ replace: String.prototype.replace,
+ split: String.prototype.split
+ },
+ compliantExecNpcg = real.exec.call(/()??/, "")[1] === undefined, // check `exec` handling of nonparticipating capturing groups
+ compliantLastIndexIncrement = (function() {
+ var x = /^/g;
+ real.test.call(x, "");
+ return !x.lastIndex;
+ })();
+
+ if (compliantLastIndexIncrement && compliantExecNpcg) return;
+ RegExp.prototype.exec = function(str) {
+ var match = real.exec.apply(this, arguments),
+ name,
+ r2;
+ if (typeof str == "string" && match) {
+ if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) {
+ r2 = RegExp(
+ this.source,
+ real.replace.call(getNativeFlags(this), "g", "")
+ );
+ real.replace.call(str.slice(match.index), r2, function() {
+ for (var i = 1; i < arguments.length - 2; i++) {
+ if (arguments[i] === undefined) match[i] = undefined;
+ }
+ });
+ }
+ if (this._xregexp && this._xregexp.captureNames) {
+ for (var i = 1; i < match.length; i++) {
+ name = this._xregexp.captureNames[i - 1];
+ if (name) match[name] = match[i];
+ }
+ }
+ if (
+ !compliantLastIndexIncrement &&
+ this.global &&
+ !match[0].length &&
+ this.lastIndex > match.index
+ )
+ this.lastIndex--;
+ }
+ return match;
+ };
+ if (!compliantLastIndexIncrement) {
+ RegExp.prototype.test = function(str) {
+ var match = real.exec.call(this, str);
+ if (
+ match &&
+ this.global &&
+ !match[0].length &&
+ this.lastIndex > match.index
+ )
+ this.lastIndex--;
+ return !!match;
+ };
+ }
+
+ function getNativeFlags(regex) {
+ return (
+ (regex.global ? "g" : "") +
+ (regex.ignoreCase ? "i" : "") +
+ (regex.multiline ? "m" : "") +
+ (regex.extended ? "x" : "") + // Proposed for ES4; included in AS3
+ (regex.sticky ? "y" : "")
+ );
+ }
+
+ function indexOf(array, item, from) {
+ if (Array.prototype.indexOf)
+ // Use the native array method if available
+ return array.indexOf(item, from);
+ for (var i = from || 0; i < array.length; i++) {
+ if (array[i] === item) return i;
+ }
+ return -1;
+ }
+});
+
+ace.define("ace/lib/es5-shim", ["require", "exports", "module"], function(
+ require,
+ exports,
+ module
+) {
+ function Empty() {}
+
+ if (!Function.prototype.bind) {
+ Function.prototype.bind = function bind(that) {
+ // .length is 1
+ var target = this;
+ if (typeof target != "function") {
+ throw new TypeError(
+ "Function.prototype.bind called on incompatible " + target
+ );
+ }
+ var args = slice.call(arguments, 1); // for normal call
+ var bound = function() {
+ if (this instanceof bound) {
+ var result = target.apply(this, args.concat(slice.call(arguments)));
+ if (Object(result) === result) {
+ return result;
+ }
+ return this;
+ } else {
+ return target.apply(that, args.concat(slice.call(arguments)));
+ }
+ };
+ if (target.prototype) {
+ Empty.prototype = target.prototype;
+ bound.prototype = new Empty();
+ Empty.prototype = null;
+ }
+ return bound;
+ };
+ }
+ var call = Function.prototype.call;
+ var prototypeOfArray = Array.prototype;
+ var prototypeOfObject = Object.prototype;
+ var slice = prototypeOfArray.slice;
+ var _toString = call.bind(prototypeOfObject.toString);
+ var owns = call.bind(prototypeOfObject.hasOwnProperty);
+ var defineGetter;
+ var defineSetter;
+ var lookupGetter;
+ var lookupSetter;
+ var supportsAccessors;
+ if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) {
+ defineGetter = call.bind(prototypeOfObject.__defineGetter__);
+ defineSetter = call.bind(prototypeOfObject.__defineSetter__);
+ lookupGetter = call.bind(prototypeOfObject.__lookupGetter__);
+ lookupSetter = call.bind(prototypeOfObject.__lookupSetter__);
+ }
+ if ([1, 2].splice(0).length != 2) {
+ if (
+ (function() {
+ // test IE < 9 to splice bug - see issue #138
+ function makeArray(l) {
+ var a = new Array(l + 2);
+ a[0] = a[1] = 0;
+ return a;
+ }
+ var array = [],
+ lengthBefore;
+
+ array.splice.apply(array, makeArray(20));
+ array.splice.apply(array, makeArray(26));
+
+ lengthBefore = array.length; //46
+ array.splice(5, 0, "XXX"); // add one element
+
+ lengthBefore + 1 == array.length;
+
+ if (lengthBefore + 1 == array.length) {
+ return true; // has right splice implementation without bugs
+ }
+ })()
+ ) {
+ //IE 6/7
+ var array_splice = Array.prototype.splice;
+ Array.prototype.splice = function(start, deleteCount) {
+ if (!arguments.length) {
+ return [];
+ } else {
+ return array_splice.apply(
+ this,
+ [
+ start === void 0 ? 0 : start,
+ deleteCount === void 0 ? this.length - start : deleteCount
+ ].concat(slice.call(arguments, 2))
+ );
+ }
+ };
+ } else {
+ //IE8
+ Array.prototype.splice = function(pos, removeCount) {
+ var length = this.length;
+ if (pos > 0) {
+ if (pos > length) pos = length;
+ } else if (pos == void 0) {
+ pos = 0;
+ } else if (pos < 0) {
+ pos = Math.max(length + pos, 0);
+ }
+
+ if (!(pos + removeCount < length)) removeCount = length - pos;
+
+ var removed = this.slice(pos, pos + removeCount);
+ var insert = slice.call(arguments, 2);
+ var add = insert.length;
+ if (pos === length) {
+ if (add) {
+ this.push.apply(this, insert);
+ }
+ } else {
+ var remove = Math.min(removeCount, length - pos);
+ var tailOldPos = pos + remove;
+ var tailNewPos = tailOldPos + add - remove;
+ var tailCount = length - tailOldPos;
+ var lengthAfterRemove = length - remove;
+
+ if (tailNewPos < tailOldPos) {
+ // case A
+ for (var i = 0; i < tailCount; ++i) {
+ this[tailNewPos + i] = this[tailOldPos + i];
+ }
+ } else if (tailNewPos > tailOldPos) {
+ // case B
+ for (i = tailCount; i--; ) {
+ this[tailNewPos + i] = this[tailOldPos + i];
+ }
+ } // else, add == remove (nothing to do)
+
+ if (add && pos === lengthAfterRemove) {
+ this.length = lengthAfterRemove; // truncate array
+ this.push.apply(this, insert);
+ } else {
+ this.length = lengthAfterRemove + add; // reserves space
+ for (i = 0; i < add; ++i) {
+ this[pos + i] = insert[i];
+ }
+ }
+ }
+ return removed;
+ };
+ }
+ }
+ if (!Array.isArray) {
+ Array.isArray = function isArray(obj) {
+ return _toString(obj) == "[object Array]";
+ };
+ }
+ var boxedString = Object("a"),
+ splitString = boxedString[0] != "a" || !(0 in boxedString);
+
+ if (!Array.prototype.forEach) {
+ Array.prototype.forEach = function forEach(fun /*, thisp*/) {
+ var object = toObject(this),
+ self =
+ splitString && _toString(this) == "[object String]"
+ ? this.split("")
+ : object,
+ thisp = arguments[1],
+ i = -1,
+ length = self.length >>> 0;
+ if (_toString(fun) != "[object Function]") {
+ throw new TypeError(); // TODO message
+ }
+
+ while (++i < length) {
+ if (i in self) {
+ fun.call(thisp, self[i], i, object);
+ }
+ }
+ };
+ }
+ if (!Array.prototype.map) {
+ Array.prototype.map = function map(fun /*, thisp*/) {
+ var object = toObject(this),
+ self =
+ splitString && _toString(this) == "[object String]"
+ ? this.split("")
+ : object,
+ length = self.length >>> 0,
+ result = Array(length),
+ thisp = arguments[1];
+ if (_toString(fun) != "[object Function]") {
+ throw new TypeError(fun + " is not a function");
+ }
+
+ for (var i = 0; i < length; i++) {
+ if (i in self) result[i] = fun.call(thisp, self[i], i, object);
+ }
+ return result;
+ };
+ }
+ if (!Array.prototype.filter) {
+ Array.prototype.filter = function filter(fun /*, thisp */) {
+ var object = toObject(this),
+ self =
+ splitString && _toString(this) == "[object String]"
+ ? this.split("")
+ : object,
+ length = self.length >>> 0,
+ result = [],
+ value,
+ thisp = arguments[1];
+ if (_toString(fun) != "[object Function]") {
+ throw new TypeError(fun + " is not a function");
+ }
+
+ for (var i = 0; i < length; i++) {
+ if (i in self) {
+ value = self[i];
+ if (fun.call(thisp, value, i, object)) {
+ result.push(value);
+ }
+ }
+ }
+ return result;
+ };
+ }
+ if (!Array.prototype.every) {
+ Array.prototype.every = function every(fun /*, thisp */) {
+ var object = toObject(this),
+ self =
+ splitString && _toString(this) == "[object String]"
+ ? this.split("")
+ : object,
+ length = self.length >>> 0,
+ thisp = arguments[1];
+ if (_toString(fun) != "[object Function]") {
+ throw new TypeError(fun + " is not a function");
+ }
+
+ for (var i = 0; i < length; i++) {
+ if (i in self && !fun.call(thisp, self[i], i, object)) {
+ return false;
+ }
+ }
+ return true;
+ };
+ }
+ if (!Array.prototype.some) {
+ Array.prototype.some = function some(fun /*, thisp */) {
+ var object = toObject(this),
+ self =
+ splitString && _toString(this) == "[object String]"
+ ? this.split("")
+ : object,
+ length = self.length >>> 0,
+ thisp = arguments[1];
+ if (_toString(fun) != "[object Function]") {
+ throw new TypeError(fun + " is not a function");
+ }
+
+ for (var i = 0; i < length; i++) {
+ if (i in self && fun.call(thisp, self[i], i, object)) {
+ return true;
+ }
+ }
+ return false;
+ };
+ }
+ if (!Array.prototype.reduce) {
+ Array.prototype.reduce = function reduce(fun /*, initial*/) {
+ var object = toObject(this),
+ self =
+ splitString && _toString(this) == "[object String]"
+ ? this.split("")
+ : object,
+ length = self.length >>> 0;
+ if (_toString(fun) != "[object Function]") {
+ throw new TypeError(fun + " is not a function");
+ }
+ if (!length && arguments.length == 1) {
+ throw new TypeError("reduce of empty array with no initial value");
+ }
+
+ var i = 0;
+ var result;
+ if (arguments.length >= 2) {
+ result = arguments[1];
+ } else {
+ do {
+ if (i in self) {
+ result = self[i++];
+ break;
+ }
+ if (++i >= length) {
+ throw new TypeError("reduce of empty array with no initial value");
+ }
+ } while (true);
+ }
+
+ for (; i < length; i++) {
+ if (i in self) {
+ result = fun.call(void 0, result, self[i], i, object);
+ }
+ }
+
+ return result;
+ };
+ }
+ if (!Array.prototype.reduceRight) {
+ Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) {
+ var object = toObject(this),
+ self =
+ splitString && _toString(this) == "[object String]"
+ ? this.split("")
+ : object,
+ length = self.length >>> 0;
+ if (_toString(fun) != "[object Function]") {
+ throw new TypeError(fun + " is not a function");
+ }
+ if (!length && arguments.length == 1) {
+ throw new TypeError("reduceRight of empty array with no initial value");
+ }
+
+ var result,
+ i = length - 1;
+ if (arguments.length >= 2) {
+ result = arguments[1];
+ } else {
+ do {
+ if (i in self) {
+ result = self[i--];
+ break;
+ }
+ if (--i < 0) {
+ throw new TypeError(
+ "reduceRight of empty array with no initial value"
+ );
+ }
+ } while (true);
+ }
+
+ do {
+ if (i in this) {
+ result = fun.call(void 0, result, self[i], i, object);
+ }
+ } while (i--);
+
+ return result;
+ };
+ }
+ if (!Array.prototype.indexOf || [0, 1].indexOf(1, 2) != -1) {
+ Array.prototype.indexOf = function indexOf(sought /*, fromIndex */) {
+ var self =
+ splitString && _toString(this) == "[object String]"
+ ? this.split("")
+ : toObject(this),
+ length = self.length >>> 0;
+
+ if (!length) {
+ return -1;
+ }
+
+ var i = 0;
+ if (arguments.length > 1) {
+ i = toInteger(arguments[1]);
+ }
+ i = i >= 0 ? i : Math.max(0, length + i);
+ for (; i < length; i++) {
+ if (i in self && self[i] === sought) {
+ return i;
+ }
+ }
+ return -1;
+ };
+ }
+ if (!Array.prototype.lastIndexOf || [0, 1].lastIndexOf(0, -3) != -1) {
+ Array.prototype.lastIndexOf = function lastIndexOf(
+ sought /*, fromIndex */
+ ) {
+ var self =
+ splitString && _toString(this) == "[object String]"
+ ? this.split("")
+ : toObject(this),
+ length = self.length >>> 0;
+
+ if (!length) {
+ return -1;
+ }
+ var i = length - 1;
+ if (arguments.length > 1) {
+ i = Math.min(i, toInteger(arguments[1]));
+ }
+ i = i >= 0 ? i : length - Math.abs(i);
+ for (; i >= 0; i--) {
+ if (i in self && sought === self[i]) {
+ return i;
+ }
+ }
+ return -1;
+ };
+ }
+ if (!Object.getPrototypeOf) {
+ Object.getPrototypeOf = function getPrototypeOf(object) {
+ return (
+ object.__proto__ ||
+ (object.constructor ? object.constructor.prototype : prototypeOfObject)
+ );
+ };
+ }
+ if (!Object.getOwnPropertyDescriptor) {
+ var ERR_NON_OBJECT =
+ "Object.getOwnPropertyDescriptor called on a " + "non-object: ";
+ Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(
+ object,
+ property
+ ) {
+ if (
+ (typeof object != "object" && typeof object != "function") ||
+ object === null
+ )
+ throw new TypeError(ERR_NON_OBJECT + object);
+ if (!owns(object, property)) return;
+
+ var descriptor, getter, setter;
+ descriptor = { enumerable: true, configurable: true };
+ if (supportsAccessors) {
+ var prototype = object.__proto__;
+ object.__proto__ = prototypeOfObject;
+
+ var getter = lookupGetter(object, property);
+ var setter = lookupSetter(object, property);
+ object.__proto__ = prototype;
+
+ if (getter || setter) {
+ if (getter) descriptor.get = getter;
+ if (setter) descriptor.set = setter;
+ return descriptor;
+ }
+ }
+ descriptor.value = object[property];
+ return descriptor;
+ };
+ }
+ if (!Object.getOwnPropertyNames) {
+ Object.getOwnPropertyNames = function getOwnPropertyNames(object) {
+ return Object.keys(object);
+ };
+ }
+ if (!Object.create) {
+ var createEmpty;
+ if (Object.prototype.__proto__ === null) {
+ createEmpty = function() {
+ return { __proto__: null };
+ };
+ } else {
+ createEmpty = function() {
+ var empty = {};
+ for (var i in empty) empty[i] = null;
+ empty.constructor = empty.hasOwnProperty = empty.propertyIsEnumerable = empty.isPrototypeOf = empty.toLocaleString = empty.toString = empty.valueOf = empty.__proto__ = null;
+ return empty;
+ };
+ }
+
+ Object.create = function create(prototype, properties) {
+ var object;
+ if (prototype === null) {
+ object = createEmpty();
+ } else {
+ if (typeof prototype != "object")
+ throw new TypeError(
+ "typeof prototype[" + typeof prototype + "] != 'object'"
+ );
+ var Type = function() {};
+ Type.prototype = prototype;
+ object = new Type();
+ object.__proto__ = prototype;
+ }
+ if (properties !== void 0) Object.defineProperties(object, properties);
+ return object;
+ };
+ }
+
+ function doesDefinePropertyWork(object) {
+ try {
+ Object.defineProperty(object, "sentinel", {});
+ return "sentinel" in object;
+ } catch (exception) {}
+ }
+ if (Object.defineProperty) {
+ var definePropertyWorksOnObject = doesDefinePropertyWork({});
+ var definePropertyWorksOnDom =
+ typeof document == "undefined" ||
+ doesDefinePropertyWork(document.createElement("div"));
+ if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) {
+ var definePropertyFallback = Object.defineProperty;
+ }
+ }
+
+ if (!Object.defineProperty || definePropertyFallback) {
+ var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: ";
+ var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: ";
+ var ERR_ACCESSORS_NOT_SUPPORTED =
+ "getters & setters can not be defined " + "on this javascript engine";
+
+ Object.defineProperty = function defineProperty(
+ object,
+ property,
+ descriptor
+ ) {
+ if (
+ (typeof object != "object" && typeof object != "function") ||
+ object === null
+ )
+ throw new TypeError(ERR_NON_OBJECT_TARGET + object);
+ if (
+ (typeof descriptor != "object" && typeof descriptor != "function") ||
+ descriptor === null
+ )
+ throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);
+ if (definePropertyFallback) {
+ try {
+ return definePropertyFallback.call(
+ Object,
+ object,
+ property,
+ descriptor
+ );
+ } catch (exception) {}
+ }
+ if (owns(descriptor, "value")) {
+ if (
+ supportsAccessors &&
+ (lookupGetter(object, property) || lookupSetter(object, property))
+ ) {
+ var prototype = object.__proto__;
+ object.__proto__ = prototypeOfObject;
+ delete object[property];
+ object[property] = descriptor.value;
+ object.__proto__ = prototype;
+ } else {
+ object[property] = descriptor.value;
+ }
+ } else {
+ if (!supportsAccessors)
+ throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
+ if (owns(descriptor, "get"))
+ defineGetter(object, property, descriptor.get);
+ if (owns(descriptor, "set"))
+ defineSetter(object, property, descriptor.set);
+ }
+
+ return object;
+ };
+ }
+ if (!Object.defineProperties) {
+ Object.defineProperties = function defineProperties(object, properties) {
+ for (var property in properties) {
+ if (owns(properties, property))
+ Object.defineProperty(object, property, properties[property]);
+ }
+ return object;
+ };
+ }
+ if (!Object.seal) {
+ Object.seal = function seal(object) {
+ return object;
+ };
+ }
+ if (!Object.freeze) {
+ Object.freeze = function freeze(object) {
+ return object;
+ };
+ }
+ try {
+ Object.freeze(function() {});
+ } catch (exception) {
+ Object.freeze = (function freeze(freezeObject) {
+ return function freeze(object) {
+ if (typeof object == "function") {
+ return object;
+ } else {
+ return freezeObject(object);
+ }
+ };
+ })(Object.freeze);
+ }
+ if (!Object.preventExtensions) {
+ Object.preventExtensions = function preventExtensions(object) {
+ return object;
+ };
+ }
+ if (!Object.isSealed) {
+ Object.isSealed = function isSealed(object) {
+ return false;
+ };
+ }
+ if (!Object.isFrozen) {
+ Object.isFrozen = function isFrozen(object) {
+ return false;
+ };
+ }
+ if (!Object.isExtensible) {
+ Object.isExtensible = function isExtensible(object) {
+ if (Object(object) === object) {
+ throw new TypeError(); // TODO message
+ }
+ var name = "";
+ while (owns(object, name)) {
+ name += "?";
+ }
+ object[name] = true;
+ var returnValue = owns(object, name);
+ delete object[name];
+ return returnValue;
+ };
+ }
+ if (!Object.keys) {
+ var hasDontEnumBug = true,
+ dontEnums = [
+ "toString",
+ "toLocaleString",
+ "valueOf",
+ "hasOwnProperty",
+ "isPrototypeOf",
+ "propertyIsEnumerable",
+ "constructor"
+ ],
+ dontEnumsLength = dontEnums.length;
+
+ for (var key in { toString: null }) {
+ hasDontEnumBug = false;
+ }
+
+ Object.keys = function keys(object) {
+ if (
+ (typeof object != "object" && typeof object != "function") ||
+ object === null
+ ) {
+ throw new TypeError("Object.keys called on a non-object");
+ }
+
+ var keys = [];
+ for (var name in object) {
+ if (owns(object, name)) {
+ keys.push(name);
+ }
+ }
+
+ if (hasDontEnumBug) {
+ for (var i = 0, ii = dontEnumsLength; i < ii; i++) {
+ var dontEnum = dontEnums[i];
+ if (owns(object, dontEnum)) {
+ keys.push(dontEnum);
+ }
+ }
+ }
+ return keys;
+ };
+ }
+ if (!Date.now) {
+ Date.now = function now() {
+ return new Date().getTime();
+ };
+ }
+ var ws =
+ "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u2000\u2001\u2002\u2003" +
+ "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" +
+ "\u2029\uFEFF";
+ if (!String.prototype.trim) {
+ ws = "[" + ws + "]";
+ var trimBeginRegexp = new RegExp("^" + ws + ws + "*"),
+ trimEndRegexp = new RegExp(ws + ws + "*$");
+ String.prototype.trim = function trim() {
+ return String(this)
+ .replace(trimBeginRegexp, "")
+ .replace(trimEndRegexp, "");
+ };
+ }
+
+ function toInteger(n) {
+ n = +n;
+ if (n !== n) {
+ // isNaN
+ n = 0;
+ } else if (n !== 0 && n !== 1 / 0 && n !== -(1 / 0)) {
+ n = (n > 0 || -1) * Math.floor(Math.abs(n));
+ }
+ return n;
+ }
+
+ function isPrimitive(input) {
+ var type = typeof input;
+ return (
+ input === null ||
+ type === "undefined" ||
+ type === "boolean" ||
+ type === "number" ||
+ type === "string"
+ );
+ }
+
+ function toPrimitive(input) {
+ var val, valueOf, toString;
+ if (isPrimitive(input)) {
+ return input;
+ }
+ valueOf = input.valueOf;
+ if (typeof valueOf === "function") {
+ val = valueOf.call(input);
+ if (isPrimitive(val)) {
+ return val;
+ }
+ }
+ toString = input.toString;
+ if (typeof toString === "function") {
+ val = toString.call(input);
+ if (isPrimitive(val)) {
+ return val;
+ }
+ }
+ throw new TypeError();
+ }
+ var toObject = function(o) {
+ if (o == null) {
+ // this matches both null and undefined
+ throw new TypeError("can't convert " + o + " to object");
+ }
+ return Object(o);
+ };
+});
+
+ace.define(
+ "ace/lib/fixoldbrowsers",
+ ["require", "exports", "module", "ace/lib/regexp", "ace/lib/es5-shim"],
+ function(require, exports, module) {
+ "use strict";
+
+ require("./regexp");
+ require("./es5-shim");
+ if (typeof Element != "undefined" && !Element.prototype.remove) {
+ Object.defineProperty(Element.prototype, "remove", {
+ enumerable: false,
+ writable: true,
+ configurable: true,
+ value: function() {
+ this.parentNode && this.parentNode.removeChild(this);
+ }
+ });
+ }
+ }
+);
+
+ace.define("ace/lib/useragent", ["require", "exports", "module"], function(
+ require,
+ exports,
+ module
+) {
+ "use strict";
+ exports.OS = {
+ LINUX: "LINUX",
+ MAC: "MAC",
+ WINDOWS: "WINDOWS"
+ };
+ exports.getOS = function() {
+ if (exports.isMac) {
+ return exports.OS.MAC;
+ } else if (exports.isLinux) {
+ return exports.OS.LINUX;
+ } else {
+ return exports.OS.WINDOWS;
+ }
+ };
+ var _navigator = typeof navigator == "object" ? navigator : {};
+
+ var os = (/mac|win|linux/i.exec(_navigator.platform) || [
+ "other"
+ ])[0].toLowerCase();
+ var ua = _navigator.userAgent || "";
+ var appName = _navigator.appName || "";
+ exports.isWin = os == "win";
+ exports.isMac = os == "mac";
+ exports.isLinux = os == "linux";
+ exports.isIE =
+ appName == "Microsoft Internet Explorer" ||
+ appName.indexOf("MSAppHost") >= 0
+ ? parseFloat(
+ (ua.match(
+ /(?:MSIE |Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/
+ ) || [])[1]
+ )
+ : parseFloat(
+ (ua.match(/(?:Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/) ||
+ [])[1]
+ ); // for ie
+
+ exports.isOldIE = exports.isIE && exports.isIE < 9;
+ exports.isGecko = exports.isMozilla = ua.match(/ Gecko\/\d+/);
+ exports.isOpera =
+ typeof opera == "object" &&
+ Object.prototype.toString.call(window.opera) == "[object Opera]";
+ exports.isWebKit = parseFloat(ua.split("WebKit/")[1]) || undefined;
+
+ exports.isChrome = parseFloat(ua.split(" Chrome/")[1]) || undefined;
+
+ exports.isEdge = parseFloat(ua.split(" Edge/")[1]) || undefined;
+
+ exports.isAIR = ua.indexOf("AdobeAIR") >= 0;
+
+ exports.isAndroid = ua.indexOf("Android") >= 0;
+
+ exports.isChromeOS = ua.indexOf(" CrOS ") >= 0;
+
+ exports.isIOS = /iPad|iPhone|iPod/.test(ua) && !window.MSStream;
+
+ if (exports.isIOS) exports.isMac = true;
+
+ exports.isMobile = exports.isIOS || exports.isAndroid;
+});
+
+ace.define(
+ "ace/lib/dom",
+ ["require", "exports", "module", "ace/lib/useragent"],
+ function(require, exports, module) {
+ "use strict";
+
+ var useragent = require("./useragent");
+ var XHTML_NS = "http://www.w3.org/1999/xhtml";
+
+ exports.buildDom = function buildDom(arr, parent, refs) {
+ if (typeof arr == "string" && arr) {
+ var txt = document.createTextNode(arr);
+ if (parent) parent.appendChild(txt);
+ return txt;
+ }
+
+ if (!Array.isArray(arr)) {
+ if (arr && arr.appendChild && parent) parent.appendChild(arr);
+ return arr;
+ }
+ if (typeof arr[0] != "string" || !arr[0]) {
+ var els = [];
+ for (var i = 0; i < arr.length; i++) {
+ var ch = buildDom(arr[i], parent, refs);
+ ch && els.push(ch);
+ }
+ return els;
+ }
+
+ var el = document.createElement(arr[0]);
+ var options = arr[1];
+ var childIndex = 1;
+ if (options && typeof options == "object" && !Array.isArray(options))
+ childIndex = 2;
+ for (var i = childIndex; i < arr.length; i++) buildDom(arr[i], el, refs);
+ if (childIndex == 2) {
+ Object.keys(options).forEach(function(n) {
+ var val = options[n];
+ if (n === "class") {
+ el.className = Array.isArray(val) ? val.join(" ") : val;
+ } else if (typeof val == "function" || n == "value" || n[0] == "$") {
+ el[n] = val;
+ } else if (n === "ref") {
+ if (refs) refs[val] = el;
+ } else if (val != null) {
+ el.setAttribute(n, val);
+ }
+ });
+ }
+ if (parent) parent.appendChild(el);
+ return el;
+ };
+
+ exports.getDocumentHead = function(doc) {
+ if (!doc) doc = document;
+ return (
+ doc.head || doc.getElementsByTagName("head")[0] || doc.documentElement
+ );
+ };
+
+ exports.createElement = function(tag, ns) {
+ return document.createElementNS
+ ? document.createElementNS(ns || XHTML_NS, tag)
+ : document.createElement(tag);
+ };
+
+ exports.removeChildren = function(element) {
+ element.innerHTML = "";
+ };
+
+ exports.createTextNode = function(textContent, element) {
+ var doc = element ? element.ownerDocument : document;
+ return doc.createTextNode(textContent);
+ };
+
+ exports.createFragment = function(element) {
+ var doc = element ? element.ownerDocument : document;
+ return doc.createDocumentFragment();
+ };
+
+ exports.hasCssClass = function(el, name) {
+ var classes = (el.className + "").split(/\s+/g);
+ return classes.indexOf(name) !== -1;
+ };
+ exports.addCssClass = function(el, name) {
+ if (!exports.hasCssClass(el, name)) {
+ el.className += " " + name;
+ }
+ };
+ exports.removeCssClass = function(el, name) {
+ var classes = el.className.split(/\s+/g);
+ while (true) {
+ var index = classes.indexOf(name);
+ if (index == -1) {
+ break;
+ }
+ classes.splice(index, 1);
+ }
+ el.className = classes.join(" ");
+ };
+
+ exports.toggleCssClass = function(el, name) {
+ var classes = el.className.split(/\s+/g),
+ add = true;
+ while (true) {
+ var index = classes.indexOf(name);
+ if (index == -1) {
+ break;
+ }
+ add = false;
+ classes.splice(index, 1);
+ }
+ if (add) classes.push(name);
+
+ el.className = classes.join(" ");
+ return add;
+ };
+ exports.setCssClass = function(node, className, include) {
+ if (include) {
+ exports.addCssClass(node, className);
+ } else {
+ exports.removeCssClass(node, className);
+ }
+ };
+
+ exports.hasCssString = function(id, doc) {
+ var index = 0,
+ sheets;
+ doc = doc || document;
+ if ((sheets = doc.querySelectorAll("style"))) {
+ while (index < sheets.length)
+ if (sheets[index++].id === id) return true;
+ }
+ };
+
+ exports.importCssString = function importCssString(cssText, id, target) {
+ var container = target;
+ if (!target || !target.getRootNode) {
+ container = document;
+ } else {
+ container = target.getRootNode();
+ if (!container || container == target) container = document;
+ }
+
+ var doc = container.ownerDocument || container;
+ if (id && exports.hasCssString(id, container)) return null;
+
+ if (id) cssText += "\n/*# sourceURL=ace/css/" + id + " */";
+
+ var style = exports.createElement("style");
+ style.appendChild(doc.createTextNode(cssText));
+ if (id) style.id = id;
+
+ if (container == doc) container = exports.getDocumentHead(doc);
+ container.insertBefore(style, container.firstChild);
+ };
+
+ exports.importCssStylsheet = function(uri, doc) {
+ exports.buildDom(
+ ["link", { rel: "stylesheet", href: uri }],
+ exports.getDocumentHead(doc)
+ );
+ };
+ exports.scrollbarWidth = function(document) {
+ var inner = exports.createElement("ace_inner");
+ inner.style.width = "100%";
+ inner.style.minWidth = "0px";
+ inner.style.height = "200px";
+ inner.style.display = "block";
+
+ var outer = exports.createElement("ace_outer");
+ var style = outer.style;
+
+ style.position = "absolute";
+ style.left = "-10000px";
+ style.overflow = "hidden";
+ style.width = "200px";
+ style.minWidth = "0px";
+ style.height = "150px";
+ style.display = "block";
+
+ outer.appendChild(inner);
+
+ var body = document.documentElement;
+ body.appendChild(outer);
+
+ var noScrollbar = inner.offsetWidth;
+
+ style.overflow = "scroll";
+ var withScrollbar = inner.offsetWidth;
+
+ if (noScrollbar == withScrollbar) {
+ withScrollbar = outer.clientWidth;
+ }
+
+ body.removeChild(outer);
+
+ return noScrollbar - withScrollbar;
+ };
+
+ if (typeof document == "undefined") {
+ exports.importCssString = function() {};
+ }
+
+ exports.computedStyle = function(element, style) {
+ return window.getComputedStyle(element, "") || {};
+ };
+
+ exports.setStyle = function(styles, property, value) {
+ if (styles[property] !== value) {
+ styles[property] = value;
+ }
+ };
+
+ exports.HAS_CSS_ANIMATION = false;
+ exports.HAS_CSS_TRANSFORMS = false;
+ exports.HI_DPI = useragent.isWin
+ ? typeof window !== "undefined" && window.devicePixelRatio >= 1.5
+ : true;
+
+ if (typeof document !== "undefined") {
+ var div = document.createElement("div");
+ if (exports.HI_DPI && div.style.transform !== undefined)
+ exports.HAS_CSS_TRANSFORMS = true;
+ if (!useragent.isEdge && typeof div.style.animationName !== "undefined")
+ exports.HAS_CSS_ANIMATION = true;
+ div = null;
+ }
+
+ if (exports.HAS_CSS_TRANSFORMS) {
+ exports.translate = function(element, tx, ty) {
+ element.style.transform =
+ "translate(" + Math.round(tx) + "px, " + Math.round(ty) + "px)";
+ };
+ } else {
+ exports.translate = function(element, tx, ty) {
+ element.style.top = Math.round(ty) + "px";
+ element.style.left = Math.round(tx) + "px";
+ };
+ }
+ }
+);
+
+ace.define("ace/lib/oop", ["require", "exports", "module"], function(
+ require,
+ exports,
+ module
+) {
+ "use strict";
+
+ exports.inherits = function(ctor, superCtor) {
+ ctor.super_ = superCtor;
+ ctor.prototype = Object.create(superCtor.prototype, {
+ constructor: {
+ value: ctor,
+ enumerable: false,
+ writable: true,
+ configurable: true
+ }
+ });
+ };
+
+ exports.mixin = function(obj, mixin) {
+ for (var key in mixin) {
+ obj[key] = mixin[key];
+ }
+ return obj;
+ };
+
+ exports.implement = function(proto, mixin) {
+ exports.mixin(proto, mixin);
+ };
+});
+
+ace.define(
+ "ace/lib/keys",
+ ["require", "exports", "module", "ace/lib/oop"],
+ function(require, exports, module) {
+ "use strict";
+
+ var oop = require("./oop");
+ var Keys = (function() {
+ var ret = {
+ MODIFIER_KEYS: {
+ 16: "Shift",
+ 17: "Ctrl",
+ 18: "Alt",
+ 224: "Meta",
+ 91: "MetaLeft",
+ 92: "MetaRight",
+ 93: "ContextMenu"
+ },
+
+ KEY_MODS: {
+ ctrl: 1,
+ alt: 2,
+ option: 2,
+ shift: 4,
+ super: 8,
+ meta: 8,
+ command: 8,
+ cmd: 8,
+ control: 1
+ },
+
+ FUNCTION_KEYS: {
+ 8: "Backspace",
+ 9: "Tab",
+ 13: "Return",
+ 19: "Pause",
+ 27: "Esc",
+ 32: "Space",
+ 33: "PageUp",
+ 34: "PageDown",
+ 35: "End",
+ 36: "Home",
+ 37: "Left",
+ 38: "Up",
+ 39: "Right",
+ 40: "Down",
+ 44: "Print",
+ 45: "Insert",
+ 46: "Delete",
+ 96: "Numpad0",
+ 97: "Numpad1",
+ 98: "Numpad2",
+ 99: "Numpad3",
+ 100: "Numpad4",
+ 101: "Numpad5",
+ 102: "Numpad6",
+ 103: "Numpad7",
+ 104: "Numpad8",
+ 105: "Numpad9",
+ "-13": "NumpadEnter",
+ 112: "F1",
+ 113: "F2",
+ 114: "F3",
+ 115: "F4",
+ 116: "F5",
+ 117: "F6",
+ 118: "F7",
+ 119: "F8",
+ 120: "F9",
+ 121: "F10",
+ 122: "F11",
+ 123: "F12",
+ 144: "Numlock",
+ 145: "Scrolllock"
+ },
+
+ PRINTABLE_KEYS: {
+ 32: " ",
+ 48: "0",
+ 49: "1",
+ 50: "2",
+ 51: "3",
+ 52: "4",
+ 53: "5",
+ 54: "6",
+ 55: "7",
+ 56: "8",
+ 57: "9",
+ 59: ";",
+ 61: "=",
+ 65: "a",
+ 66: "b",
+ 67: "c",
+ 68: "d",
+ 69: "e",
+ 70: "f",
+ 71: "g",
+ 72: "h",
+ 73: "i",
+ 74: "j",
+ 75: "k",
+ 76: "l",
+ 77: "m",
+ 78: "n",
+ 79: "o",
+ 80: "p",
+ 81: "q",
+ 82: "r",
+ 83: "s",
+ 84: "t",
+ 85: "u",
+ 86: "v",
+ 87: "w",
+ 88: "x",
+ 89: "y",
+ 90: "z",
+ 107: "+",
+ 109: "-",
+ 110: ".",
+ 186: ";",
+ 187: "=",
+ 188: ",",
+ 189: "-",
+ 190: ".",
+ 191: "/",
+ 192: "`",
+ 219: "[",
+ 220: "\\",
+ 221: "]",
+ 222: "'",
+ 111: "/",
+ 106: "*"
+ }
+ };
+ var name, i;
+ for (i in ret.FUNCTION_KEYS) {
+ name = ret.FUNCTION_KEYS[i].toLowerCase();
+ ret[name] = parseInt(i, 10);
+ }
+ for (i in ret.PRINTABLE_KEYS) {
+ name = ret.PRINTABLE_KEYS[i].toLowerCase();
+ ret[name] = parseInt(i, 10);
+ }
+ oop.mixin(ret, ret.MODIFIER_KEYS);
+ oop.mixin(ret, ret.PRINTABLE_KEYS);
+ oop.mixin(ret, ret.FUNCTION_KEYS);
+ ret.enter = ret["return"];
+ ret.escape = ret.esc;
+ ret.del = ret["delete"];
+ ret[173] = "-";
+
+ (function() {
+ var mods = ["cmd", "ctrl", "alt", "shift"];
+ for (var i = Math.pow(2, mods.length); i--; ) {
+ ret.KEY_MODS[i] =
+ mods
+ .filter(function(x) {
+ return i & ret.KEY_MODS[x];
+ })
+ .join("-") + "-";
+ }
+ })();
+
+ ret.KEY_MODS[0] = "";
+ ret.KEY_MODS[-1] = "input-";
+
+ return ret;
+ })();
+ oop.mixin(exports, Keys);
+
+ exports.keyCodeToString = function(keyCode) {
+ var keyString = Keys[keyCode];
+ if (typeof keyString != "string")
+ keyString = String.fromCharCode(keyCode);
+ return keyString.toLowerCase();
+ };
+ }
+);
+
+ace.define(
+ "ace/lib/event",
+ ["require", "exports", "module", "ace/lib/keys", "ace/lib/useragent"],
+ function(require, exports, module) {
+ "use strict";
+
+ var keys = require("./keys");
+ var useragent = require("./useragent");
+
+ var pressedKeys = null;
+ var ts = 0;
+
+ var activeListenerOptions;
+ function detectListenerOptionsSupport() {
+ activeListenerOptions = false;
+ try {
+ document.createComment("").addEventListener("test", function() {}, {
+ get passive() {
+ activeListenerOptions = { passive: false };
+ }
+ });
+ } catch (e) {}
+ }
+
+ function getListenerOptions() {
+ if (activeListenerOptions == undefined) detectListenerOptionsSupport();
+ return activeListenerOptions;
+ }
+
+ function EventListener(elem, type, callback) {
+ this.elem = elem;
+ this.type = type;
+ this.callback = callback;
+ }
+ EventListener.prototype.destroy = function() {
+ removeListener(this.elem, this.type, this.callback);
+ this.elem = this.type = this.callback = undefined;
+ };
+
+ var addListener = (exports.addListener = function(
+ elem,
+ type,
+ callback,
+ destroyer
+ ) {
+ elem.addEventListener(type, callback, getListenerOptions());
+ if (destroyer)
+ destroyer.$toDestroy.push(new EventListener(elem, type, callback));
+ });
+
+ var removeListener = (exports.removeListener = function(
+ elem,
+ type,
+ callback
+ ) {
+ elem.removeEventListener(type, callback, getListenerOptions());
+ });
+ exports.stopEvent = function(e) {
+ exports.stopPropagation(e);
+ exports.preventDefault(e);
+ return false;
+ };
+
+ exports.stopPropagation = function(e) {
+ if (e.stopPropagation) e.stopPropagation();
+ };
+
+ exports.preventDefault = function(e) {
+ if (e.preventDefault) e.preventDefault();
+ };
+ exports.getButton = function(e) {
+ if (e.type == "dblclick") return 0;
+ if (
+ e.type == "contextmenu" ||
+ (useragent.isMac && e.ctrlKey && !e.altKey && !e.shiftKey)
+ )
+ return 2;
+ return e.button;
+ };
+
+ exports.capture = function(el, eventHandler, releaseCaptureHandler) {
+ function onMouseUp(e) {
+ eventHandler && eventHandler(e);
+ releaseCaptureHandler && releaseCaptureHandler(e);
+
+ removeListener(document, "mousemove", eventHandler);
+ removeListener(document, "mouseup", onMouseUp);
+ removeListener(document, "dragstart", onMouseUp);
+ }
+
+ addListener(document, "mousemove", eventHandler);
+ addListener(document, "mouseup", onMouseUp);
+ addListener(document, "dragstart", onMouseUp);
+
+ return onMouseUp;
+ };
+
+ exports.addMouseWheelListener = function(el, callback, destroyer) {
+ if ("onmousewheel" in el) {
+ addListener(
+ el,
+ "mousewheel",
+ function(e) {
+ var factor = 8;
+ if (e.wheelDeltaX !== undefined) {
+ e.wheelX = -e.wheelDeltaX / factor;
+ e.wheelY = -e.wheelDeltaY / factor;
+ } else {
+ e.wheelX = 0;
+ e.wheelY = -e.wheelDelta / factor;
+ }
+ callback(e);
+ },
+ destroyer
+ );
+ } else if ("onwheel" in el) {
+ addListener(
+ el,
+ "wheel",
+ function(e) {
+ var factor = 0.35;
+ switch (e.deltaMode) {
+ case e.DOM_DELTA_PIXEL:
+ e.wheelX = e.deltaX * factor || 0;
+ e.wheelY = e.deltaY * factor || 0;
+ break;
+ case e.DOM_DELTA_LINE:
+ case e.DOM_DELTA_PAGE:
+ e.wheelX = (e.deltaX || 0) * 5;
+ e.wheelY = (e.deltaY || 0) * 5;
+ break;
+ }
+
+ callback(e);
+ },
+ destroyer
+ );
+ } else {
+ addListener(
+ el,
+ "DOMMouseScroll",
+ function(e) {
+ if (e.axis && e.axis == e.HORIZONTAL_AXIS) {
+ e.wheelX = (e.detail || 0) * 5;
+ e.wheelY = 0;
+ } else {
+ e.wheelX = 0;
+ e.wheelY = (e.detail || 0) * 5;
+ }
+ callback(e);
+ },
+ destroyer
+ );
+ }
+ };
+
+ exports.addMultiMouseDownListener = function(
+ elements,
+ timeouts,
+ eventHandler,
+ callbackName,
+ destroyer
+ ) {
+ var clicks = 0;
+ var startX, startY, timer;
+ var eventNames = {
+ 2: "dblclick",
+ 3: "tripleclick",
+ 4: "quadclick"
+ };
+
+ function onMousedown(e) {
+ if (exports.getButton(e) !== 0) {
+ clicks = 0;
+ } else if (e.detail > 1) {
+ clicks++;
+ if (clicks > 4) clicks = 1;
+ } else {
+ clicks = 1;
+ }
+ if (useragent.isIE) {
+ var isNewClick =
+ Math.abs(e.clientX - startX) > 5 ||
+ Math.abs(e.clientY - startY) > 5;
+ if (!timer || isNewClick) clicks = 1;
+ if (timer) clearTimeout(timer);
+ timer = setTimeout(function() {
+ timer = null;
+ }, timeouts[clicks - 1] || 600);
+
+ if (clicks == 1) {
+ startX = e.clientX;
+ startY = e.clientY;
+ }
+ }
+
+ e._clicks = clicks;
+
+ eventHandler[callbackName]("mousedown", e);
+
+ if (clicks > 4) clicks = 0;
+ else if (clicks > 1)
+ return eventHandler[callbackName](eventNames[clicks], e);
+ }
+ if (!Array.isArray(elements)) elements = [elements];
+ elements.forEach(function(el) {
+ addListener(el, "mousedown", onMousedown, destroyer);
+ });
+ };
+
+ var getModifierHash = function(e) {
+ return (
+ 0 |
+ (e.ctrlKey ? 1 : 0) |
+ (e.altKey ? 2 : 0) |
+ (e.shiftKey ? 4 : 0) |
+ (e.metaKey ? 8 : 0)
+ );
+ };
+
+ exports.getModifierString = function(e) {
+ return keys.KEY_MODS[getModifierHash(e)];
+ };
+
+ function normalizeCommandKeys(callback, e, keyCode) {
+ var hashId = getModifierHash(e);
+
+ if (!useragent.isMac && pressedKeys) {
+ if (
+ e.getModifierState &&
+ (e.getModifierState("OS") || e.getModifierState("Win"))
+ )
+ hashId |= 8;
+ if (pressedKeys.altGr) {
+ if ((3 & hashId) != 3) pressedKeys.altGr = 0;
+ else return;
+ }
+ if (keyCode === 18 || keyCode === 17) {
+ var location = "location" in e ? e.location : e.keyLocation;
+ if (keyCode === 17 && location === 1) {
+ if (pressedKeys[keyCode] == 1) ts = e.timeStamp;
+ } else if (keyCode === 18 && hashId === 3 && location === 2) {
+ var dt = e.timeStamp - ts;
+ if (dt < 50) pressedKeys.altGr = true;
+ }
+ }
+ }
+
+ if (keyCode in keys.MODIFIER_KEYS) {
+ keyCode = -1;
+ }
+
+ if (!hashId && keyCode === 13) {
+ var location = "location" in e ? e.location : e.keyLocation;
+ if (location === 3) {
+ callback(e, hashId, -keyCode);
+ if (e.defaultPrevented) return;
+ }
+ }
+
+ if (useragent.isChromeOS && hashId & 8) {
+ callback(e, hashId, keyCode);
+ if (e.defaultPrevented) return;
+ else hashId &= ~8;
+ }
+ if (
+ !hashId &&
+ !(keyCode in keys.FUNCTION_KEYS) &&
+ !(keyCode in keys.PRINTABLE_KEYS)
+ ) {
+ return false;
+ }
+
+ return callback(e, hashId, keyCode);
+ }
+
+ exports.addCommandKeyListener = function(el, callback, destroyer) {
+ if (
+ useragent.isOldGecko ||
+ (useragent.isOpera && !("KeyboardEvent" in window))
+ ) {
+ var lastKeyDownKeyCode = null;
+ addListener(
+ el,
+ "keydown",
+ function(e) {
+ lastKeyDownKeyCode = e.keyCode;
+ },
+ destroyer
+ );
+ addListener(
+ el,
+ "keypress",
+ function(e) {
+ return normalizeCommandKeys(callback, e, lastKeyDownKeyCode);
+ },
+ destroyer
+ );
+ } else {
+ var lastDefaultPrevented = null;
+
+ addListener(
+ el,
+ "keydown",
+ function(e) {
+ pressedKeys[e.keyCode] = (pressedKeys[e.keyCode] || 0) + 1;
+ var result = normalizeCommandKeys(callback, e, e.keyCode);
+ lastDefaultPrevented = e.defaultPrevented;
+ return result;
+ },
+ destroyer
+ );
+
+ addListener(
+ el,
+ "keypress",
+ function(e) {
+ if (
+ lastDefaultPrevented &&
+ (e.ctrlKey || e.altKey || e.shiftKey || e.metaKey)
+ ) {
+ exports.stopEvent(e);
+ lastDefaultPrevented = null;
+ }
+ },
+ destroyer
+ );
+
+ addListener(
+ el,
+ "keyup",
+ function(e) {
+ pressedKeys[e.keyCode] = null;
+ },
+ destroyer
+ );
+
+ if (!pressedKeys) {
+ resetPressedKeys();
+ addListener(window, "focus", resetPressedKeys);
+ }
+ }
+ };
+ function resetPressedKeys() {
+ pressedKeys = Object.create(null);
+ }
+
+ if (typeof window == "object" && window.postMessage && !useragent.isOldIE) {
+ var postMessageId = 1;
+ exports.nextTick = function(callback, win) {
+ win = win || window;
+ var messageName = "zero-timeout-message-" + postMessageId++;
+
+ var listener = function(e) {
+ if (e.data == messageName) {
+ exports.stopPropagation(e);
+ removeListener(win, "message", listener);
+ callback();
+ }
+ };
+
+ addListener(win, "message", listener);
+ win.postMessage(messageName, "*");
+ };
+ }
+
+ exports.$idleBlocked = false;
+ exports.onIdle = function(cb, timeout) {
+ return setTimeout(function handler() {
+ if (!exports.$idleBlocked) {
+ cb();
+ } else {
+ setTimeout(handler, 100);
+ }
+ }, timeout);
+ };
+
+ exports.$idleBlockId = null;
+ exports.blockIdle = function(delay) {
+ if (exports.$idleBlockId) clearTimeout(exports.$idleBlockId);
+
+ exports.$idleBlocked = true;
+ exports.$idleBlockId = setTimeout(function() {
+ exports.$idleBlocked = false;
+ }, delay || 100);
+ };
+
+ exports.nextFrame =
+ typeof window == "object" &&
+ (window.requestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.msRequestAnimationFrame ||
+ window.oRequestAnimationFrame);
+
+ if (exports.nextFrame) exports.nextFrame = exports.nextFrame.bind(window);
+ else
+ exports.nextFrame = function(callback) {
+ setTimeout(callback, 17);
+ };
+ }
+);
+
+ace.define("ace/range", ["require", "exports", "module"], function(
+ require,
+ exports,
+ module
+) {
+ "use strict";
+ var comparePoints = function(p1, p2) {
+ return p1.row - p2.row || p1.column - p2.column;
+ };
+ var Range = function(startRow, startColumn, endRow, endColumn) {
+ this.start = {
+ row: startRow,
+ column: startColumn
+ };
+
+ this.end = {
+ row: endRow,
+ column: endColumn
+ };
+ };
+
+ (function() {
+ this.isEqual = function(range) {
+ return (
+ this.start.row === range.start.row &&
+ this.end.row === range.end.row &&
+ this.start.column === range.start.column &&
+ this.end.column === range.end.column
+ );
+ };
+ this.toString = function() {
+ return (
+ "Range: [" +
+ this.start.row +
+ "/" +
+ this.start.column +
+ "] -> [" +
+ this.end.row +
+ "/" +
+ this.end.column +
+ "]"
+ );
+ };
+
+ this.contains = function(row, column) {
+ return this.compare(row, column) == 0;
+ };
+ this.compareRange = function(range) {
+ var cmp,
+ end = range.end,
+ start = range.start;
+
+ cmp = this.compare(end.row, end.column);
+ if (cmp == 1) {
+ cmp = this.compare(start.row, start.column);
+ if (cmp == 1) {
+ return 2;
+ } else if (cmp == 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+ } else if (cmp == -1) {
+ return -2;
+ } else {
+ cmp = this.compare(start.row, start.column);
+ if (cmp == -1) {
+ return -1;
+ } else if (cmp == 1) {
+ return 42;
+ } else {
+ return 0;
+ }
+ }
+ };
+ this.comparePoint = function(p) {
+ return this.compare(p.row, p.column);
+ };
+ this.containsRange = function(range) {
+ return (
+ this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0
+ );
+ };
+ this.intersects = function(range) {
+ var cmp = this.compareRange(range);
+ return cmp == -1 || cmp == 0 || cmp == 1;
+ };
+ this.isEnd = function(row, column) {
+ return this.end.row == row && this.end.column == column;
+ };
+ this.isStart = function(row, column) {
+ return this.start.row == row && this.start.column == column;
+ };
+ this.setStart = function(row, column) {
+ if (typeof row == "object") {
+ this.start.column = row.column;
+ this.start.row = row.row;
+ } else {
+ this.start.row = row;
+ this.start.column = column;
+ }
+ };
+ this.setEnd = function(row, column) {
+ if (typeof row == "object") {
+ this.end.column = row.column;
+ this.end.row = row.row;
+ } else {
+ this.end.row = row;
+ this.end.column = column;
+ }
+ };
+ this.inside = function(row, column) {
+ if (this.compare(row, column) == 0) {
+ if (this.isEnd(row, column) || this.isStart(row, column)) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+ return false;
+ };
+ this.insideStart = function(row, column) {
+ if (this.compare(row, column) == 0) {
+ if (this.isEnd(row, column)) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+ return false;
+ };
+ this.insideEnd = function(row, column) {
+ if (this.compare(row, column) == 0) {
+ if (this.isStart(row, column)) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+ return false;
+ };
+ this.compare = function(row, column) {
+ if (!this.isMultiLine()) {
+ if (row === this.start.row) {
+ return column < this.start.column
+ ? -1
+ : column > this.end.column
+ ? 1
+ : 0;
+ }
+ }
+
+ if (row < this.start.row) return -1;
+
+ if (row > this.end.row) return 1;
+
+ if (this.start.row === row) return column >= this.start.column ? 0 : -1;
+
+ if (this.end.row === row) return column <= this.end.column ? 0 : 1;
+
+ return 0;
+ };
+ this.compareStart = function(row, column) {
+ if (this.start.row == row && this.start.column == column) {
+ return -1;
+ } else {
+ return this.compare(row, column);
+ }
+ };
+ this.compareEnd = function(row, column) {
+ if (this.end.row == row && this.end.column == column) {
+ return 1;
+ } else {
+ return this.compare(row, column);
+ }
+ };
+ this.compareInside = function(row, column) {
+ if (this.end.row == row && this.end.column == column) {
+ return 1;
+ } else if (this.start.row == row && this.start.column == column) {
+ return -1;
+ } else {
+ return this.compare(row, column);
+ }
+ };
+ this.clipRows = function(firstRow, lastRow) {
+ if (this.end.row > lastRow) var end = { row: lastRow + 1, column: 0 };
+ else if (this.end.row < firstRow) var end = { row: firstRow, column: 0 };
+
+ if (this.start.row > lastRow) var start = { row: lastRow + 1, column: 0 };
+ else if (this.start.row < firstRow)
+ var start = { row: firstRow, column: 0 };
+
+ return Range.fromPoints(start || this.start, end || this.end);
+ };
+ this.extend = function(row, column) {
+ var cmp = this.compare(row, column);
+
+ if (cmp == 0) return this;
+ else if (cmp == -1) var start = { row: row, column: column };
+ else var end = { row: row, column: column };
+
+ return Range.fromPoints(start || this.start, end || this.end);
+ };
+
+ this.isEmpty = function() {
+ return (
+ this.start.row === this.end.row && this.start.column === this.end.column
+ );
+ };
+ this.isMultiLine = function() {
+ return this.start.row !== this.end.row;
+ };
+ this.clone = function() {
+ return Range.fromPoints(this.start, this.end);
+ };
+ this.collapseRows = function() {
+ if (this.end.column == 0)
+ return new Range(
+ this.start.row,
+ 0,
+ Math.max(this.start.row, this.end.row - 1),
+ 0
+ );
+ else return new Range(this.start.row, 0, this.end.row, 0);
+ };
+ this.toScreenRange = function(session) {
+ var screenPosStart = session.documentToScreenPosition(this.start);
+ var screenPosEnd = session.documentToScreenPosition(this.end);
+
+ return new Range(
+ screenPosStart.row,
+ screenPosStart.column,
+ screenPosEnd.row,
+ screenPosEnd.column
+ );
+ };
+ this.moveBy = function(row, column) {
+ this.start.row += row;
+ this.start.column += column;
+ this.end.row += row;
+ this.end.column += column;
+ };
+ }.call(Range.prototype));
+ Range.fromPoints = function(start, end) {
+ return new Range(start.row, start.column, end.row, end.column);
+ };
+ Range.comparePoints = comparePoints;
+
+ Range.comparePoints = function(p1, p2) {
+ return p1.row - p2.row || p1.column - p2.column;
+ };
+
+ exports.Range = Range;
+});
+
+ace.define("ace/lib/lang", ["require", "exports", "module"], function(
+ require,
+ exports,
+ module
+) {
+ "use strict";
+
+ exports.last = function(a) {
+ return a[a.length - 1];
+ };
+
+ exports.stringReverse = function(string) {
+ return string
+ .split("")
+ .reverse()
+ .join("");
+ };
+
+ exports.stringRepeat = function(string, count) {
+ var result = "";
+ while (count > 0) {
+ if (count & 1) result += string;
+
+ if ((count >>= 1)) string += string;
+ }
+ return result;
+ };
+
+ var trimBeginRegexp = /^\s\s*/;
+ var trimEndRegexp = /\s\s*$/;
+
+ exports.stringTrimLeft = function(string) {
+ return string.replace(trimBeginRegexp, "");
+ };
+
+ exports.stringTrimRight = function(string) {
+ return string.replace(trimEndRegexp, "");
+ };
+
+ exports.copyObject = function(obj) {
+ var copy = {};
+ for (var key in obj) {
+ copy[key] = obj[key];
+ }
+ return copy;
+ };
+
+ exports.copyArray = function(array) {
+ var copy = [];
+ for (var i = 0, l = array.length; i < l; i++) {
+ if (array[i] && typeof array[i] == "object")
+ copy[i] = this.copyObject(array[i]);
+ else copy[i] = array[i];
+ }
+ return copy;
+ };
+
+ exports.deepCopy = function deepCopy(obj) {
+ if (typeof obj !== "object" || !obj) return obj;
+ var copy;
+ if (Array.isArray(obj)) {
+ copy = [];
+ for (var key = 0; key < obj.length; key++) {
+ copy[key] = deepCopy(obj[key]);
+ }
+ return copy;
+ }
+ if (Object.prototype.toString.call(obj) !== "[object Object]") return obj;
+
+ copy = {};
+ for (var key in obj) copy[key] = deepCopy(obj[key]);
+ return copy;
+ };
+
+ exports.arrayToMap = function(arr) {
+ var map = {};
+ for (var i = 0; i < arr.length; i++) {
+ map[arr[i]] = 1;
+ }
+ return map;
+ };
+
+ exports.createMap = function(props) {
+ var map = Object.create(null);
+ for (var i in props) {
+ map[i] = props[i];
+ }
+ return map;
+ };
+ exports.arrayRemove = function(array, value) {
+ for (var i = 0; i <= array.length; i++) {
+ if (value === array[i]) {
+ array.splice(i, 1);
+ }
+ }
+ };
+
+ exports.escapeRegExp = function(str) {
+ return str.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
+ };
+
+ exports.escapeHTML = function(str) {
+ return ("" + str)
+ .replace(/&/g, "&")
+ .replace(/"/g, """)
+ .replace(/'/g, "'")
+ .replace(/ Date.now() - 50) return true;
+ return ($cancelT = false);
+ },
+ cancel: function() {
+ $cancelT = Date.now();
+ }
+ };
+});
+
+ace.define(
+ "ace/keyboard/textinput",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/lib/event",
+ "ace/lib/useragent",
+ "ace/lib/dom",
+ "ace/lib/lang",
+ "ace/clipboard",
+ "ace/lib/keys"
+ ],
+ function(require, exports, module) {
+ "use strict";
+
+ var event = require("../lib/event");
+ var useragent = require("../lib/useragent");
+ var dom = require("../lib/dom");
+ var lang = require("../lib/lang");
+ var clipboard = require("../clipboard");
+ var BROKEN_SETDATA = useragent.isChrome < 18;
+ var USE_IE_MIME_TYPE = useragent.isIE;
+ var HAS_FOCUS_ARGS = useragent.isChrome > 63;
+ var MAX_LINE_LENGTH = 400;
+
+ var KEYS = require("../lib/keys");
+ var MODS = KEYS.KEY_MODS;
+ var isIOS = useragent.isIOS;
+ var valueResetRegex = isIOS ? /\s/ : /\n/;
+ var isMobile = useragent.isMobile;
+
+ var TextInput = function(parentNode, host) {
+ var text = dom.createElement("textarea");
+ text.className = "ace_text-input";
+
+ text.setAttribute("wrap", "off");
+ text.setAttribute("autocorrect", "off");
+ text.setAttribute("autocapitalize", "off");
+ text.setAttribute("spellcheck", false);
+
+ text.style.opacity = "0";
+ parentNode.insertBefore(text, parentNode.firstChild);
+
+ var copied = false;
+ var pasted = false;
+ var inComposition = false;
+ var sendingText = false;
+ var tempStyle = "";
+
+ if (!isMobile) text.style.fontSize = "1px";
+
+ var commandMode = false;
+ var ignoreFocusEvents = false;
+
+ var lastValue = "";
+ var lastSelectionStart = 0;
+ var lastSelectionEnd = 0;
+ var lastRestoreEnd = 0;
+ try {
+ var isFocused = document.activeElement === text;
+ } catch (e) {}
+
+ event.addListener(
+ text,
+ "blur",
+ function(e) {
+ if (ignoreFocusEvents) return;
+ host.onBlur(e);
+ isFocused = false;
+ },
+ host
+ );
+ event.addListener(
+ text,
+ "focus",
+ function(e) {
+ if (ignoreFocusEvents) return;
+ isFocused = true;
+ if (useragent.isEdge) {
+ try {
+ if (!document.hasFocus()) return;
+ } catch (e) {}
+ }
+ host.onFocus(e);
+ if (useragent.isEdge) setTimeout(resetSelection);
+ else resetSelection();
+ },
+ host
+ );
+ this.$focusScroll = false;
+ this.focus = function() {
+ if (tempStyle || HAS_FOCUS_ARGS || this.$focusScroll == "browser")
+ return text.focus({ preventScroll: true });
+
+ var top = text.style.top;
+ text.style.position = "fixed";
+ text.style.top = "0px";
+ try {
+ var isTransformed = text.getBoundingClientRect().top != 0;
+ } catch (e) {
+ return;
+ }
+ var ancestors = [];
+ if (isTransformed) {
+ var t = text.parentElement;
+ while (t && t.nodeType == 1) {
+ ancestors.push(t);
+ t.setAttribute("ace_nocontext", true);
+ if (!t.parentElement && t.getRootNode) t = t.getRootNode().host;
+ else t = t.parentElement;
+ }
+ }
+ text.focus({ preventScroll: true });
+ if (isTransformed) {
+ ancestors.forEach(function(p) {
+ p.removeAttribute("ace_nocontext");
+ });
+ }
+ setTimeout(function() {
+ text.style.position = "";
+ if (text.style.top == "0px") text.style.top = top;
+ }, 0);
+ };
+ this.blur = function() {
+ text.blur();
+ };
+ this.isFocused = function() {
+ return isFocused;
+ };
+
+ host.on("beforeEndOperation", function() {
+ var curOp = host.curOp;
+ var commandName = curOp && curOp.command && curOp.command.name;
+ if (commandName == "insertstring") return;
+ var isUserAction =
+ commandName && (curOp.docChanged || curOp.selectionChanged);
+ if (inComposition && isUserAction) {
+ lastValue = text.value = "";
+ onCompositionEnd();
+ }
+ resetSelection();
+ });
+
+ var resetSelection = isIOS
+ ? function(value) {
+ if (!isFocused || (copied && !value) || sendingText) return;
+ if (!value) value = "";
+ var newValue = "\n ab" + value + "cde fg\n";
+ if (newValue != text.value) text.value = lastValue = newValue;
+
+ var selectionStart = 4;
+ var selectionEnd =
+ 4 + (value.length || (host.selection.isEmpty() ? 0 : 1));
+
+ if (
+ lastSelectionStart != selectionStart ||
+ lastSelectionEnd != selectionEnd
+ ) {
+ text.setSelectionRange(selectionStart, selectionEnd);
+ }
+ lastSelectionStart = selectionStart;
+ lastSelectionEnd = selectionEnd;
+ }
+ : function() {
+ if (inComposition || sendingText) return;
+ if (!isFocused && !afterContextMenu) return;
+ inComposition = true;
+
+ var selectionStart = 0;
+ var selectionEnd = 0;
+ var line = "";
+
+ if (host.session) {
+ var selection = host.selection;
+ var range = selection.getRange();
+ var row = selection.cursor.row;
+ selectionStart = range.start.column;
+ selectionEnd = range.end.column;
+ line = host.session.getLine(row);
+
+ if (range.start.row != row) {
+ var prevLine = host.session.getLine(row - 1);
+ selectionStart = range.start.row < row - 1 ? 0 : selectionStart;
+ selectionEnd += prevLine.length + 1;
+ line = prevLine + "\n" + line;
+ } else if (range.end.row != row) {
+ var nextLine = host.session.getLine(row + 1);
+ selectionEnd =
+ range.end.row > row + 1 ? nextLine.length : selectionEnd;
+ selectionEnd += line.length + 1;
+ line = line + "\n" + nextLine;
+ } else if (isMobile && row > 0) {
+ line = "\n" + line;
+ selectionEnd += 1;
+ selectionStart += 1;
+ }
+
+ if (line.length > MAX_LINE_LENGTH) {
+ if (
+ selectionStart < MAX_LINE_LENGTH &&
+ selectionEnd < MAX_LINE_LENGTH
+ ) {
+ line = line.slice(0, MAX_LINE_LENGTH);
+ } else {
+ line = "\n";
+ selectionStart = 0;
+ selectionEnd = 1;
+ }
+ }
+ }
+
+ var newValue = line + "\n\n";
+ if (newValue != lastValue) {
+ text.value = lastValue = newValue;
+ lastSelectionStart = lastSelectionEnd = newValue.length;
+ }
+ if (afterContextMenu) {
+ lastSelectionStart = text.selectionStart;
+ lastSelectionEnd = text.selectionEnd;
+ }
+ if (
+ lastSelectionEnd != selectionEnd ||
+ lastSelectionStart != selectionStart ||
+ text.selectionEnd != lastSelectionEnd // on ie edge selectionEnd changes silently after the initialization
+ ) {
+ try {
+ text.setSelectionRange(selectionStart, selectionEnd);
+ lastSelectionStart = selectionStart;
+ lastSelectionEnd = selectionEnd;
+ } catch (e) {}
+ }
+ inComposition = false;
+ };
+ this.resetSelection = resetSelection;
+
+ if (isFocused) host.onFocus();
+
+ var isAllSelected = function(text) {
+ return (
+ text.selectionStart === 0 &&
+ text.selectionEnd >= lastValue.length &&
+ text.value === lastValue &&
+ lastValue &&
+ text.selectionEnd !== lastSelectionEnd
+ );
+ };
+
+ var onSelect = function(e) {
+ if (inComposition) return;
+ if (copied) {
+ copied = false;
+ } else if (isAllSelected(text)) {
+ host.selectAll();
+ resetSelection();
+ } else if (isMobile && text.selectionStart != lastSelectionStart) {
+ resetSelection();
+ }
+ };
+
+ var inputHandler = null;
+ this.setInputHandler = function(cb) {
+ inputHandler = cb;
+ };
+ this.getInputHandler = function() {
+ return inputHandler;
+ };
+ var afterContextMenu = false;
+
+ var sendText = function(value, fromInput) {
+ if (afterContextMenu) afterContextMenu = false;
+ if (pasted) {
+ resetSelection();
+ if (value) host.onPaste(value);
+ pasted = false;
+ return "";
+ } else {
+ var selectionStart = text.selectionStart;
+ var selectionEnd = text.selectionEnd;
+
+ var extendLeft = lastSelectionStart;
+ var extendRight = lastValue.length - lastSelectionEnd;
+
+ var inserted = value;
+ var restoreStart = value.length - selectionStart;
+ var restoreEnd = value.length - selectionEnd;
+
+ var i = 0;
+ while (extendLeft > 0 && lastValue[i] == value[i]) {
+ i++;
+ extendLeft--;
+ }
+ inserted = inserted.slice(i);
+ i = 1;
+ while (
+ extendRight > 0 &&
+ lastValue.length - i > lastSelectionStart - 1 &&
+ lastValue[lastValue.length - i] == value[value.length - i]
+ ) {
+ i++;
+ extendRight--;
+ }
+ restoreStart -= i - 1;
+ restoreEnd -= i - 1;
+ var endIndex = inserted.length - i + 1;
+ if (endIndex < 0) {
+ extendLeft = -endIndex;
+ endIndex = 0;
+ }
+ inserted = inserted.slice(0, endIndex);
+ if (
+ !fromInput &&
+ !inserted &&
+ !restoreStart &&
+ !extendLeft &&
+ !extendRight &&
+ !restoreEnd
+ )
+ return "";
+ sendingText = true;
+ if (
+ (inserted &&
+ !extendLeft &&
+ !extendRight &&
+ !restoreStart &&
+ !restoreEnd) ||
+ commandMode
+ ) {
+ host.onTextInput(inserted);
+ } else {
+ host.onTextInput(inserted, {
+ extendLeft: extendLeft,
+ extendRight: extendRight,
+ restoreStart: restoreStart,
+ restoreEnd: restoreEnd
+ });
+ }
+ sendingText = false;
+
+ lastValue = value;
+ lastSelectionStart = selectionStart;
+ lastSelectionEnd = selectionEnd;
+ lastRestoreEnd = restoreEnd;
+ return inserted;
+ }
+ };
+ var onInput = function(e) {
+ if (inComposition) return onCompositionUpdate();
+ if (e && e.inputType) {
+ if (e.inputType == "historyUndo") return host.execCommand("undo");
+ if (e.inputType == "historyRedo") return host.execCommand("redo");
+ }
+ var data = text.value;
+ var inserted = sendText(data, true);
+ if (
+ data.length > MAX_LINE_LENGTH + 100 ||
+ valueResetRegex.test(inserted) ||
+ (isMobile &&
+ lastSelectionStart < 1 &&
+ lastSelectionStart == lastSelectionEnd)
+ ) {
+ resetSelection();
+ }
+ };
+
+ var handleClipboardData = function(e, data, forceIEMime) {
+ var clipboardData = e.clipboardData || window.clipboardData;
+ if (!clipboardData || BROKEN_SETDATA) return;
+ var mime = USE_IE_MIME_TYPE || forceIEMime ? "Text" : "text/plain";
+ try {
+ if (data) {
+ return clipboardData.setData(mime, data) !== false;
+ } else {
+ return clipboardData.getData(mime);
+ }
+ } catch (e) {
+ if (!forceIEMime) return handleClipboardData(e, data, true);
+ }
+ };
+
+ var doCopy = function(e, isCut) {
+ var data = host.getCopyText();
+ if (!data) return event.preventDefault(e);
+
+ if (handleClipboardData(e, data)) {
+ if (isIOS) {
+ resetSelection(data);
+ copied = data;
+ setTimeout(function() {
+ copied = false;
+ }, 10);
+ }
+ isCut ? host.onCut() : host.onCopy();
+ event.preventDefault(e);
+ } else {
+ copied = true;
+ text.value = data;
+ text.select();
+ setTimeout(function() {
+ copied = false;
+ resetSelection();
+ isCut ? host.onCut() : host.onCopy();
+ });
+ }
+ };
+
+ var onCut = function(e) {
+ doCopy(e, true);
+ };
+
+ var onCopy = function(e) {
+ doCopy(e, false);
+ };
+
+ var onPaste = function(e) {
+ var data = handleClipboardData(e);
+ if (clipboard.pasteCancelled()) return;
+ if (typeof data == "string") {
+ if (data) host.onPaste(data, e);
+ if (useragent.isIE) setTimeout(resetSelection);
+ event.preventDefault(e);
+ } else {
+ text.value = "";
+ pasted = true;
+ }
+ };
+
+ event.addCommandKeyListener(text, host.onCommandKey.bind(host), host);
+
+ event.addListener(text, "select", onSelect, host);
+ event.addListener(text, "input", onInput, host);
+
+ event.addListener(text, "cut", onCut, host);
+ event.addListener(text, "copy", onCopy, host);
+ event.addListener(text, "paste", onPaste, host);
+ if (!("oncut" in text) || !("oncopy" in text) || !("onpaste" in text)) {
+ event.addListener(
+ parentNode,
+ "keydown",
+ function(e) {
+ if ((useragent.isMac && !e.metaKey) || !e.ctrlKey) return;
+
+ switch (e.keyCode) {
+ case 67:
+ onCopy(e);
+ break;
+ case 86:
+ onPaste(e);
+ break;
+ case 88:
+ onCut(e);
+ break;
+ }
+ },
+ host
+ );
+ }
+ var onCompositionStart = function(e) {
+ if (inComposition || !host.onCompositionStart || host.$readOnly) return;
+
+ inComposition = {};
+
+ if (commandMode) return;
+
+ if (e.data) inComposition.useTextareaForIME = false;
+
+ setTimeout(onCompositionUpdate, 0);
+ host._signal("compositionStart");
+ host.on("mousedown", cancelComposition);
+
+ var range = host.getSelectionRange();
+ range.end.row = range.start.row;
+ range.end.column = range.start.column;
+ inComposition.markerRange = range;
+ inComposition.selectionStart = lastSelectionStart;
+ host.onCompositionStart(inComposition);
+
+ if (inComposition.useTextareaForIME) {
+ lastValue = text.value = "";
+ lastSelectionStart = 0;
+ lastSelectionEnd = 0;
+ } else {
+ if (text.msGetInputContext)
+ inComposition.context = text.msGetInputContext();
+ if (text.getInputContext)
+ inComposition.context = text.getInputContext();
+ }
+ };
+
+ var onCompositionUpdate = function() {
+ if (!inComposition || !host.onCompositionUpdate || host.$readOnly)
+ return;
+ if (commandMode) return cancelComposition();
+
+ if (inComposition.useTextareaForIME) {
+ host.onCompositionUpdate(text.value);
+ } else {
+ var data = text.value;
+ sendText(data);
+ if (inComposition.markerRange) {
+ if (inComposition.context) {
+ inComposition.markerRange.start.column = inComposition.selectionStart =
+ inComposition.context.compositionStartOffset;
+ }
+ inComposition.markerRange.end.column =
+ inComposition.markerRange.start.column +
+ lastSelectionEnd -
+ inComposition.selectionStart +
+ lastRestoreEnd;
+ }
+ }
+ };
+
+ var onCompositionEnd = function(e) {
+ if (!host.onCompositionEnd || host.$readOnly) return;
+ inComposition = false;
+ host.onCompositionEnd();
+ host.off("mousedown", cancelComposition);
+ if (e) onInput();
+ };
+
+ function cancelComposition() {
+ ignoreFocusEvents = true;
+ text.blur();
+ text.focus();
+ ignoreFocusEvents = false;
+ }
+
+ var syncComposition = lang
+ .delayedCall(onCompositionUpdate, 50)
+ .schedule.bind(null, null);
+
+ function onKeyup(e) {
+ if (e.keyCode == 27 && text.value.length < text.selectionStart) {
+ if (!inComposition) lastValue = text.value;
+ lastSelectionStart = lastSelectionEnd = -1;
+ resetSelection();
+ }
+ syncComposition();
+ }
+
+ event.addListener(text, "compositionstart", onCompositionStart, host);
+ event.addListener(text, "compositionupdate", onCompositionUpdate, host);
+ event.addListener(text, "keyup", onKeyup, host);
+ event.addListener(text, "keydown", syncComposition, host);
+ event.addListener(text, "compositionend", onCompositionEnd, host);
+
+ this.getElement = function() {
+ return text;
+ };
+ this.setCommandMode = function(value) {
+ commandMode = value;
+ text.readOnly = false;
+ };
+
+ this.setReadOnly = function(readOnly) {
+ if (!commandMode) text.readOnly = readOnly;
+ };
+
+ this.setCopyWithEmptySelection = function(value) {};
+
+ this.onContextMenu = function(e) {
+ afterContextMenu = true;
+ resetSelection();
+ host._emit("nativecontextmenu", { target: host, domEvent: e });
+ this.moveToMouse(e, true);
+ };
+
+ this.moveToMouse = function(e, bringToFront) {
+ if (!tempStyle) tempStyle = text.style.cssText;
+ text.style.cssText =
+ (bringToFront ? "z-index:100000;" : "") +
+ (useragent.isIE ? "opacity:0.1;" : "") +
+ "text-indent: -" +
+ (lastSelectionStart + lastSelectionEnd) *
+ host.renderer.characterWidth *
+ 0.5 +
+ "px;";
+
+ var rect = host.container.getBoundingClientRect();
+ var style = dom.computedStyle(host.container);
+ var top = rect.top + (parseInt(style.borderTopWidth) || 0);
+ var left = rect.left + (parseInt(rect.borderLeftWidth) || 0);
+ var maxTop = rect.bottom - top - text.clientHeight - 2;
+ var move = function(e) {
+ dom.translate(
+ text,
+ e.clientX - left - 2,
+ Math.min(e.clientY - top - 2, maxTop)
+ );
+ };
+ move(e);
+
+ if (e.type != "mousedown") return;
+
+ host.renderer.$isMousePressed = true;
+
+ clearTimeout(closeTimeout);
+ if (useragent.isWin)
+ event.capture(host.container, move, onContextMenuClose);
+ };
+
+ this.onContextMenuClose = onContextMenuClose;
+ var closeTimeout;
+ function onContextMenuClose() {
+ clearTimeout(closeTimeout);
+ closeTimeout = setTimeout(function() {
+ if (tempStyle) {
+ text.style.cssText = tempStyle;
+ tempStyle = "";
+ }
+ host.renderer.$isMousePressed = false;
+ if (host.renderer.$keepTextAreaAtCursor)
+ host.renderer.$moveTextAreaToCursor();
+ }, 0);
+ }
+
+ var onContextMenu = function(e) {
+ host.textInput.onContextMenu(e);
+ onContextMenuClose();
+ };
+ event.addListener(text, "mouseup", onContextMenu, host);
+ event.addListener(
+ text,
+ "mousedown",
+ function(e) {
+ e.preventDefault();
+ onContextMenuClose();
+ },
+ host
+ );
+ event.addListener(
+ host.renderer.scroller,
+ "contextmenu",
+ onContextMenu,
+ host
+ );
+ event.addListener(text, "contextmenu", onContextMenu, host);
+
+ if (isIOS) addIosSelectionHandler(parentNode, host, text);
+
+ function addIosSelectionHandler(parentNode, host, text) {
+ var typingResetTimeout = null;
+ var typing = false;
+
+ text.addEventListener(
+ "keydown",
+ function(e) {
+ if (typingResetTimeout) clearTimeout(typingResetTimeout);
+ typing = true;
+ },
+ true
+ );
+
+ text.addEventListener(
+ "keyup",
+ function(e) {
+ typingResetTimeout = setTimeout(function() {
+ typing = false;
+ }, 100);
+ },
+ true
+ );
+ var detectArrowKeys = function(e) {
+ if (document.activeElement !== text) return;
+ if (typing || inComposition || host.$mouseHandler.isMousePressed)
+ return;
+
+ if (copied) {
+ return;
+ }
+ var selectionStart = text.selectionStart;
+ var selectionEnd = text.selectionEnd;
+
+ var key = null;
+ var modifier = 0;
+ if (selectionStart == 0) {
+ key = KEYS.up;
+ } else if (selectionStart == 1) {
+ key = KEYS.home;
+ } else if (
+ selectionEnd > lastSelectionEnd &&
+ lastValue[selectionEnd] == "\n"
+ ) {
+ key = KEYS.end;
+ } else if (
+ selectionStart < lastSelectionStart &&
+ lastValue[selectionStart - 1] == " "
+ ) {
+ key = KEYS.left;
+ modifier = MODS.option;
+ } else if (
+ selectionStart < lastSelectionStart ||
+ (selectionStart == lastSelectionStart &&
+ lastSelectionEnd != lastSelectionStart &&
+ selectionStart == selectionEnd)
+ ) {
+ key = KEYS.left;
+ } else if (
+ selectionEnd > lastSelectionEnd &&
+ lastValue.slice(0, selectionEnd).split("\n").length > 2
+ ) {
+ key = KEYS.down;
+ } else if (
+ selectionEnd > lastSelectionEnd &&
+ lastValue[selectionEnd - 1] == " "
+ ) {
+ key = KEYS.right;
+ modifier = MODS.option;
+ } else if (
+ selectionEnd > lastSelectionEnd ||
+ (selectionEnd == lastSelectionEnd &&
+ lastSelectionEnd != lastSelectionStart &&
+ selectionStart == selectionEnd)
+ ) {
+ key = KEYS.right;
+ }
+
+ if (selectionStart !== selectionEnd) modifier |= MODS.shift;
+
+ if (key) {
+ var result = host.onCommandKey({}, modifier, key);
+ if (!result && host.commands) {
+ key = KEYS.keyCodeToString(key);
+ var command = host.commands.findKeyCommand(modifier, key);
+ if (command) host.execCommand(command);
+ }
+ lastSelectionStart = selectionStart;
+ lastSelectionEnd = selectionEnd;
+ resetSelection("");
+ }
+ };
+ document.addEventListener("selectionchange", detectArrowKeys);
+ host.on("destroy", function() {
+ document.removeEventListener("selectionchange", detectArrowKeys);
+ });
+ }
+ };
+
+ exports.TextInput = TextInput;
+ exports.$setUserAgentForTests = function(_isMobile, _isIOS) {
+ isMobile = _isMobile;
+ isIOS = _isIOS;
+ };
+ }
+);
+
+ace.define(
+ "ace/mouse/default_handlers",
+ ["require", "exports", "module", "ace/lib/useragent"],
+ function(require, exports, module) {
+ "use strict";
+
+ var useragent = require("../lib/useragent");
+
+ var DRAG_OFFSET = 0; // pixels
+ var SCROLL_COOLDOWN_T = 550; // milliseconds
+
+ function DefaultHandlers(mouseHandler) {
+ mouseHandler.$clickSelection = null;
+
+ var editor = mouseHandler.editor;
+ editor.setDefaultHandler(
+ "mousedown",
+ this.onMouseDown.bind(mouseHandler)
+ );
+ editor.setDefaultHandler(
+ "dblclick",
+ this.onDoubleClick.bind(mouseHandler)
+ );
+ editor.setDefaultHandler(
+ "tripleclick",
+ this.onTripleClick.bind(mouseHandler)
+ );
+ editor.setDefaultHandler(
+ "quadclick",
+ this.onQuadClick.bind(mouseHandler)
+ );
+ editor.setDefaultHandler(
+ "mousewheel",
+ this.onMouseWheel.bind(mouseHandler)
+ );
+
+ var exports = [
+ "select",
+ "startSelect",
+ "selectEnd",
+ "selectAllEnd",
+ "selectByWordsEnd",
+ "selectByLinesEnd",
+ "dragWait",
+ "dragWaitEnd",
+ "focusWait"
+ ];
+
+ exports.forEach(function(x) {
+ mouseHandler[x] = this[x];
+ }, this);
+
+ mouseHandler.selectByLines = this.extendSelectionBy.bind(
+ mouseHandler,
+ "getLineRange"
+ );
+ mouseHandler.selectByWords = this.extendSelectionBy.bind(
+ mouseHandler,
+ "getWordRange"
+ );
+ }
+
+ (function() {
+ this.onMouseDown = function(ev) {
+ var inSelection = ev.inSelection();
+ var pos = ev.getDocumentPosition();
+ this.mousedownEvent = ev;
+ var editor = this.editor;
+
+ var button = ev.getButton();
+ if (button !== 0) {
+ var selectionRange = editor.getSelectionRange();
+ var selectionEmpty = selectionRange.isEmpty();
+ if (selectionEmpty || button == 1)
+ editor.selection.moveToPosition(pos);
+ if (button == 2) {
+ editor.textInput.onContextMenu(ev.domEvent);
+ if (!useragent.isMozilla) ev.preventDefault();
+ }
+ return;
+ }
+
+ this.mousedownEvent.time = Date.now();
+ if (inSelection && !editor.isFocused()) {
+ editor.focus();
+ if (
+ this.$focusTimeout &&
+ !this.$clickSelection &&
+ !editor.inMultiSelectMode
+ ) {
+ this.setState("focusWait");
+ this.captureMouse(ev);
+ return;
+ }
+ }
+
+ this.captureMouse(ev);
+ this.startSelect(pos, ev.domEvent._clicks > 1);
+ return ev.preventDefault();
+ };
+
+ this.startSelect = function(pos, waitForClickSelection) {
+ pos =
+ pos || this.editor.renderer.screenToTextCoordinates(this.x, this.y);
+ var editor = this.editor;
+ if (!this.mousedownEvent) return;
+ if (this.mousedownEvent.getShiftKey())
+ editor.selection.selectToPosition(pos);
+ else if (!waitForClickSelection) editor.selection.moveToPosition(pos);
+ if (!waitForClickSelection) this.select();
+ if (editor.renderer.scroller.setCapture) {
+ editor.renderer.scroller.setCapture();
+ }
+ editor.setStyle("ace_selecting");
+ this.setState("select");
+ };
+
+ this.select = function() {
+ var anchor,
+ editor = this.editor;
+ var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y);
+ if (this.$clickSelection) {
+ var cmp = this.$clickSelection.comparePoint(cursor);
+
+ if (cmp == -1) {
+ anchor = this.$clickSelection.end;
+ } else if (cmp == 1) {
+ anchor = this.$clickSelection.start;
+ } else {
+ var orientedRange = calcRangeOrientation(
+ this.$clickSelection,
+ cursor
+ );
+ cursor = orientedRange.cursor;
+ anchor = orientedRange.anchor;
+ }
+ editor.selection.setSelectionAnchor(anchor.row, anchor.column);
+ }
+ editor.selection.selectToPosition(cursor);
+ editor.renderer.scrollCursorIntoView();
+ };
+
+ this.extendSelectionBy = function(unitName) {
+ var anchor,
+ editor = this.editor;
+ var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y);
+ var range = editor.selection[unitName](cursor.row, cursor.column);
+ if (this.$clickSelection) {
+ var cmpStart = this.$clickSelection.comparePoint(range.start);
+ var cmpEnd = this.$clickSelection.comparePoint(range.end);
+
+ if (cmpStart == -1 && cmpEnd <= 0) {
+ anchor = this.$clickSelection.end;
+ if (
+ range.end.row != cursor.row ||
+ range.end.column != cursor.column
+ )
+ cursor = range.start;
+ } else if (cmpEnd == 1 && cmpStart >= 0) {
+ anchor = this.$clickSelection.start;
+ if (
+ range.start.row != cursor.row ||
+ range.start.column != cursor.column
+ )
+ cursor = range.end;
+ } else if (cmpStart == -1 && cmpEnd == 1) {
+ cursor = range.end;
+ anchor = range.start;
+ } else {
+ var orientedRange = calcRangeOrientation(
+ this.$clickSelection,
+ cursor
+ );
+ cursor = orientedRange.cursor;
+ anchor = orientedRange.anchor;
+ }
+ editor.selection.setSelectionAnchor(anchor.row, anchor.column);
+ }
+ editor.selection.selectToPosition(cursor);
+ editor.renderer.scrollCursorIntoView();
+ };
+
+ this.selectEnd = this.selectAllEnd = this.selectByWordsEnd = this.selectByLinesEnd = function() {
+ this.$clickSelection = null;
+ this.editor.unsetStyle("ace_selecting");
+ if (this.editor.renderer.scroller.releaseCapture) {
+ this.editor.renderer.scroller.releaseCapture();
+ }
+ };
+
+ this.focusWait = function() {
+ var distance = calcDistance(
+ this.mousedownEvent.x,
+ this.mousedownEvent.y,
+ this.x,
+ this.y
+ );
+ var time = Date.now();
+
+ if (
+ distance > DRAG_OFFSET ||
+ time - this.mousedownEvent.time > this.$focusTimeout
+ )
+ this.startSelect(this.mousedownEvent.getDocumentPosition());
+ };
+
+ this.onDoubleClick = function(ev) {
+ var pos = ev.getDocumentPosition();
+ var editor = this.editor;
+ var session = editor.session;
+
+ var range = session.getBracketRange(pos);
+ if (range) {
+ if (range.isEmpty()) {
+ range.start.column--;
+ range.end.column++;
+ }
+ this.setState("select");
+ } else {
+ range = editor.selection.getWordRange(pos.row, pos.column);
+ this.setState("selectByWords");
+ }
+ this.$clickSelection = range;
+ this.select();
+ };
+
+ this.onTripleClick = function(ev) {
+ var pos = ev.getDocumentPosition();
+ var editor = this.editor;
+
+ this.setState("selectByLines");
+ var range = editor.getSelectionRange();
+ if (range.isMultiLine() && range.contains(pos.row, pos.column)) {
+ this.$clickSelection = editor.selection.getLineRange(range.start.row);
+ this.$clickSelection.end = editor.selection.getLineRange(
+ range.end.row
+ ).end;
+ } else {
+ this.$clickSelection = editor.selection.getLineRange(pos.row);
+ }
+ this.select();
+ };
+
+ this.onQuadClick = function(ev) {
+ var editor = this.editor;
+
+ editor.selectAll();
+ this.$clickSelection = editor.getSelectionRange();
+ this.setState("selectAll");
+ };
+
+ this.onMouseWheel = function(ev) {
+ if (ev.getAccelKey()) return;
+ if (ev.getShiftKey() && ev.wheelY && !ev.wheelX) {
+ ev.wheelX = ev.wheelY;
+ ev.wheelY = 0;
+ }
+
+ var editor = this.editor;
+
+ if (!this.$lastScroll)
+ this.$lastScroll = { t: 0, vx: 0, vy: 0, allowed: 0 };
+
+ var prevScroll = this.$lastScroll;
+ var t = ev.domEvent.timeStamp;
+ var dt = t - prevScroll.t;
+ var vx = dt ? ev.wheelX / dt : prevScroll.vx;
+ var vy = dt ? ev.wheelY / dt : prevScroll.vy;
+ if (dt < SCROLL_COOLDOWN_T) {
+ vx = (vx + prevScroll.vx) / 2;
+ vy = (vy + prevScroll.vy) / 2;
+ }
+
+ var direction = Math.abs(vx / vy);
+
+ var canScroll = false;
+ if (
+ direction >= 1 &&
+ editor.renderer.isScrollableBy(ev.wheelX * ev.speed, 0)
+ )
+ canScroll = true;
+ if (
+ direction <= 1 &&
+ editor.renderer.isScrollableBy(0, ev.wheelY * ev.speed)
+ )
+ canScroll = true;
+
+ if (canScroll) {
+ prevScroll.allowed = t;
+ } else if (t - prevScroll.allowed < SCROLL_COOLDOWN_T) {
+ var isSlower =
+ Math.abs(vx) <= 1.5 * Math.abs(prevScroll.vx) &&
+ Math.abs(vy) <= 1.5 * Math.abs(prevScroll.vy);
+ if (isSlower) {
+ canScroll = true;
+ prevScroll.allowed = t;
+ } else {
+ prevScroll.allowed = 0;
+ }
+ }
+
+ prevScroll.t = t;
+ prevScroll.vx = vx;
+ prevScroll.vy = vy;
+
+ if (canScroll) {
+ editor.renderer.scrollBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed);
+ return ev.stop();
+ }
+ };
+ }.call(DefaultHandlers.prototype));
+
+ exports.DefaultHandlers = DefaultHandlers;
+
+ function calcDistance(ax, ay, bx, by) {
+ return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2));
+ }
+
+ function calcRangeOrientation(range, cursor) {
+ if (range.start.row == range.end.row)
+ var cmp = 2 * cursor.column - range.start.column - range.end.column;
+ else if (
+ range.start.row == range.end.row - 1 &&
+ !range.start.column &&
+ !range.end.column
+ )
+ var cmp = cursor.column - 4;
+ else var cmp = 2 * cursor.row - range.start.row - range.end.row;
+
+ if (cmp < 0) return { cursor: range.start, anchor: range.end };
+ else return { cursor: range.end, anchor: range.start };
+ }
+ }
+);
+
+ace.define(
+ "ace/tooltip",
+ ["require", "exports", "module", "ace/lib/oop", "ace/lib/dom"],
+ function(require, exports, module) {
+ "use strict";
+
+ var oop = require("./lib/oop");
+ var dom = require("./lib/dom");
+ function Tooltip(parentNode) {
+ this.isOpen = false;
+ this.$element = null;
+ this.$parentNode = parentNode;
+ }
+
+ (function() {
+ this.$init = function() {
+ this.$element = dom.createElement("div");
+ this.$element.className = "ace_tooltip";
+ this.$element.style.display = "none";
+ this.$parentNode.appendChild(this.$element);
+ return this.$element;
+ };
+ this.getElement = function() {
+ return this.$element || this.$init();
+ };
+ this.setText = function(text) {
+ this.getElement().textContent = text;
+ };
+ this.setHtml = function(html) {
+ this.getElement().innerHTML = html;
+ };
+ this.setPosition = function(x, y) {
+ this.getElement().style.left = x + "px";
+ this.getElement().style.top = y + "px";
+ };
+ this.setClassName = function(className) {
+ dom.addCssClass(this.getElement(), className);
+ };
+ this.show = function(text, x, y) {
+ if (text != null) this.setText(text);
+ if (x != null && y != null) this.setPosition(x, y);
+ if (!this.isOpen) {
+ this.getElement().style.display = "block";
+ this.isOpen = true;
+ }
+ };
+
+ this.hide = function() {
+ if (this.isOpen) {
+ this.getElement().style.display = "none";
+ this.isOpen = false;
+ }
+ };
+ this.getHeight = function() {
+ return this.getElement().offsetHeight;
+ };
+ this.getWidth = function() {
+ return this.getElement().offsetWidth;
+ };
+
+ this.destroy = function() {
+ this.isOpen = false;
+ if (this.$element && this.$element.parentNode) {
+ this.$element.parentNode.removeChild(this.$element);
+ }
+ };
+ }.call(Tooltip.prototype));
+
+ exports.Tooltip = Tooltip;
+ }
+);
+
+ace.define(
+ "ace/mouse/default_gutter_handler",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/lib/dom",
+ "ace/lib/oop",
+ "ace/lib/event",
+ "ace/tooltip"
+ ],
+ function(require, exports, module) {
+ "use strict";
+ var dom = require("../lib/dom");
+ var oop = require("../lib/oop");
+ var event = require("../lib/event");
+ var Tooltip = require("../tooltip").Tooltip;
+
+ function GutterHandler(mouseHandler) {
+ var editor = mouseHandler.editor;
+ var gutter = editor.renderer.$gutterLayer;
+ var tooltip = new GutterTooltip(editor.container);
+
+ mouseHandler.editor.setDefaultHandler("guttermousedown", function(e) {
+ if (!editor.isFocused() || e.getButton() != 0) return;
+ var gutterRegion = gutter.getRegion(e);
+
+ if (gutterRegion == "foldWidgets") return;
+
+ var row = e.getDocumentPosition().row;
+ var selection = editor.session.selection;
+
+ if (e.getShiftKey()) selection.selectTo(row, 0);
+ else {
+ if (e.domEvent.detail == 2) {
+ editor.selectAll();
+ return e.preventDefault();
+ }
+ mouseHandler.$clickSelection = editor.selection.getLineRange(row);
+ }
+ mouseHandler.setState("selectByLines");
+ mouseHandler.captureMouse(e);
+ return e.preventDefault();
+ });
+
+ var tooltipTimeout, mouseEvent, tooltipAnnotation;
+
+ function showTooltip() {
+ var row = mouseEvent.getDocumentPosition().row;
+ var annotation = gutter.$annotations[row];
+ if (!annotation) return hideTooltip();
+
+ var maxRow = editor.session.getLength();
+ if (row == maxRow) {
+ var screenRow = editor.renderer.pixelToScreenCoordinates(
+ 0,
+ mouseEvent.y
+ ).row;
+ var pos = mouseEvent.$pos;
+ if (
+ screenRow > editor.session.documentToScreenRow(pos.row, pos.column)
+ )
+ return hideTooltip();
+ }
+
+ if (tooltipAnnotation == annotation) return;
+ tooltipAnnotation = annotation.text.join("
");
+
+ tooltip.setHtml(tooltipAnnotation);
+ tooltip.show();
+ editor._signal("showGutterTooltip", tooltip);
+ editor.on("mousewheel", hideTooltip);
+
+ if (mouseHandler.$tooltipFollowsMouse) {
+ moveTooltip(mouseEvent);
+ } else {
+ var gutterElement = mouseEvent.domEvent.target;
+ var rect = gutterElement.getBoundingClientRect();
+ var style = tooltip.getElement().style;
+ style.left = rect.right + "px";
+ style.top = rect.bottom + "px";
+ }
+ }
+
+ function hideTooltip() {
+ if (tooltipTimeout) tooltipTimeout = clearTimeout(tooltipTimeout);
+ if (tooltipAnnotation) {
+ tooltip.hide();
+ tooltipAnnotation = null;
+ editor._signal("hideGutterTooltip", tooltip);
+ editor.off("mousewheel", hideTooltip);
+ }
+ }
+
+ function moveTooltip(e) {
+ tooltip.setPosition(e.x, e.y);
+ }
+
+ mouseHandler.editor.setDefaultHandler("guttermousemove", function(e) {
+ var target = e.domEvent.target || e.domEvent.srcElement;
+ if (dom.hasCssClass(target, "ace_fold-widget")) return hideTooltip();
+
+ if (tooltipAnnotation && mouseHandler.$tooltipFollowsMouse)
+ moveTooltip(e);
+
+ mouseEvent = e;
+ if (tooltipTimeout) return;
+ tooltipTimeout = setTimeout(function() {
+ tooltipTimeout = null;
+ if (mouseEvent && !mouseHandler.isMousePressed) showTooltip();
+ else hideTooltip();
+ }, 50);
+ });
+
+ event.addListener(
+ editor.renderer.$gutter,
+ "mouseout",
+ function(e) {
+ mouseEvent = null;
+ if (!tooltipAnnotation || tooltipTimeout) return;
+
+ tooltipTimeout = setTimeout(function() {
+ tooltipTimeout = null;
+ hideTooltip();
+ }, 50);
+ },
+ editor
+ );
+
+ editor.on("changeSession", hideTooltip);
+ }
+
+ function GutterTooltip(parentNode) {
+ Tooltip.call(this, parentNode);
+ }
+
+ oop.inherits(GutterTooltip, Tooltip);
+
+ (function() {
+ this.setPosition = function(x, y) {
+ var windowWidth =
+ window.innerWidth || document.documentElement.clientWidth;
+ var windowHeight =
+ window.innerHeight || document.documentElement.clientHeight;
+ var width = this.getWidth();
+ var height = this.getHeight();
+ x += 15;
+ y += 15;
+ if (x + width > windowWidth) {
+ x -= x + width - windowWidth;
+ }
+ if (y + height > windowHeight) {
+ y -= 20 + height;
+ }
+ Tooltip.prototype.setPosition.call(this, x, y);
+ };
+ }.call(GutterTooltip.prototype));
+
+ exports.GutterHandler = GutterHandler;
+ }
+);
+
+ace.define(
+ "ace/mouse/mouse_event",
+ ["require", "exports", "module", "ace/lib/event", "ace/lib/useragent"],
+ function(require, exports, module) {
+ "use strict";
+
+ var event = require("../lib/event");
+ var useragent = require("../lib/useragent");
+ var MouseEvent = (exports.MouseEvent = function(domEvent, editor) {
+ this.domEvent = domEvent;
+ this.editor = editor;
+
+ this.x = this.clientX = domEvent.clientX;
+ this.y = this.clientY = domEvent.clientY;
+
+ this.$pos = null;
+ this.$inSelection = null;
+
+ this.propagationStopped = false;
+ this.defaultPrevented = false;
+ });
+
+ (function() {
+ this.stopPropagation = function() {
+ event.stopPropagation(this.domEvent);
+ this.propagationStopped = true;
+ };
+
+ this.preventDefault = function() {
+ event.preventDefault(this.domEvent);
+ this.defaultPrevented = true;
+ };
+
+ this.stop = function() {
+ this.stopPropagation();
+ this.preventDefault();
+ };
+ this.getDocumentPosition = function() {
+ if (this.$pos) return this.$pos;
+
+ this.$pos = this.editor.renderer.screenToTextCoordinates(
+ this.clientX,
+ this.clientY
+ );
+ return this.$pos;
+ };
+ this.inSelection = function() {
+ if (this.$inSelection !== null) return this.$inSelection;
+
+ var editor = this.editor;
+
+ var selectionRange = editor.getSelectionRange();
+ if (selectionRange.isEmpty()) this.$inSelection = false;
+ else {
+ var pos = this.getDocumentPosition();
+ this.$inSelection = selectionRange.contains(pos.row, pos.column);
+ }
+
+ return this.$inSelection;
+ };
+ this.getButton = function() {
+ return event.getButton(this.domEvent);
+ };
+ this.getShiftKey = function() {
+ return this.domEvent.shiftKey;
+ };
+
+ this.getAccelKey = useragent.isMac
+ ? function() {
+ return this.domEvent.metaKey;
+ }
+ : function() {
+ return this.domEvent.ctrlKey;
+ };
+ }.call(MouseEvent.prototype));
+ }
+);
+
+ace.define(
+ "ace/mouse/dragdrop_handler",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/lib/dom",
+ "ace/lib/event",
+ "ace/lib/useragent"
+ ],
+ function(require, exports, module) {
+ "use strict";
+
+ var dom = require("../lib/dom");
+ var event = require("../lib/event");
+ var useragent = require("../lib/useragent");
+
+ var AUTOSCROLL_DELAY = 200;
+ var SCROLL_CURSOR_DELAY = 200;
+ var SCROLL_CURSOR_HYSTERESIS = 5;
+
+ function DragdropHandler(mouseHandler) {
+ var editor = mouseHandler.editor;
+
+ var blankImage = dom.createElement("img");
+ blankImage.src =
+ "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
+ if (useragent.isOpera)
+ blankImage.style.cssText =
+ "width:1px;height:1px;position:fixed;top:0;left:0;z-index:2147483647;opacity:0;";
+
+ var exports = [
+ "dragWait",
+ "dragWaitEnd",
+ "startDrag",
+ "dragReadyEnd",
+ "onMouseDrag"
+ ];
+
+ exports.forEach(function(x) {
+ mouseHandler[x] = this[x];
+ }, this);
+ editor.on("mousedown", this.onMouseDown.bind(mouseHandler));
+
+ var mouseTarget = editor.container;
+ var dragSelectionMarker, x, y;
+ var timerId, range;
+ var dragCursor,
+ counter = 0;
+ var dragOperation;
+ var isInternal;
+ var autoScrollStartTime;
+ var cursorMovedTime;
+ var cursorPointOnCaretMoved;
+
+ this.onDragStart = function(e) {
+ if (this.cancelDrag || !mouseTarget.draggable) {
+ var self = this;
+ setTimeout(function() {
+ self.startSelect();
+ self.captureMouse(e);
+ }, 0);
+ return e.preventDefault();
+ }
+ range = editor.getSelectionRange();
+
+ var dataTransfer = e.dataTransfer;
+ dataTransfer.effectAllowed = editor.getReadOnly() ? "copy" : "copyMove";
+ if (useragent.isOpera) {
+ editor.container.appendChild(blankImage);
+ blankImage.scrollTop = 0;
+ }
+ dataTransfer.setDragImage &&
+ dataTransfer.setDragImage(blankImage, 0, 0);
+ if (useragent.isOpera) {
+ editor.container.removeChild(blankImage);
+ }
+ dataTransfer.clearData();
+ dataTransfer.setData("Text", editor.session.getTextRange());
+
+ isInternal = true;
+ this.setState("drag");
+ };
+
+ this.onDragEnd = function(e) {
+ mouseTarget.draggable = false;
+ isInternal = false;
+ this.setState(null);
+ if (!editor.getReadOnly()) {
+ var dropEffect = e.dataTransfer.dropEffect;
+ if (!dragOperation && dropEffect == "move")
+ editor.session.remove(editor.getSelectionRange());
+ editor.$resetCursorStyle();
+ }
+ this.editor.unsetStyle("ace_dragging");
+ this.editor.renderer.setCursorStyle("");
+ };
+
+ this.onDragEnter = function(e) {
+ if (editor.getReadOnly() || !canAccept(e.dataTransfer)) return;
+ x = e.clientX;
+ y = e.clientY;
+ if (!dragSelectionMarker) addDragMarker();
+ counter++;
+ e.dataTransfer.dropEffect = dragOperation = getDropEffect(e);
+ return event.preventDefault(e);
+ };
+
+ this.onDragOver = function(e) {
+ if (editor.getReadOnly() || !canAccept(e.dataTransfer)) return;
+ x = e.clientX;
+ y = e.clientY;
+ if (!dragSelectionMarker) {
+ addDragMarker();
+ counter++;
+ }
+ if (onMouseMoveTimer !== null) onMouseMoveTimer = null;
+
+ e.dataTransfer.dropEffect = dragOperation = getDropEffect(e);
+ return event.preventDefault(e);
+ };
+
+ this.onDragLeave = function(e) {
+ counter--;
+ if (counter <= 0 && dragSelectionMarker) {
+ clearDragMarker();
+ dragOperation = null;
+ return event.preventDefault(e);
+ }
+ };
+
+ this.onDrop = function(e) {
+ if (!dragCursor) return;
+ var dataTransfer = e.dataTransfer;
+ if (isInternal) {
+ switch (dragOperation) {
+ case "move":
+ if (range.contains(dragCursor.row, dragCursor.column)) {
+ range = {
+ start: dragCursor,
+ end: dragCursor
+ };
+ } else {
+ range = editor.moveText(range, dragCursor);
+ }
+ break;
+ case "copy":
+ range = editor.moveText(range, dragCursor, true);
+ break;
+ }
+ } else {
+ var dropData = dataTransfer.getData("Text");
+ range = {
+ start: dragCursor,
+ end: editor.session.insert(dragCursor, dropData)
+ };
+ editor.focus();
+ dragOperation = null;
+ }
+ clearDragMarker();
+ return event.preventDefault(e);
+ };
+
+ event.addListener(
+ mouseTarget,
+ "dragstart",
+ this.onDragStart.bind(mouseHandler),
+ editor
+ );
+ event.addListener(
+ mouseTarget,
+ "dragend",
+ this.onDragEnd.bind(mouseHandler),
+ editor
+ );
+ event.addListener(
+ mouseTarget,
+ "dragenter",
+ this.onDragEnter.bind(mouseHandler),
+ editor
+ );
+ event.addListener(
+ mouseTarget,
+ "dragover",
+ this.onDragOver.bind(mouseHandler),
+ editor
+ );
+ event.addListener(
+ mouseTarget,
+ "dragleave",
+ this.onDragLeave.bind(mouseHandler),
+ editor
+ );
+ event.addListener(
+ mouseTarget,
+ "drop",
+ this.onDrop.bind(mouseHandler),
+ editor
+ );
+
+ function scrollCursorIntoView(cursor, prevCursor) {
+ var now = Date.now();
+ var vMovement = !prevCursor || cursor.row != prevCursor.row;
+ var hMovement = !prevCursor || cursor.column != prevCursor.column;
+ if (!cursorMovedTime || vMovement || hMovement) {
+ editor.moveCursorToPosition(cursor);
+ cursorMovedTime = now;
+ cursorPointOnCaretMoved = { x: x, y: y };
+ } else {
+ var distance = calcDistance(
+ cursorPointOnCaretMoved.x,
+ cursorPointOnCaretMoved.y,
+ x,
+ y
+ );
+ if (distance > SCROLL_CURSOR_HYSTERESIS) {
+ cursorMovedTime = null;
+ } else if (now - cursorMovedTime >= SCROLL_CURSOR_DELAY) {
+ editor.renderer.scrollCursorIntoView();
+ cursorMovedTime = null;
+ }
+ }
+ }
+
+ function autoScroll(cursor, prevCursor) {
+ var now = Date.now();
+ var lineHeight = editor.renderer.layerConfig.lineHeight;
+ var characterWidth = editor.renderer.layerConfig.characterWidth;
+ var editorRect = editor.renderer.scroller.getBoundingClientRect();
+ var offsets = {
+ x: {
+ left: x - editorRect.left,
+ right: editorRect.right - x
+ },
+ y: {
+ top: y - editorRect.top,
+ bottom: editorRect.bottom - y
+ }
+ };
+ var nearestXOffset = Math.min(offsets.x.left, offsets.x.right);
+ var nearestYOffset = Math.min(offsets.y.top, offsets.y.bottom);
+ var scrollCursor = { row: cursor.row, column: cursor.column };
+ if (nearestXOffset / characterWidth <= 2) {
+ scrollCursor.column += offsets.x.left < offsets.x.right ? -3 : +2;
+ }
+ if (nearestYOffset / lineHeight <= 1) {
+ scrollCursor.row += offsets.y.top < offsets.y.bottom ? -1 : +1;
+ }
+ var vScroll = cursor.row != scrollCursor.row;
+ var hScroll = cursor.column != scrollCursor.column;
+ var vMovement = !prevCursor || cursor.row != prevCursor.row;
+ if (vScroll || (hScroll && !vMovement)) {
+ if (!autoScrollStartTime) autoScrollStartTime = now;
+ else if (now - autoScrollStartTime >= AUTOSCROLL_DELAY)
+ editor.renderer.scrollCursorIntoView(scrollCursor);
+ } else {
+ autoScrollStartTime = null;
+ }
+ }
+
+ function onDragInterval() {
+ var prevCursor = dragCursor;
+ dragCursor = editor.renderer.screenToTextCoordinates(x, y);
+ scrollCursorIntoView(dragCursor, prevCursor);
+ autoScroll(dragCursor, prevCursor);
+ }
+
+ function addDragMarker() {
+ range = editor.selection.toOrientedRange();
+ dragSelectionMarker = editor.session.addMarker(
+ range,
+ "ace_selection",
+ editor.getSelectionStyle()
+ );
+ editor.clearSelection();
+ if (editor.isFocused()) editor.renderer.$cursorLayer.setBlinking(false);
+ clearInterval(timerId);
+ onDragInterval();
+ timerId = setInterval(onDragInterval, 20);
+ counter = 0;
+ event.addListener(document, "mousemove", onMouseMove);
+ }
+
+ function clearDragMarker() {
+ clearInterval(timerId);
+ editor.session.removeMarker(dragSelectionMarker);
+ dragSelectionMarker = null;
+ editor.selection.fromOrientedRange(range);
+ if (editor.isFocused() && !isInternal) editor.$resetCursorStyle();
+ range = null;
+ dragCursor = null;
+ counter = 0;
+ autoScrollStartTime = null;
+ cursorMovedTime = null;
+ event.removeListener(document, "mousemove", onMouseMove);
+ }
+ var onMouseMoveTimer = null;
+ function onMouseMove() {
+ if (onMouseMoveTimer == null) {
+ onMouseMoveTimer = setTimeout(function() {
+ if (onMouseMoveTimer != null && dragSelectionMarker)
+ clearDragMarker();
+ }, 20);
+ }
+ }
+
+ function canAccept(dataTransfer) {
+ var types = dataTransfer.types;
+ return (
+ !types ||
+ Array.prototype.some.call(types, function(type) {
+ return type == "text/plain" || type == "Text";
+ })
+ );
+ }
+
+ function getDropEffect(e) {
+ var copyAllowed = ["copy", "copymove", "all", "uninitialized"];
+ var moveAllowed = [
+ "move",
+ "copymove",
+ "linkmove",
+ "all",
+ "uninitialized"
+ ];
+
+ var copyModifierState = useragent.isMac ? e.altKey : e.ctrlKey;
+ var effectAllowed = "uninitialized";
+ try {
+ effectAllowed = e.dataTransfer.effectAllowed.toLowerCase();
+ } catch (e) {}
+ var dropEffect = "none";
+
+ if (copyModifierState && copyAllowed.indexOf(effectAllowed) >= 0)
+ dropEffect = "copy";
+ else if (moveAllowed.indexOf(effectAllowed) >= 0) dropEffect = "move";
+ else if (copyAllowed.indexOf(effectAllowed) >= 0) dropEffect = "copy";
+
+ return dropEffect;
+ }
+ }
+
+ (function() {
+ this.dragWait = function() {
+ var interval = Date.now() - this.mousedownEvent.time;
+ if (interval > this.editor.getDragDelay()) this.startDrag();
+ };
+
+ this.dragWaitEnd = function() {
+ var target = this.editor.container;
+ target.draggable = false;
+ this.startSelect(this.mousedownEvent.getDocumentPosition());
+ this.selectEnd();
+ };
+
+ this.dragReadyEnd = function(e) {
+ this.editor.$resetCursorStyle();
+ this.editor.unsetStyle("ace_dragging");
+ this.editor.renderer.setCursorStyle("");
+ this.dragWaitEnd();
+ };
+
+ this.startDrag = function() {
+ this.cancelDrag = false;
+ var editor = this.editor;
+ var target = editor.container;
+ target.draggable = true;
+ editor.renderer.$cursorLayer.setBlinking(false);
+ editor.setStyle("ace_dragging");
+ var cursorStyle = useragent.isWin ? "default" : "move";
+ editor.renderer.setCursorStyle(cursorStyle);
+ this.setState("dragReady");
+ };
+
+ this.onMouseDrag = function(e) {
+ var target = this.editor.container;
+ if (useragent.isIE && this.state == "dragReady") {
+ var distance = calcDistance(
+ this.mousedownEvent.x,
+ this.mousedownEvent.y,
+ this.x,
+ this.y
+ );
+ if (distance > 3) target.dragDrop();
+ }
+ if (this.state === "dragWait") {
+ var distance = calcDistance(
+ this.mousedownEvent.x,
+ this.mousedownEvent.y,
+ this.x,
+ this.y
+ );
+ if (distance > 0) {
+ target.draggable = false;
+ this.startSelect(this.mousedownEvent.getDocumentPosition());
+ }
+ }
+ };
+
+ this.onMouseDown = function(e) {
+ if (!this.$dragEnabled) return;
+ this.mousedownEvent = e;
+ var editor = this.editor;
+
+ var inSelection = e.inSelection();
+ var button = e.getButton();
+ var clickCount = e.domEvent.detail || 1;
+ if (clickCount === 1 && button === 0 && inSelection) {
+ if (
+ e.editor.inMultiSelectMode &&
+ (e.getAccelKey() || e.getShiftKey())
+ )
+ return;
+ this.mousedownEvent.time = Date.now();
+ var eventTarget = e.domEvent.target || e.domEvent.srcElement;
+ if ("unselectable" in eventTarget) eventTarget.unselectable = "on";
+ if (editor.getDragDelay()) {
+ if (useragent.isWebKit) {
+ this.cancelDrag = true;
+ var mouseTarget = editor.container;
+ mouseTarget.draggable = true;
+ }
+ this.setState("dragWait");
+ } else {
+ this.startDrag();
+ }
+ this.captureMouse(e, this.onMouseDrag.bind(this));
+ e.defaultPrevented = true;
+ }
+ };
+ }.call(DragdropHandler.prototype));
+
+ function calcDistance(ax, ay, bx, by) {
+ return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2));
+ }
+
+ exports.DragdropHandler = DragdropHandler;
+ }
+);
+
+ace.define(
+ "ace/mouse/touch_handler",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/mouse/mouse_event",
+ "ace/lib/event",
+ "ace/lib/dom"
+ ],
+ function(require, exports, module) {
+ "use strict";
+
+ var MouseEvent = require("./mouse_event").MouseEvent;
+ var event = require("../lib/event");
+ var dom = require("../lib/dom");
+
+ exports.addTouchListeners = function(el, editor) {
+ var mode = "scroll";
+ var startX;
+ var startY;
+ var touchStartT;
+ var lastT;
+ var longTouchTimer;
+ var animationTimer;
+ var animationSteps = 0;
+ var pos;
+ var clickCount = 0;
+ var vX = 0;
+ var vY = 0;
+ var pressed;
+ var contextMenu;
+
+ function createContextMenu() {
+ var clipboard = window.navigator && window.navigator.clipboard;
+ var isOpen = false;
+ var updateMenu = function() {
+ var selected = editor.getCopyText();
+ var hasUndo = editor.session.getUndoManager().hasUndo();
+ contextMenu.replaceChild(
+ dom.buildDom(
+ isOpen
+ ? [
+ "span",
+ !selected && [
+ "span",
+ { class: "ace_mobile-button", action: "selectall" },
+ "Select All"
+ ],
+ selected && [
+ "span",
+ { class: "ace_mobile-button", action: "copy" },
+ "Copy"
+ ],
+ selected && [
+ "span",
+ { class: "ace_mobile-button", action: "cut" },
+ "Cut"
+ ],
+ clipboard && [
+ "span",
+ { class: "ace_mobile-button", action: "paste" },
+ "Paste"
+ ],
+ hasUndo && [
+ "span",
+ { class: "ace_mobile-button", action: "undo" },
+ "Undo"
+ ],
+ [
+ "span",
+ { class: "ace_mobile-button", action: "find" },
+ "Find"
+ ],
+ [
+ "span",
+ {
+ class: "ace_mobile-button",
+ action: "openCommandPallete"
+ },
+ "Pallete"
+ ]
+ ]
+ : ["span"]
+ ),
+ contextMenu.firstChild
+ );
+ };
+ var handleClick = function(e) {
+ var action = e.target.getAttribute("action");
+
+ if (action == "more" || !isOpen) {
+ isOpen = !isOpen;
+ return updateMenu();
+ }
+ if (action == "paste") {
+ clipboard.readText().then(function(text) {
+ editor.execCommand(action, text);
+ });
+ } else if (action) {
+ if (action == "cut" || action == "copy") {
+ if (clipboard) clipboard.writeText(editor.getCopyText());
+ else document.execCommand("copy");
+ }
+ editor.execCommand(action);
+ }
+ contextMenu.firstChild.style.display = "none";
+ isOpen = false;
+ if (action != "openCommandPallete") editor.focus();
+ };
+ contextMenu = dom.buildDom(
+ [
+ "div",
+ {
+ class: "ace_mobile-menu",
+ ontouchstart: function(e) {
+ mode = "menu";
+ e.stopPropagation();
+ e.preventDefault();
+ editor.textInput.focus();
+ },
+ ontouchend: function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+ handleClick(e);
+ },
+ onclick: handleClick
+ },
+ ["span"],
+ ["span", { class: "ace_mobile-button", action: "more" }, "..."]
+ ],
+ editor.container
+ );
+ }
+ function showContextMenu() {
+ if (!contextMenu) createContextMenu();
+ var cursor = editor.selection.cursor;
+ var pagePos = editor.renderer.textToScreenCoordinates(
+ cursor.row,
+ cursor.column
+ );
+ var rect = editor.container.getBoundingClientRect();
+ contextMenu.style.top = pagePos.pageY - rect.top - 3 + "px";
+ contextMenu.style.right = "10px";
+ contextMenu.style.display = "";
+ contextMenu.firstChild.style.display = "none";
+ editor.on("input", hideContextMenu);
+ }
+ function hideContextMenu(e) {
+ if (contextMenu) contextMenu.style.display = "none";
+ editor.off("input", hideContextMenu);
+ }
+
+ function handleLongTap() {
+ longTouchTimer = null;
+ clearTimeout(longTouchTimer);
+ var range = editor.selection.getRange();
+ var inSelection = range.contains(pos.row, pos.column);
+ if (range.isEmpty() || !inSelection) {
+ editor.selection.moveToPosition(pos);
+ editor.selection.selectWord();
+ }
+ mode = "wait";
+ showContextMenu();
+ }
+ function switchToSelectionMode() {
+ longTouchTimer = null;
+ clearTimeout(longTouchTimer);
+ editor.selection.moveToPosition(pos);
+ var range =
+ clickCount >= 2
+ ? editor.selection.getLineRange(pos.row)
+ : editor.session.getBracketRange(pos);
+ if (range && !range.isEmpty()) {
+ editor.selection.setRange(range);
+ } else {
+ editor.selection.selectWord();
+ }
+ mode = "wait";
+ }
+ event.addListener(
+ el,
+ "contextmenu",
+ function(e) {
+ if (!pressed) return;
+ var textarea = editor.textInput.getElement();
+ textarea.focus();
+ },
+ editor
+ );
+ event.addListener(
+ el,
+ "touchstart",
+ function(e) {
+ var touches = e.touches;
+ if (longTouchTimer || touches.length > 1) {
+ clearTimeout(longTouchTimer);
+ longTouchTimer = null;
+ touchStartT = -1;
+ mode = "zoom";
+ return;
+ }
+
+ pressed = editor.$mouseHandler.isMousePressed = true;
+ var h = editor.renderer.layerConfig.lineHeight;
+ var w = editor.renderer.layerConfig.lineHeight;
+ var t = e.timeStamp;
+ lastT = t;
+ var touchObj = touches[0];
+ var x = touchObj.clientX;
+ var y = touchObj.clientY;
+ if (Math.abs(startX - x) + Math.abs(startY - y) > h) touchStartT = -1;
+
+ startX = e.clientX = x;
+ startY = e.clientY = y;
+ vX = vY = 0;
+
+ var ev = new MouseEvent(e, editor);
+ pos = ev.getDocumentPosition();
+
+ if (t - touchStartT < 500 && touches.length == 1 && !animationSteps) {
+ clickCount++;
+ e.preventDefault();
+ e.button = 0;
+ switchToSelectionMode();
+ } else {
+ clickCount = 0;
+ var cursor = editor.selection.cursor;
+ var anchor = editor.selection.isEmpty()
+ ? cursor
+ : editor.selection.anchor;
+
+ var cursorPos = editor.renderer.$cursorLayer.getPixelPosition(
+ cursor,
+ true
+ );
+ var anchorPos = editor.renderer.$cursorLayer.getPixelPosition(
+ anchor,
+ true
+ );
+ var rect = editor.renderer.scroller.getBoundingClientRect();
+ var weightedDistance = function(x, y) {
+ x = x / w;
+ y = y / h - 0.75;
+ return x * x + y * y;
+ };
+
+ if (e.clientX < rect.left) {
+ mode = "zoom";
+ return;
+ }
+
+ var diff1 = weightedDistance(
+ e.clientX - rect.left - cursorPos.left,
+ e.clientY - rect.top - cursorPos.top
+ );
+ var diff2 = weightedDistance(
+ e.clientX - rect.left - anchorPos.left,
+ e.clientY - rect.top - anchorPos.top
+ );
+ if (diff1 < 3.5 && diff2 < 3.5)
+ mode = diff1 > diff2 ? "cursor" : "anchor";
+
+ if (diff2 < 3.5) mode = "anchor";
+ else if (diff1 < 3.5) mode = "cursor";
+ else mode = "scroll";
+ longTouchTimer = setTimeout(handleLongTap, 450);
+ }
+ touchStartT = t;
+ },
+ editor
+ );
+
+ event.addListener(
+ el,
+ "touchend",
+ function(e) {
+ pressed = editor.$mouseHandler.isMousePressed = false;
+ if (animationTimer) clearInterval(animationTimer);
+ if (mode == "zoom") {
+ mode = "";
+ animationSteps = 0;
+ } else if (longTouchTimer) {
+ editor.selection.moveToPosition(pos);
+ animationSteps = 0;
+ showContextMenu();
+ } else if (mode == "scroll") {
+ animate();
+ hideContextMenu();
+ } else {
+ showContextMenu();
+ }
+ clearTimeout(longTouchTimer);
+ longTouchTimer = null;
+ },
+ editor
+ );
+ event.addListener(
+ el,
+ "touchmove",
+ function(e) {
+ if (longTouchTimer) {
+ clearTimeout(longTouchTimer);
+ longTouchTimer = null;
+ }
+ var touches = e.touches;
+ if (touches.length > 1 || mode == "zoom") return;
+
+ var touchObj = touches[0];
+
+ var wheelX = startX - touchObj.clientX;
+ var wheelY = startY - touchObj.clientY;
+
+ if (mode == "wait") {
+ if (wheelX * wheelX + wheelY * wheelY > 4) mode = "cursor";
+ else return e.preventDefault();
+ }
+
+ startX = touchObj.clientX;
+ startY = touchObj.clientY;
+
+ e.clientX = touchObj.clientX;
+ e.clientY = touchObj.clientY;
+
+ var t = e.timeStamp;
+ var dt = t - lastT;
+ lastT = t;
+ if (mode == "scroll") {
+ var mouseEvent = new MouseEvent(e, editor);
+ mouseEvent.speed = 1;
+ mouseEvent.wheelX = wheelX;
+ mouseEvent.wheelY = wheelY;
+ if (10 * Math.abs(wheelX) < Math.abs(wheelY)) wheelX = 0;
+ if (10 * Math.abs(wheelY) < Math.abs(wheelX)) wheelY = 0;
+ if (dt != 0) {
+ vX = wheelX / dt;
+ vY = wheelY / dt;
+ }
+ editor._emit("mousewheel", mouseEvent);
+ if (!mouseEvent.propagationStopped) {
+ vX = vY = 0;
+ }
+ } else {
+ var ev = new MouseEvent(e, editor);
+ var pos = ev.getDocumentPosition();
+ if (mode == "cursor") editor.selection.moveCursorToPosition(pos);
+ else if (mode == "anchor")
+ editor.selection.setSelectionAnchor(pos.row, pos.column);
+ editor.renderer.scrollCursorIntoView(pos);
+ e.preventDefault();
+ }
+ },
+ editor
+ );
+
+ function animate() {
+ animationSteps += 60;
+ animationTimer = setInterval(function() {
+ if (animationSteps-- <= 0) {
+ clearInterval(animationTimer);
+ animationTimer = null;
+ }
+ if (Math.abs(vX) < 0.01) vX = 0;
+ if (Math.abs(vY) < 0.01) vY = 0;
+ if (animationSteps < 20) vX = 0.9 * vX;
+ if (animationSteps < 20) vY = 0.9 * vY;
+ var oldScrollTop = editor.session.getScrollTop();
+ editor.renderer.scrollBy(10 * vX, 10 * vY);
+ if (oldScrollTop == editor.session.getScrollTop()) animationSteps = 0;
+ }, 10);
+ }
+ };
+ }
+);
+
+ace.define(
+ "ace/lib/net",
+ ["require", "exports", "module", "ace/lib/dom"],
+ function(require, exports, module) {
+ "use strict";
+ var dom = require("./dom");
+
+ exports.get = function(url, callback) {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", url, true);
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === 4) {
+ callback(xhr.responseText);
+ }
+ };
+ xhr.send(null);
+ };
+
+ exports.loadScript = function(path, callback) {
+ var head = dom.getDocumentHead();
+ var s = document.createElement("script");
+
+ s.src = path;
+ head.appendChild(s);
+
+ s.onload = s.onreadystatechange = function(_, isAbort) {
+ if (
+ isAbort ||
+ !s.readyState ||
+ s.readyState == "loaded" ||
+ s.readyState == "complete"
+ ) {
+ s = s.onload = s.onreadystatechange = null;
+ if (!isAbort) callback();
+ }
+ };
+ };
+ exports.qualifyURL = function(url) {
+ var a = document.createElement("a");
+ a.href = url;
+ return a.href;
+ };
+ }
+);
+
+ace.define("ace/lib/event_emitter", ["require", "exports", "module"], function(
+ require,
+ exports,
+ module
+) {
+ "use strict";
+
+ var EventEmitter = {};
+ var stopPropagation = function() {
+ this.propagationStopped = true;
+ };
+ var preventDefault = function() {
+ this.defaultPrevented = true;
+ };
+
+ EventEmitter._emit = EventEmitter._dispatchEvent = function(eventName, e) {
+ this._eventRegistry || (this._eventRegistry = {});
+ this._defaultHandlers || (this._defaultHandlers = {});
+
+ var listeners = this._eventRegistry[eventName] || [];
+ var defaultHandler = this._defaultHandlers[eventName];
+ if (!listeners.length && !defaultHandler) return;
+
+ if (typeof e != "object" || !e) e = {};
+
+ if (!e.type) e.type = eventName;
+ if (!e.stopPropagation) e.stopPropagation = stopPropagation;
+ if (!e.preventDefault) e.preventDefault = preventDefault;
+
+ listeners = listeners.slice();
+ for (var i = 0; i < listeners.length; i++) {
+ listeners[i](e, this);
+ if (e.propagationStopped) break;
+ }
+
+ if (defaultHandler && !e.defaultPrevented) return defaultHandler(e, this);
+ };
+
+ EventEmitter._signal = function(eventName, e) {
+ var listeners = (this._eventRegistry || {})[eventName];
+ if (!listeners) return;
+ listeners = listeners.slice();
+ for (var i = 0; i < listeners.length; i++) listeners[i](e, this);
+ };
+
+ EventEmitter.once = function(eventName, callback) {
+ var _self = this;
+ this.on(eventName, function newCallback() {
+ _self.off(eventName, newCallback);
+ callback.apply(null, arguments);
+ });
+ if (!callback) {
+ return new Promise(function(resolve) {
+ callback = resolve;
+ });
+ }
+ };
+
+ EventEmitter.setDefaultHandler = function(eventName, callback) {
+ var handlers = this._defaultHandlers;
+ if (!handlers) handlers = this._defaultHandlers = { _disabled_: {} };
+
+ if (handlers[eventName]) {
+ var old = handlers[eventName];
+ var disabled = handlers._disabled_[eventName];
+ if (!disabled) handlers._disabled_[eventName] = disabled = [];
+ disabled.push(old);
+ var i = disabled.indexOf(callback);
+ if (i != -1) disabled.splice(i, 1);
+ }
+ handlers[eventName] = callback;
+ };
+ EventEmitter.removeDefaultHandler = function(eventName, callback) {
+ var handlers = this._defaultHandlers;
+ if (!handlers) return;
+ var disabled = handlers._disabled_[eventName];
+
+ if (handlers[eventName] == callback) {
+ if (disabled) this.setDefaultHandler(eventName, disabled.pop());
+ } else if (disabled) {
+ var i = disabled.indexOf(callback);
+ if (i != -1) disabled.splice(i, 1);
+ }
+ };
+
+ EventEmitter.on = EventEmitter.addEventListener = function(
+ eventName,
+ callback,
+ capturing
+ ) {
+ this._eventRegistry = this._eventRegistry || {};
+
+ var listeners = this._eventRegistry[eventName];
+ if (!listeners) listeners = this._eventRegistry[eventName] = [];
+
+ if (listeners.indexOf(callback) == -1)
+ listeners[capturing ? "unshift" : "push"](callback);
+ return callback;
+ };
+
+ EventEmitter.off = EventEmitter.removeListener = EventEmitter.removeEventListener = function(
+ eventName,
+ callback
+ ) {
+ this._eventRegistry = this._eventRegistry || {};
+
+ var listeners = this._eventRegistry[eventName];
+ if (!listeners) return;
+
+ var index = listeners.indexOf(callback);
+ if (index !== -1) listeners.splice(index, 1);
+ };
+
+ EventEmitter.removeAllListeners = function(eventName) {
+ if (!eventName) this._eventRegistry = this._defaultHandlers = undefined;
+ if (this._eventRegistry) this._eventRegistry[eventName] = undefined;
+ if (this._defaultHandlers) this._defaultHandlers[eventName] = undefined;
+ };
+
+ exports.EventEmitter = EventEmitter;
+});
+
+ace.define(
+ "ace/lib/app_config",
+ ["require", "exports", "module", "ace/lib/oop", "ace/lib/event_emitter"],
+ function(require, exports, module) {
+ "no use strict";
+
+ var oop = require("./oop");
+ var EventEmitter = require("./event_emitter").EventEmitter;
+
+ var optionsProvider = {
+ setOptions: function(optList) {
+ Object.keys(optList).forEach(function(key) {
+ this.setOption(key, optList[key]);
+ }, this);
+ },
+ getOptions: function(optionNames) {
+ var result = {};
+ if (!optionNames) {
+ var options = this.$options;
+ optionNames = Object.keys(options).filter(function(key) {
+ return !options[key].hidden;
+ });
+ } else if (!Array.isArray(optionNames)) {
+ result = optionNames;
+ optionNames = Object.keys(result);
+ }
+ optionNames.forEach(function(key) {
+ result[key] = this.getOption(key);
+ }, this);
+ return result;
+ },
+ setOption: function(name, value) {
+ if (this["$" + name] === value) return;
+ var opt = this.$options[name];
+ if (!opt) {
+ return warn('misspelled option "' + name + '"');
+ }
+ if (opt.forwardTo)
+ return (
+ this[opt.forwardTo] && this[opt.forwardTo].setOption(name, value)
+ );
+
+ if (!opt.handlesSet) this["$" + name] = value;
+ if (opt && opt.set) opt.set.call(this, value);
+ },
+ getOption: function(name) {
+ var opt = this.$options[name];
+ if (!opt) {
+ return warn('misspelled option "' + name + '"');
+ }
+ if (opt.forwardTo)
+ return this[opt.forwardTo] && this[opt.forwardTo].getOption(name);
+ return opt && opt.get ? opt.get.call(this) : this["$" + name];
+ }
+ };
+
+ function warn(message) {
+ if (typeof console != "undefined" && console.warn)
+ console.warn.apply(console, arguments);
+ }
+
+ function reportError(msg, data) {
+ var e = new Error(msg);
+ e.data = data;
+ if (typeof console == "object" && console.error) console.error(e);
+ setTimeout(function() {
+ throw e;
+ });
+ }
+
+ var AppConfig = function() {
+ this.$defaultOptions = {};
+ };
+
+ (function() {
+ oop.implement(this, EventEmitter);
+ this.defineOptions = function(obj, path, options) {
+ if (!obj.$options) this.$defaultOptions[path] = obj.$options = {};
+
+ Object.keys(options).forEach(function(key) {
+ var opt = options[key];
+ if (typeof opt == "string") opt = { forwardTo: opt };
+
+ opt.name || (opt.name = key);
+ obj.$options[opt.name] = opt;
+ if ("initialValue" in opt) obj["$" + opt.name] = opt.initialValue;
+ });
+ oop.implement(obj, optionsProvider);
+
+ return this;
+ };
+
+ this.resetOptions = function(obj) {
+ Object.keys(obj.$options).forEach(function(key) {
+ var opt = obj.$options[key];
+ if ("value" in opt) obj.setOption(key, opt.value);
+ });
+ };
+
+ this.setDefaultValue = function(path, name, value) {
+ if (!path) {
+ for (path in this.$defaultOptions)
+ if (this.$defaultOptions[path][name]) break;
+ if (!this.$defaultOptions[path][name]) return false;
+ }
+ var opts =
+ this.$defaultOptions[path] || (this.$defaultOptions[path] = {});
+ if (opts[name]) {
+ if (opts.forwardTo) this.setDefaultValue(opts.forwardTo, name, value);
+ else opts[name].value = value;
+ }
+ };
+
+ this.setDefaultValues = function(path, optionHash) {
+ Object.keys(optionHash).forEach(function(key) {
+ this.setDefaultValue(path, key, optionHash[key]);
+ }, this);
+ };
+
+ this.warn = warn;
+ this.reportError = reportError;
+ }.call(AppConfig.prototype));
+
+ exports.AppConfig = AppConfig;
+ }
+);
+
+ace.define(
+ "ace/config",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/lib/lang",
+ "ace/lib/oop",
+ "ace/lib/net",
+ "ace/lib/app_config"
+ ],
+ function(require, exports, module) {
+ "no use strict";
+
+ var lang = require("./lib/lang");
+ var oop = require("./lib/oop");
+ var net = require("./lib/net");
+ var AppConfig = require("./lib/app_config").AppConfig;
+
+ module.exports = exports = new AppConfig();
+
+ var global = (function() {
+ return this || (typeof window != "undefined" && window);
+ })();
+
+ var options = {
+ packaged: false,
+ workerPath: null,
+ modePath: null,
+ themePath: null,
+ basePath: "",
+ suffix: ".js",
+ $moduleUrls: {},
+ loadWorkerFromBlob: true,
+ sharedPopups: false
+ };
+
+ exports.get = function(key) {
+ if (!options.hasOwnProperty(key))
+ throw new Error("Unknown config key: " + key);
+
+ return options[key];
+ };
+
+ exports.set = function(key, value) {
+ if (options.hasOwnProperty(key)) options[key] = value;
+ else if (this.setDefaultValue("", key, value) == false)
+ throw new Error("Unknown config key: " + key);
+ };
+
+ exports.all = function() {
+ return lang.copyObject(options);
+ };
+
+ exports.$modes = {};
+ exports.moduleUrl = function(name, component) {
+ if (options.$moduleUrls[name]) return options.$moduleUrls[name];
+
+ var parts = name.split("/");
+ component = component || parts[parts.length - 2] || "";
+ var sep = component == "snippets" ? "/" : "-";
+ var base = parts[parts.length - 1];
+ if (component == "worker" && sep == "-") {
+ var re = new RegExp(
+ "^" + component + "[\\-_]|[\\-_]" + component + "$",
+ "g"
+ );
+ base = base.replace(re, "");
+ }
+
+ if ((!base || base == component) && parts.length > 1)
+ base = parts[parts.length - 2];
+ var path = options[component + "Path"];
+ if (path == null) {
+ path = options.basePath;
+ } else if (sep == "/") {
+ component = sep = "";
+ }
+ if (path && path.slice(-1) != "/") path += "/";
+ return path + component + sep + base + this.get("suffix");
+ };
+
+ exports.setModuleUrl = function(name, subst) {
+ return (options.$moduleUrls[name] = subst);
+ };
+
+ exports.$loading = {};
+ exports.loadModule = function(moduleName, onLoad) {
+ var module, moduleType;
+ if (Array.isArray(moduleName)) {
+ moduleType = moduleName[0];
+ moduleName = moduleName[1];
+ }
+
+ try {
+ module = require(moduleName);
+ } catch (e) {}
+ if (module && !exports.$loading[moduleName])
+ return onLoad && onLoad(module);
+
+ if (!exports.$loading[moduleName]) exports.$loading[moduleName] = [];
+
+ exports.$loading[moduleName].push(onLoad);
+
+ if (exports.$loading[moduleName].length > 1) return;
+
+ var afterLoad = function() {
+ require([moduleName], function(module) {
+ exports._emit("load.module", { name: moduleName, module: module });
+ var listeners = exports.$loading[moduleName];
+ exports.$loading[moduleName] = null;
+ listeners.forEach(function(onLoad) {
+ onLoad && onLoad(module);
+ });
+ });
+ };
+
+ if (!exports.get("packaged")) return afterLoad();
+
+ net.loadScript(exports.moduleUrl(moduleName, moduleType), afterLoad);
+ reportErrorIfPathIsNotConfigured();
+ };
+
+ var reportErrorIfPathIsNotConfigured = function() {
+ if (
+ !options.basePath &&
+ !options.workerPath &&
+ !options.modePath &&
+ !options.themePath &&
+ !Object.keys(options.$moduleUrls).length
+ ) {
+ console.error(
+ "Unable to infer path to ace from script src,",
+ "use ace.config.set('basePath', 'path') to enable dynamic loading of modes and themes",
+ "or with webpack use ace/webpack-resolver"
+ );
+ reportErrorIfPathIsNotConfigured = function() {};
+ }
+ };
+ init(true);
+ function init(packaged) {
+ if (!global || !global.document) return;
+
+ options.packaged =
+ packaged ||
+ require.packaged ||
+ module.packaged ||
+ (global.define && define.packaged);
+
+ var scriptOptions = {};
+ var scriptUrl = "";
+ var currentScript = document.currentScript || document._currentScript; // native or polyfill
+ var currentDocument =
+ (currentScript && currentScript.ownerDocument) || document;
+
+ var scripts = currentDocument.getElementsByTagName("script");
+ for (var i = 0; i < scripts.length; i++) {
+ var script = scripts[i];
+
+ var src = script.src || script.getAttribute("src");
+ if (!src) continue;
+
+ var attributes = script.attributes;
+ for (var j = 0, l = attributes.length; j < l; j++) {
+ var attr = attributes[j];
+ if (attr.name.indexOf("data-ace-") === 0) {
+ scriptOptions[deHyphenate(attr.name.replace(/^data-ace-/, ""))] =
+ attr.value;
+ }
+ }
+
+ var m = src.match(/^(.*)\/ace(\-\w+)?\.js(\?|$)/);
+ if (m) scriptUrl = m[1];
+ }
+
+ if (scriptUrl) {
+ scriptOptions.base = scriptOptions.base || scriptUrl;
+ scriptOptions.packaged = true;
+ }
+
+ scriptOptions.basePath = scriptOptions.base;
+ scriptOptions.workerPath = scriptOptions.workerPath || scriptOptions.base;
+ scriptOptions.modePath = scriptOptions.modePath || scriptOptions.base;
+ scriptOptions.themePath = scriptOptions.themePath || scriptOptions.base;
+ delete scriptOptions.base;
+
+ for (var key in scriptOptions)
+ if (typeof scriptOptions[key] !== "undefined")
+ exports.set(key, scriptOptions[key]);
+ }
+
+ exports.init = init;
+
+ function deHyphenate(str) {
+ return str.replace(/-(.)/g, function(m, m1) {
+ return m1.toUpperCase();
+ });
+ }
+
+ exports.version = "1.4.10";
+ }
+);
+
+ace.define(
+ "ace/mouse/mouse_handler",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/lib/event",
+ "ace/lib/useragent",
+ "ace/mouse/default_handlers",
+ "ace/mouse/default_gutter_handler",
+ "ace/mouse/mouse_event",
+ "ace/mouse/dragdrop_handler",
+ "ace/mouse/touch_handler",
+ "ace/config"
+ ],
+ function(require, exports, module) {
+ "use strict";
+
+ var event = require("../lib/event");
+ var useragent = require("../lib/useragent");
+ var DefaultHandlers = require("./default_handlers").DefaultHandlers;
+ var DefaultGutterHandler = require("./default_gutter_handler")
+ .GutterHandler;
+ var MouseEvent = require("./mouse_event").MouseEvent;
+ var DragdropHandler = require("./dragdrop_handler").DragdropHandler;
+ var addTouchListeners = require("./touch_handler").addTouchListeners;
+ var config = require("../config");
+
+ var MouseHandler = function(editor) {
+ var _self = this;
+ this.editor = editor;
+
+ new DefaultHandlers(this);
+ new DefaultGutterHandler(this);
+ new DragdropHandler(this);
+
+ var focusEditor = function(e) {
+ var windowBlurred =
+ !document.hasFocus ||
+ !document.hasFocus() ||
+ (!editor.isFocused() &&
+ document.activeElement ==
+ (editor.textInput && editor.textInput.getElement()));
+ if (windowBlurred) window.focus();
+ editor.focus();
+ };
+
+ var mouseTarget = editor.renderer.getMouseEventTarget();
+ event.addListener(
+ mouseTarget,
+ "click",
+ this.onMouseEvent.bind(this, "click"),
+ editor
+ );
+ event.addListener(
+ mouseTarget,
+ "mousemove",
+ this.onMouseMove.bind(this, "mousemove"),
+ editor
+ );
+ event.addMultiMouseDownListener(
+ [
+ mouseTarget,
+ editor.renderer.scrollBarV && editor.renderer.scrollBarV.inner,
+ editor.renderer.scrollBarH && editor.renderer.scrollBarH.inner,
+ editor.textInput && editor.textInput.getElement()
+ ].filter(Boolean),
+ [400, 300, 250],
+ this,
+ "onMouseEvent",
+ editor
+ );
+ event.addMouseWheelListener(
+ editor.container,
+ this.onMouseWheel.bind(this, "mousewheel"),
+ editor
+ );
+ addTouchListeners(editor.container, editor);
+
+ var gutterEl = editor.renderer.$gutter;
+ event.addListener(
+ gutterEl,
+ "mousedown",
+ this.onMouseEvent.bind(this, "guttermousedown"),
+ editor
+ );
+ event.addListener(
+ gutterEl,
+ "click",
+ this.onMouseEvent.bind(this, "gutterclick"),
+ editor
+ );
+ event.addListener(
+ gutterEl,
+ "dblclick",
+ this.onMouseEvent.bind(this, "gutterdblclick"),
+ editor
+ );
+ event.addListener(
+ gutterEl,
+ "mousemove",
+ this.onMouseEvent.bind(this, "guttermousemove"),
+ editor
+ );
+
+ event.addListener(mouseTarget, "mousedown", focusEditor, editor);
+ event.addListener(gutterEl, "mousedown", focusEditor, editor);
+ if (useragent.isIE && editor.renderer.scrollBarV) {
+ event.addListener(
+ editor.renderer.scrollBarV.element,
+ "mousedown",
+ focusEditor,
+ editor
+ );
+ event.addListener(
+ editor.renderer.scrollBarH.element,
+ "mousedown",
+ focusEditor,
+ editor
+ );
+ }
+
+ editor.on(
+ "mousemove",
+ function(e) {
+ if (_self.state || _self.$dragDelay || !_self.$dragEnabled) return;
+
+ var character = editor.renderer.screenToTextCoordinates(e.x, e.y);
+ var range = editor.session.selection.getRange();
+ var renderer = editor.renderer;
+
+ if (
+ !range.isEmpty() &&
+ range.insideStart(character.row, character.column)
+ ) {
+ renderer.setCursorStyle("default");
+ } else {
+ renderer.setCursorStyle("");
+ }
+ },
+ editor
+ );
+ };
+
+ (function() {
+ this.onMouseEvent = function(name, e) {
+ this.editor._emit(name, new MouseEvent(e, this.editor));
+ };
+
+ this.onMouseMove = function(name, e) {
+ var listeners =
+ this.editor._eventRegistry && this.editor._eventRegistry.mousemove;
+ if (!listeners || !listeners.length) return;
+
+ this.editor._emit(name, new MouseEvent(e, this.editor));
+ };
+
+ this.onMouseWheel = function(name, e) {
+ var mouseEvent = new MouseEvent(e, this.editor);
+ mouseEvent.speed = this.$scrollSpeed * 2;
+ mouseEvent.wheelX = e.wheelX;
+ mouseEvent.wheelY = e.wheelY;
+
+ this.editor._emit(name, mouseEvent);
+ };
+
+ this.setState = function(state) {
+ this.state = state;
+ };
+
+ this.captureMouse = function(ev, mouseMoveHandler) {
+ this.x = ev.x;
+ this.y = ev.y;
+
+ this.isMousePressed = true;
+ var editor = this.editor;
+ var renderer = this.editor.renderer;
+ renderer.$isMousePressed = true;
+
+ var self = this;
+ var onMouseMove = function(e) {
+ if (!e) return;
+ if (useragent.isWebKit && !e.which && self.releaseMouse)
+ return self.releaseMouse();
+
+ self.x = e.clientX;
+ self.y = e.clientY;
+ mouseMoveHandler && mouseMoveHandler(e);
+ self.mouseEvent = new MouseEvent(e, self.editor);
+ self.$mouseMoved = true;
+ };
+
+ var onCaptureEnd = function(e) {
+ editor.off("beforeEndOperation", onOperationEnd);
+ clearInterval(timerId);
+ onCaptureInterval();
+ self[self.state + "End"] && self[self.state + "End"](e);
+ self.state = "";
+ self.isMousePressed = renderer.$isMousePressed = false;
+ if (renderer.$keepTextAreaAtCursor) renderer.$moveTextAreaToCursor();
+ self.$onCaptureMouseMove = self.releaseMouse = null;
+ e && self.onMouseEvent("mouseup", e);
+ editor.endOperation();
+ };
+
+ var onCaptureInterval = function() {
+ self[self.state] && self[self.state]();
+ self.$mouseMoved = false;
+ };
+
+ if (useragent.isOldIE && ev.domEvent.type == "dblclick") {
+ return setTimeout(function() {
+ onCaptureEnd(ev);
+ });
+ }
+
+ var onOperationEnd = function(e) {
+ if (!self.releaseMouse) return;
+ if (editor.curOp.command.name && editor.curOp.selectionChanged) {
+ self[self.state + "End"] && self[self.state + "End"]();
+ self.state = "";
+ self.releaseMouse();
+ }
+ };
+
+ editor.on("beforeEndOperation", onOperationEnd);
+ editor.startOperation({ command: { name: "mouse" } });
+
+ self.$onCaptureMouseMove = onMouseMove;
+ self.releaseMouse = event.capture(
+ this.editor.container,
+ onMouseMove,
+ onCaptureEnd
+ );
+ var timerId = setInterval(onCaptureInterval, 20);
+ };
+ this.releaseMouse = null;
+ this.cancelContextMenu = function() {
+ var stop = function(e) {
+ if (e && e.domEvent && e.domEvent.type != "contextmenu") return;
+ this.editor.off("nativecontextmenu", stop);
+ if (e && e.domEvent) event.stopEvent(e.domEvent);
+ }.bind(this);
+ setTimeout(stop, 10);
+ this.editor.on("nativecontextmenu", stop);
+ };
+ }.call(MouseHandler.prototype));
+
+ config.defineOptions(MouseHandler.prototype, "mouseHandler", {
+ scrollSpeed: { initialValue: 2 },
+ dragDelay: { initialValue: useragent.isMac ? 150 : 0 },
+ dragEnabled: { initialValue: true },
+ focusTimeout: { initialValue: 0 },
+ tooltipFollowsMouse: { initialValue: true }
+ });
+
+ exports.MouseHandler = MouseHandler;
+ }
+);
+
+ace.define(
+ "ace/mouse/fold_handler",
+ ["require", "exports", "module", "ace/lib/dom"],
+ function(require, exports, module) {
+ "use strict";
+ var dom = require("../lib/dom");
+
+ function FoldHandler(editor) {
+ editor.on("click", function(e) {
+ var position = e.getDocumentPosition();
+ var session = editor.session;
+ var fold = session.getFoldAt(position.row, position.column, 1);
+ if (fold) {
+ if (e.getAccelKey()) session.removeFold(fold);
+ else session.expandFold(fold);
+
+ e.stop();
+ }
+
+ var target = e.domEvent && e.domEvent.target;
+ if (target && dom.hasCssClass(target, "ace_inline_button")) {
+ if (dom.hasCssClass(target, "ace_toggle_wrap")) {
+ session.setOption("wrap", !session.getUseWrapMode());
+ editor.renderer.scrollCursorIntoView();
+ }
+ }
+ });
+
+ editor.on("gutterclick", function(e) {
+ var gutterRegion = editor.renderer.$gutterLayer.getRegion(e);
+
+ if (gutterRegion == "foldWidgets") {
+ var row = e.getDocumentPosition().row;
+ var session = editor.session;
+ if (session.foldWidgets && session.foldWidgets[row])
+ editor.session.onFoldWidgetClick(row, e);
+ if (!editor.isFocused()) editor.focus();
+ e.stop();
+ }
+ });
+
+ editor.on("gutterdblclick", function(e) {
+ var gutterRegion = editor.renderer.$gutterLayer.getRegion(e);
+
+ if (gutterRegion == "foldWidgets") {
+ var row = e.getDocumentPosition().row;
+ var session = editor.session;
+ var data = session.getParentFoldRangeData(row, true);
+ var range = data.range || data.firstRange;
+
+ if (range) {
+ row = range.start.row;
+ var fold = session.getFoldAt(row, session.getLine(row).length, 1);
+
+ if (fold) {
+ session.removeFold(fold);
+ } else {
+ session.addFold("...", range);
+ editor.renderer.scrollCursorIntoView({
+ row: range.start.row,
+ column: 0
+ });
+ }
+ }
+ e.stop();
+ }
+ });
+ }
+
+ exports.FoldHandler = FoldHandler;
+ }
+);
+
+ace.define(
+ "ace/keyboard/keybinding",
+ ["require", "exports", "module", "ace/lib/keys", "ace/lib/event"],
+ function(require, exports, module) {
+ "use strict";
+
+ var keyUtil = require("../lib/keys");
+ var event = require("../lib/event");
+
+ var KeyBinding = function(editor) {
+ this.$editor = editor;
+ this.$data = { editor: editor };
+ this.$handlers = [];
+ this.setDefaultHandler(editor.commands);
+ };
+
+ (function() {
+ this.setDefaultHandler = function(kb) {
+ this.removeKeyboardHandler(this.$defaultHandler);
+ this.$defaultHandler = kb;
+ this.addKeyboardHandler(kb, 0);
+ };
+
+ this.setKeyboardHandler = function(kb) {
+ var h = this.$handlers;
+ if (h[h.length - 1] == kb) return;
+
+ while (h[h.length - 1] && h[h.length - 1] != this.$defaultHandler)
+ this.removeKeyboardHandler(h[h.length - 1]);
+
+ this.addKeyboardHandler(kb, 1);
+ };
+
+ this.addKeyboardHandler = function(kb, pos) {
+ if (!kb) return;
+ if (typeof kb == "function" && !kb.handleKeyboard)
+ kb.handleKeyboard = kb;
+ var i = this.$handlers.indexOf(kb);
+ if (i != -1) this.$handlers.splice(i, 1);
+
+ if (pos == undefined) this.$handlers.push(kb);
+ else this.$handlers.splice(pos, 0, kb);
+
+ if (i == -1 && kb.attach) kb.attach(this.$editor);
+ };
+
+ this.removeKeyboardHandler = function(kb) {
+ var i = this.$handlers.indexOf(kb);
+ if (i == -1) return false;
+ this.$handlers.splice(i, 1);
+ kb.detach && kb.detach(this.$editor);
+ return true;
+ };
+
+ this.getKeyboardHandler = function() {
+ return this.$handlers[this.$handlers.length - 1];
+ };
+
+ this.getStatusText = function() {
+ var data = this.$data;
+ var editor = data.editor;
+ return this.$handlers
+ .map(function(h) {
+ return (h.getStatusText && h.getStatusText(editor, data)) || "";
+ })
+ .filter(Boolean)
+ .join(" ");
+ };
+
+ this.$callKeyboardHandlers = function(hashId, keyString, keyCode, e) {
+ var toExecute;
+ var success = false;
+ var commands = this.$editor.commands;
+
+ for (var i = this.$handlers.length; i--; ) {
+ toExecute = this.$handlers[i].handleKeyboard(
+ this.$data,
+ hashId,
+ keyString,
+ keyCode,
+ e
+ );
+ if (!toExecute || !toExecute.command) continue;
+ if (toExecute.command == "null") {
+ success = true;
+ } else {
+ success = commands.exec(
+ toExecute.command,
+ this.$editor,
+ toExecute.args,
+ e
+ );
+ }
+ if (
+ success &&
+ e &&
+ hashId != -1 &&
+ toExecute.passEvent != true &&
+ toExecute.command.passEvent != true
+ ) {
+ event.stopEvent(e);
+ }
+ if (success) break;
+ }
+
+ if (!success && hashId == -1) {
+ toExecute = { command: "insertstring" };
+ success = commands.exec("insertstring", this.$editor, keyString);
+ }
+
+ if (success && this.$editor._signal)
+ this.$editor._signal("keyboardActivity", toExecute);
+
+ return success;
+ };
+
+ this.onCommandKey = function(e, hashId, keyCode) {
+ var keyString = keyUtil.keyCodeToString(keyCode);
+ return this.$callKeyboardHandlers(hashId, keyString, keyCode, e);
+ };
+
+ this.onTextInput = function(text) {
+ return this.$callKeyboardHandlers(-1, text);
+ };
+ }.call(KeyBinding.prototype));
+
+ exports.KeyBinding = KeyBinding;
+ }
+);
+
+ace.define("ace/lib/bidiutil", ["require", "exports", "module"], function(
+ require,
+ exports,
+ module
+) {
+ "use strict";
+
+ var ArabicAlefBetIntervalsBegine = ["\u0621", "\u0641"];
+ var ArabicAlefBetIntervalsEnd = ["\u063A", "\u064a"];
+ var dir = 0,
+ hiLevel = 0;
+ var lastArabic = false,
+ hasUBAT_AL = false,
+ hasUBAT_B = false,
+ hasUBAT_S = false,
+ hasBlockSep = false,
+ hasSegSep = false;
+
+ var impTab_LTR = [
+ [0, 3, 0, 1, 0, 0, 0],
+ [0, 3, 0, 1, 2, 2, 0],
+ [0, 3, 0, 0x11, 2, 0, 1],
+ [0, 3, 5, 5, 4, 1, 0],
+ [0, 3, 0x15, 0x15, 4, 0, 1],
+ [0, 3, 5, 5, 4, 2, 0]
+ ];
+
+ var impTab_RTL = [
+ [2, 0, 1, 1, 0, 1, 0],
+ [2, 0, 1, 1, 0, 2, 0],
+ [2, 0, 2, 1, 3, 2, 0],
+ [2, 0, 2, 0x21, 3, 1, 1]
+ ];
+
+ var LTR = 0,
+ RTL = 1;
+
+ var L = 0;
+ var R = 1;
+ var EN = 2;
+ var AN = 3;
+ var ON = 4;
+ var B = 5;
+ var S = 6;
+ var AL = 7;
+ var WS = 8;
+ var CS = 9;
+ var ES = 10;
+ var ET = 11;
+ var NSM = 12;
+ var LRE = 13;
+ var RLE = 14;
+ var PDF = 15;
+ var LRO = 16;
+ var RLO = 17;
+ var BN = 18;
+
+ var UnicodeTBL00 = [
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ S,
+ B,
+ S,
+ WS,
+ B,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ B,
+ B,
+ B,
+ S,
+ WS,
+ ON,
+ ON,
+ ET,
+ ET,
+ ET,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ES,
+ CS,
+ ES,
+ CS,
+ CS,
+ EN,
+ EN,
+ EN,
+ EN,
+ EN,
+ EN,
+ EN,
+ EN,
+ EN,
+ EN,
+ CS,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ L,
+ ON,
+ ON,
+ ON,
+ ON,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ B,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ BN,
+ CS,
+ ON,
+ ET,
+ ET,
+ ET,
+ ET,
+ ON,
+ ON,
+ ON,
+ ON,
+ L,
+ ON,
+ ON,
+ BN,
+ ON,
+ ON,
+ ET,
+ ET,
+ EN,
+ EN,
+ ON,
+ L,
+ ON,
+ ON,
+ ON,
+ EN,
+ L,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON
+ ];
+
+ var UnicodeTBL20 = [
+ WS,
+ WS,
+ WS,
+ WS,
+ WS,
+ WS,
+ WS,
+ WS,
+ WS,
+ WS,
+ WS,
+ BN,
+ BN,
+ BN,
+ L,
+ R,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ WS,
+ B,
+ LRE,
+ RLE,
+ PDF,
+ LRO,
+ RLO,
+ CS,
+ ET,
+ ET,
+ ET,
+ ET,
+ ET,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ CS,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ ON,
+ WS
+ ];
+
+ function _computeLevels(chars, levels, len, charTypes) {
+ var impTab = dir ? impTab_RTL : impTab_LTR,
+ prevState = null,
+ newClass = null,
+ newLevel = null,
+ newState = 0,
+ action = null,
+ cond = null,
+ condPos = -1,
+ i = null,
+ ix = null,
+ classes = [];
+
+ if (!charTypes) {
+ for (i = 0, charTypes = []; i < len; i++) {
+ charTypes[i] = _getCharacterType(chars[i]);
+ }
+ }
+ hiLevel = dir;
+ lastArabic = false;
+ hasUBAT_AL = false;
+ hasUBAT_B = false;
+ hasUBAT_S = false;
+ for (ix = 0; ix < len; ix++) {
+ prevState = newState;
+ classes[ix] = newClass = _getCharClass(chars, charTypes, classes, ix);
+ newState = impTab[prevState][newClass];
+ action = newState & 0xf0;
+ newState &= 0x0f;
+ levels[ix] = newLevel = impTab[newState][5];
+ if (action > 0) {
+ if (action == 0x10) {
+ for (i = condPos; i < ix; i++) {
+ levels[i] = 1;
+ }
+ condPos = -1;
+ } else {
+ condPos = -1;
+ }
+ }
+ cond = impTab[newState][6];
+ if (cond) {
+ if (condPos == -1) {
+ condPos = ix;
+ }
+ } else {
+ if (condPos > -1) {
+ for (i = condPos; i < ix; i++) {
+ levels[i] = newLevel;
+ }
+ condPos = -1;
+ }
+ }
+ if (charTypes[ix] == B) {
+ levels[ix] = 0;
+ }
+ hiLevel |= newLevel;
+ }
+ if (hasUBAT_S) {
+ for (i = 0; i < len; i++) {
+ if (charTypes[i] == S) {
+ levels[i] = dir;
+ for (var j = i - 1; j >= 0; j--) {
+ if (charTypes[j] == WS) {
+ levels[j] = dir;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ function _invertLevel(lev, levels, _array) {
+ if (hiLevel < lev) {
+ return;
+ }
+ if (lev == 1 && dir == RTL && !hasUBAT_B) {
+ _array.reverse();
+ return;
+ }
+ var len = _array.length,
+ start = 0,
+ end,
+ lo,
+ hi,
+ tmp;
+ while (start < len) {
+ if (levels[start] >= lev) {
+ end = start + 1;
+ while (end < len && levels[end] >= lev) {
+ end++;
+ }
+ for (lo = start, hi = end - 1; lo < hi; lo++, hi--) {
+ tmp = _array[lo];
+ _array[lo] = _array[hi];
+ _array[hi] = tmp;
+ }
+ start = end;
+ }
+ start++;
+ }
+ }
+
+ function _getCharClass(chars, types, classes, ix) {
+ var cType = types[ix],
+ wType,
+ nType,
+ len,
+ i;
+ switch (cType) {
+ case L:
+ case R:
+ lastArabic = false;
+ case ON:
+ case AN:
+ return cType;
+ case EN:
+ return lastArabic ? AN : EN;
+ case AL:
+ lastArabic = true;
+ hasUBAT_AL = true;
+ return R;
+ case WS:
+ return ON;
+ case CS:
+ if (
+ ix < 1 ||
+ ix + 1 >= types.length ||
+ ((wType = classes[ix - 1]) != EN && wType != AN) ||
+ ((nType = types[ix + 1]) != EN && nType != AN)
+ ) {
+ return ON;
+ }
+ if (lastArabic) {
+ nType = AN;
+ }
+ return nType == wType ? nType : ON;
+ case ES:
+ wType = ix > 0 ? classes[ix - 1] : B;
+ if (wType == EN && ix + 1 < types.length && types[ix + 1] == EN) {
+ return EN;
+ }
+ return ON;
+ case ET:
+ if (ix > 0 && classes[ix - 1] == EN) {
+ return EN;
+ }
+ if (lastArabic) {
+ return ON;
+ }
+ i = ix + 1;
+ len = types.length;
+ while (i < len && types[i] == ET) {
+ i++;
+ }
+ if (i < len && types[i] == EN) {
+ return EN;
+ }
+ return ON;
+ case NSM:
+ len = types.length;
+ i = ix + 1;
+ while (i < len && types[i] == NSM) {
+ i++;
+ }
+ if (i < len) {
+ var c = chars[ix],
+ rtlCandidate = (c >= 0x0591 && c <= 0x08ff) || c == 0xfb1e;
+
+ wType = types[i];
+ if (rtlCandidate && (wType == R || wType == AL)) {
+ return R;
+ }
+ }
+
+ if (ix < 1 || (wType = types[ix - 1]) == B) {
+ return ON;
+ }
+ return classes[ix - 1];
+ case B:
+ lastArabic = false;
+ hasUBAT_B = true;
+ return dir;
+ case S:
+ hasUBAT_S = true;
+ return ON;
+ case LRE:
+ case RLE:
+ case LRO:
+ case RLO:
+ case PDF:
+ lastArabic = false;
+ case BN:
+ return ON;
+ }
+ }
+
+ function _getCharacterType(ch) {
+ var uc = ch.charCodeAt(0),
+ hi = uc >> 8;
+
+ if (hi == 0) {
+ return uc > 0x00bf ? L : UnicodeTBL00[uc];
+ } else if (hi == 5) {
+ return /[\u0591-\u05f4]/.test(ch) ? R : L;
+ } else if (hi == 6) {
+ if (/[\u0610-\u061a\u064b-\u065f\u06d6-\u06e4\u06e7-\u06ed]/.test(ch))
+ return NSM;
+ else if (/[\u0660-\u0669\u066b-\u066c]/.test(ch)) return AN;
+ else if (uc == 0x066a) return ET;
+ else if (/[\u06f0-\u06f9]/.test(ch)) return EN;
+ else return AL;
+ } else if (hi == 0x20 && uc <= 0x205f) {
+ return UnicodeTBL20[uc & 0xff];
+ } else if (hi == 0xfe) {
+ return uc >= 0xfe70 ? AL : ON;
+ }
+ return ON;
+ }
+
+ function _isArabicDiacritics(ch) {
+ return ch >= "\u064b" && ch <= "\u0655";
+ }
+ exports.L = L;
+ exports.R = R;
+ exports.EN = EN;
+ exports.ON_R = 3;
+ exports.AN = 4;
+ exports.R_H = 5;
+ exports.B = 6;
+ exports.RLE = 7;
+
+ exports.DOT = "\xB7";
+ exports.doBidiReorder = function(text, textCharTypes, isRtl) {
+ if (text.length < 2) return {};
+
+ var chars = text.split(""),
+ logicalFromVisual = new Array(chars.length),
+ bidiLevels = new Array(chars.length),
+ levels = [];
+
+ dir = isRtl ? RTL : LTR;
+
+ _computeLevels(chars, levels, chars.length, textCharTypes);
+
+ for (
+ var i = 0;
+ i < logicalFromVisual.length;
+ logicalFromVisual[i] = i, i++
+ );
+
+ _invertLevel(2, levels, logicalFromVisual);
+ _invertLevel(1, levels, logicalFromVisual);
+
+ for (var i = 0; i < logicalFromVisual.length - 1; i++) {
+ //fix levels to reflect character width
+ if (textCharTypes[i] === AN) {
+ levels[i] = exports.AN;
+ } else if (
+ levels[i] === R &&
+ ((textCharTypes[i] > AL && textCharTypes[i] < LRE) ||
+ textCharTypes[i] === ON ||
+ textCharTypes[i] === BN)
+ ) {
+ levels[i] = exports.ON_R;
+ } else if (
+ i > 0 &&
+ chars[i - 1] === "\u0644" &&
+ /\u0622|\u0623|\u0625|\u0627/.test(chars[i])
+ ) {
+ levels[i - 1] = levels[i] = exports.R_H;
+ i++;
+ }
+ }
+ if (chars[chars.length - 1] === exports.DOT)
+ levels[chars.length - 1] = exports.B;
+
+ if (chars[0] === "\u202B") levels[0] = exports.RLE;
+
+ for (var i = 0; i < logicalFromVisual.length; i++) {
+ bidiLevels[i] = levels[logicalFromVisual[i]];
+ }
+
+ return { logicalFromVisual: logicalFromVisual, bidiLevels: bidiLevels };
+ };
+ exports.hasBidiCharacters = function(text, textCharTypes) {
+ var ret = false;
+ for (var i = 0; i < text.length; i++) {
+ textCharTypes[i] = _getCharacterType(text.charAt(i));
+ if (
+ !ret &&
+ (textCharTypes[i] == R ||
+ textCharTypes[i] == AL ||
+ textCharTypes[i] == AN)
+ )
+ ret = true;
+ }
+ return ret;
+ };
+ exports.getVisualFromLogicalIdx = function(logIdx, rowMap) {
+ for (var i = 0; i < rowMap.logicalFromVisual.length; i++) {
+ if (rowMap.logicalFromVisual[i] == logIdx) return i;
+ }
+ return 0;
+ };
+});
+
+ace.define(
+ "ace/bidihandler",
+ ["require", "exports", "module", "ace/lib/bidiutil", "ace/lib/lang"],
+ function(require, exports, module) {
+ "use strict";
+
+ var bidiUtil = require("./lib/bidiutil");
+ var lang = require("./lib/lang");
+ var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac\u202B]/;
+ var BidiHandler = function(session) {
+ this.session = session;
+ this.bidiMap = {};
+ this.currentRow = null;
+ this.bidiUtil = bidiUtil;
+ this.charWidths = [];
+ this.EOL = "\xAC";
+ this.showInvisibles = true;
+ this.isRtlDir = false;
+ this.$isRtl = false;
+ this.line = "";
+ this.wrapIndent = 0;
+ this.EOF = "\xB6";
+ this.RLE = "\u202B";
+ this.contentWidth = 0;
+ this.fontMetrics = null;
+ this.rtlLineOffset = 0;
+ this.wrapOffset = 0;
+ this.isMoveLeftOperation = false;
+ this.seenBidi = bidiRE.test(session.getValue());
+ };
+
+ (function() {
+ this.isBidiRow = function(screenRow, docRow, splitIndex) {
+ if (!this.seenBidi) return false;
+ if (screenRow !== this.currentRow) {
+ this.currentRow = screenRow;
+ this.updateRowLine(docRow, splitIndex);
+ this.updateBidiMap();
+ }
+ return this.bidiMap.bidiLevels;
+ };
+
+ this.onChange = function(delta) {
+ if (!this.seenBidi) {
+ if (delta.action == "insert" && bidiRE.test(delta.lines.join("\n"))) {
+ this.seenBidi = true;
+ this.currentRow = null;
+ }
+ } else {
+ this.currentRow = null;
+ }
+ };
+
+ this.getDocumentRow = function() {
+ var docRow = 0;
+ var rowCache = this.session.$screenRowCache;
+ if (rowCache.length) {
+ var index = this.session.$getRowCacheIndex(rowCache, this.currentRow);
+ if (index >= 0) docRow = this.session.$docRowCache[index];
+ }
+
+ return docRow;
+ };
+
+ this.getSplitIndex = function() {
+ var splitIndex = 0;
+ var rowCache = this.session.$screenRowCache;
+ if (rowCache.length) {
+ var currentIndex,
+ prevIndex = this.session.$getRowCacheIndex(
+ rowCache,
+ this.currentRow
+ );
+ while (this.currentRow - splitIndex > 0) {
+ currentIndex = this.session.$getRowCacheIndex(
+ rowCache,
+ this.currentRow - splitIndex - 1
+ );
+ if (currentIndex !== prevIndex) break;
+
+ prevIndex = currentIndex;
+ splitIndex++;
+ }
+ } else {
+ splitIndex = this.currentRow;
+ }
+
+ return splitIndex;
+ };
+
+ this.updateRowLine = function(docRow, splitIndex) {
+ if (docRow === undefined) docRow = this.getDocumentRow();
+
+ var isLastRow = docRow === this.session.getLength() - 1,
+ endOfLine = isLastRow ? this.EOF : this.EOL;
+
+ this.wrapIndent = 0;
+ this.line = this.session.getLine(docRow);
+ this.isRtlDir = this.$isRtl || this.line.charAt(0) === this.RLE;
+ if (this.session.$useWrapMode) {
+ var splits = this.session.$wrapData[docRow];
+ if (splits) {
+ if (splitIndex === undefined) splitIndex = this.getSplitIndex();
+
+ if (splitIndex > 0 && splits.length) {
+ this.wrapIndent = splits.indent;
+ this.wrapOffset = this.wrapIndent * this.charWidths[bidiUtil.L];
+ this.line =
+ splitIndex < splits.length
+ ? this.line.substring(
+ splits[splitIndex - 1],
+ splits[splitIndex]
+ )
+ : this.line.substring(splits[splits.length - 1]);
+ } else {
+ this.line = this.line.substring(0, splits[splitIndex]);
+ }
+ }
+ if (splitIndex == splits.length)
+ this.line += this.showInvisibles ? endOfLine : bidiUtil.DOT;
+ } else {
+ this.line += this.showInvisibles ? endOfLine : bidiUtil.DOT;
+ }
+ var session = this.session,
+ shift = 0,
+ size;
+ this.line = this.line.replace(
+ /\t|[\u1100-\u2029, \u202F-\uFFE6]/g,
+ function(ch, i) {
+ if (ch === "\t" || session.isFullWidth(ch.charCodeAt(0))) {
+ size = ch === "\t" ? session.getScreenTabSize(i + shift) : 2;
+ shift += size - 1;
+ return lang.stringRepeat(bidiUtil.DOT, size);
+ }
+ return ch;
+ }
+ );
+
+ if (this.isRtlDir) {
+ this.fontMetrics.$main.textContent =
+ this.line.charAt(this.line.length - 1) == bidiUtil.DOT
+ ? this.line.substr(0, this.line.length - 1)
+ : this.line;
+ this.rtlLineOffset =
+ this.contentWidth -
+ this.fontMetrics.$main.getBoundingClientRect().width;
+ }
+ };
+
+ this.updateBidiMap = function() {
+ var textCharTypes = [];
+ if (
+ bidiUtil.hasBidiCharacters(this.line, textCharTypes) ||
+ this.isRtlDir
+ ) {
+ this.bidiMap = bidiUtil.doBidiReorder(
+ this.line,
+ textCharTypes,
+ this.isRtlDir
+ );
+ } else {
+ this.bidiMap = {};
+ }
+ };
+ this.markAsDirty = function() {
+ this.currentRow = null;
+ };
+ this.updateCharacterWidths = function(fontMetrics) {
+ if (this.characterWidth === fontMetrics.$characterSize.width) return;
+
+ this.fontMetrics = fontMetrics;
+ var characterWidth = (this.characterWidth =
+ fontMetrics.$characterSize.width);
+ var bidiCharWidth = fontMetrics.$measureCharWidth("\u05d4");
+
+ this.charWidths[bidiUtil.L] = this.charWidths[
+ bidiUtil.EN
+ ] = this.charWidths[bidiUtil.ON_R] = characterWidth;
+ this.charWidths[bidiUtil.R] = this.charWidths[
+ bidiUtil.AN
+ ] = bidiCharWidth;
+ this.charWidths[bidiUtil.R_H] = bidiCharWidth * 0.45;
+ this.charWidths[bidiUtil.B] = this.charWidths[bidiUtil.RLE] = 0;
+
+ this.currentRow = null;
+ };
+
+ this.setShowInvisibles = function(showInvisibles) {
+ this.showInvisibles = showInvisibles;
+ this.currentRow = null;
+ };
+
+ this.setEolChar = function(eolChar) {
+ this.EOL = eolChar;
+ };
+
+ this.setContentWidth = function(width) {
+ this.contentWidth = width;
+ };
+
+ this.isRtlLine = function(row) {
+ if (this.$isRtl) return true;
+ if (row != undefined)
+ return this.session.getLine(row).charAt(0) == this.RLE;
+ else return this.isRtlDir;
+ };
+
+ this.setRtlDirection = function(editor, isRtlDir) {
+ var cursor = editor.getCursorPosition();
+ for (
+ var row = editor.selection.getSelectionAnchor().row;
+ row <= cursor.row;
+ row++
+ ) {
+ if (
+ !isRtlDir &&
+ editor.session.getLine(row).charAt(0) ===
+ editor.session.$bidiHandler.RLE
+ )
+ editor.session.doc.removeInLine(row, 0, 1);
+ else if (
+ isRtlDir &&
+ editor.session.getLine(row).charAt(0) !==
+ editor.session.$bidiHandler.RLE
+ )
+ editor.session.doc.insert(
+ { column: 0, row: row },
+ editor.session.$bidiHandler.RLE
+ );
+ }
+ };
+ this.getPosLeft = function(col) {
+ col -= this.wrapIndent;
+ var leftBoundary = this.line.charAt(0) === this.RLE ? 1 : 0;
+ var logicalIdx =
+ col > leftBoundary
+ ? this.session.getOverwrite()
+ ? col
+ : col - 1
+ : leftBoundary;
+ var visualIdx = bidiUtil.getVisualFromLogicalIdx(
+ logicalIdx,
+ this.bidiMap
+ ),
+ levels = this.bidiMap.bidiLevels,
+ left = 0;
+
+ if (
+ !this.session.getOverwrite() &&
+ col <= leftBoundary &&
+ levels[visualIdx] % 2 !== 0
+ )
+ visualIdx++;
+
+ for (var i = 0; i < visualIdx; i++) {
+ left += this.charWidths[levels[i]];
+ }
+
+ if (
+ !this.session.getOverwrite() &&
+ col > leftBoundary &&
+ levels[visualIdx] % 2 === 0
+ )
+ left += this.charWidths[levels[visualIdx]];
+
+ if (this.wrapIndent)
+ left += this.isRtlDir ? -1 * this.wrapOffset : this.wrapOffset;
+
+ if (this.isRtlDir) left += this.rtlLineOffset;
+
+ return left;
+ };
+ this.getSelections = function(startCol, endCol) {
+ var map = this.bidiMap,
+ levels = map.bidiLevels,
+ level,
+ selections = [],
+ offset = 0,
+ selColMin = Math.min(startCol, endCol) - this.wrapIndent,
+ selColMax = Math.max(startCol, endCol) - this.wrapIndent,
+ isSelected = false,
+ isSelectedPrev = false,
+ selectionStart = 0;
+
+ if (this.wrapIndent)
+ offset += this.isRtlDir ? -1 * this.wrapOffset : this.wrapOffset;
+
+ for (var logIdx, visIdx = 0; visIdx < levels.length; visIdx++) {
+ logIdx = map.logicalFromVisual[visIdx];
+ level = levels[visIdx];
+ isSelected = logIdx >= selColMin && logIdx < selColMax;
+ if (isSelected && !isSelectedPrev) {
+ selectionStart = offset;
+ } else if (!isSelected && isSelectedPrev) {
+ selections.push({
+ left: selectionStart,
+ width: offset - selectionStart
+ });
+ }
+ offset += this.charWidths[level];
+ isSelectedPrev = isSelected;
+ }
+
+ if (isSelected && visIdx === levels.length) {
+ selections.push({
+ left: selectionStart,
+ width: offset - selectionStart
+ });
+ }
+
+ if (this.isRtlDir) {
+ for (var i = 0; i < selections.length; i++) {
+ selections[i].left += this.rtlLineOffset;
+ }
+ }
+ return selections;
+ };
+ this.offsetToCol = function(posX) {
+ if (this.isRtlDir) posX -= this.rtlLineOffset;
+
+ var logicalIdx = 0,
+ posX = Math.max(posX, 0),
+ offset = 0,
+ visualIdx = 0,
+ levels = this.bidiMap.bidiLevels,
+ charWidth = this.charWidths[levels[visualIdx]];
+
+ if (this.wrapIndent)
+ posX -= this.isRtlDir ? -1 * this.wrapOffset : this.wrapOffset;
+
+ while (posX > offset + charWidth / 2) {
+ offset += charWidth;
+ if (visualIdx === levels.length - 1) {
+ charWidth = 0;
+ break;
+ }
+ charWidth = this.charWidths[levels[++visualIdx]];
+ }
+
+ if (
+ visualIdx > 0 &&
+ levels[visualIdx - 1] % 2 !== 0 &&
+ levels[visualIdx] % 2 === 0
+ ) {
+ if (posX < offset) visualIdx--;
+ logicalIdx = this.bidiMap.logicalFromVisual[visualIdx];
+ } else if (
+ visualIdx > 0 &&
+ levels[visualIdx - 1] % 2 === 0 &&
+ levels[visualIdx] % 2 !== 0
+ ) {
+ logicalIdx =
+ 1 +
+ (posX > offset
+ ? this.bidiMap.logicalFromVisual[visualIdx]
+ : this.bidiMap.logicalFromVisual[visualIdx - 1]);
+ } else if (
+ (this.isRtlDir &&
+ visualIdx === levels.length - 1 &&
+ charWidth === 0 &&
+ levels[visualIdx - 1] % 2 === 0) ||
+ (!this.isRtlDir && visualIdx === 0 && levels[visualIdx] % 2 !== 0)
+ ) {
+ logicalIdx = 1 + this.bidiMap.logicalFromVisual[visualIdx];
+ } else {
+ if (
+ visualIdx > 0 &&
+ levels[visualIdx - 1] % 2 !== 0 &&
+ charWidth !== 0
+ )
+ visualIdx--;
+ logicalIdx = this.bidiMap.logicalFromVisual[visualIdx];
+ }
+
+ if (logicalIdx === 0 && this.isRtlDir) logicalIdx++;
+
+ return logicalIdx + this.wrapIndent;
+ };
+ }.call(BidiHandler.prototype));
+
+ exports.BidiHandler = BidiHandler;
+ }
+);
+
+ace.define(
+ "ace/selection",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/lib/oop",
+ "ace/lib/lang",
+ "ace/lib/event_emitter",
+ "ace/range"
+ ],
+ function(require, exports, module) {
+ "use strict";
+
+ var oop = require("./lib/oop");
+ var lang = require("./lib/lang");
+ var EventEmitter = require("./lib/event_emitter").EventEmitter;
+ var Range = require("./range").Range;
+ var Selection = function(session) {
+ this.session = session;
+ this.doc = session.getDocument();
+
+ this.clearSelection();
+ this.cursor = this.lead = this.doc.createAnchor(0, 0);
+ this.anchor = this.doc.createAnchor(0, 0);
+ this.$silent = false;
+
+ var self = this;
+ this.cursor.on("change", function(e) {
+ self.$cursorChanged = true;
+ if (!self.$silent) self._emit("changeCursor");
+ if (!self.$isEmpty && !self.$silent) self._emit("changeSelection");
+ if (!self.$keepDesiredColumnOnChange && e.old.column != e.value.column)
+ self.$desiredColumn = null;
+ });
+
+ this.anchor.on("change", function() {
+ self.$anchorChanged = true;
+ if (!self.$isEmpty && !self.$silent) self._emit("changeSelection");
+ });
+ };
+
+ (function() {
+ oop.implement(this, EventEmitter);
+ this.isEmpty = function() {
+ return (
+ this.$isEmpty ||
+ (this.anchor.row == this.lead.row &&
+ this.anchor.column == this.lead.column)
+ );
+ };
+ this.isMultiLine = function() {
+ return !this.$isEmpty && this.anchor.row != this.cursor.row;
+ };
+ this.getCursor = function() {
+ return this.lead.getPosition();
+ };
+ this.setSelectionAnchor = function(row, column) {
+ this.$isEmpty = false;
+ this.anchor.setPosition(row, column);
+ };
+ this.getAnchor = this.getSelectionAnchor = function() {
+ if (this.$isEmpty) return this.getSelectionLead();
+
+ return this.anchor.getPosition();
+ };
+ this.getSelectionLead = function() {
+ return this.lead.getPosition();
+ };
+ this.isBackwards = function() {
+ var anchor = this.anchor;
+ var lead = this.lead;
+ return (
+ anchor.row > lead.row ||
+ (anchor.row == lead.row && anchor.column > lead.column)
+ );
+ };
+ this.getRange = function() {
+ var anchor = this.anchor;
+ var lead = this.lead;
+
+ if (this.$isEmpty) return Range.fromPoints(lead, lead);
+
+ return this.isBackwards()
+ ? Range.fromPoints(lead, anchor)
+ : Range.fromPoints(anchor, lead);
+ };
+ this.clearSelection = function() {
+ if (!this.$isEmpty) {
+ this.$isEmpty = true;
+ this._emit("changeSelection");
+ }
+ };
+ this.selectAll = function() {
+ this.$setSelection(0, 0, Number.MAX_VALUE, Number.MAX_VALUE);
+ };
+ this.setRange = this.setSelectionRange = function(range, reverse) {
+ var start = reverse ? range.end : range.start;
+ var end = reverse ? range.start : range.end;
+ this.$setSelection(start.row, start.column, end.row, end.column);
+ };
+
+ this.$setSelection = function(
+ anchorRow,
+ anchorColumn,
+ cursorRow,
+ cursorColumn
+ ) {
+ if (this.$silent) return;
+ var wasEmpty = this.$isEmpty;
+ var wasMultiselect = this.inMultiSelectMode;
+ this.$silent = true;
+ this.$cursorChanged = this.$anchorChanged = false;
+ this.anchor.setPosition(anchorRow, anchorColumn);
+ this.cursor.setPosition(cursorRow, cursorColumn);
+ this.$isEmpty = !Range.comparePoints(this.anchor, this.cursor);
+ this.$silent = false;
+ if (this.$cursorChanged) this._emit("changeCursor");
+ if (
+ this.$cursorChanged ||
+ this.$anchorChanged ||
+ wasEmpty != this.$isEmpty ||
+ wasMultiselect
+ )
+ this._emit("changeSelection");
+ };
+
+ this.$moveSelection = function(mover) {
+ var lead = this.lead;
+ if (this.$isEmpty) this.setSelectionAnchor(lead.row, lead.column);
+
+ mover.call(this);
+ };
+ this.selectTo = function(row, column) {
+ this.$moveSelection(function() {
+ this.moveCursorTo(row, column);
+ });
+ };
+ this.selectToPosition = function(pos) {
+ this.$moveSelection(function() {
+ this.moveCursorToPosition(pos);
+ });
+ };
+ this.moveTo = function(row, column) {
+ this.clearSelection();
+ this.moveCursorTo(row, column);
+ };
+ this.moveToPosition = function(pos) {
+ this.clearSelection();
+ this.moveCursorToPosition(pos);
+ };
+ this.selectUp = function() {
+ this.$moveSelection(this.moveCursorUp);
+ };
+ this.selectDown = function() {
+ this.$moveSelection(this.moveCursorDown);
+ };
+ this.selectRight = function() {
+ this.$moveSelection(this.moveCursorRight);
+ };
+ this.selectLeft = function() {
+ this.$moveSelection(this.moveCursorLeft);
+ };
+ this.selectLineStart = function() {
+ this.$moveSelection(this.moveCursorLineStart);
+ };
+ this.selectLineEnd = function() {
+ this.$moveSelection(this.moveCursorLineEnd);
+ };
+ this.selectFileEnd = function() {
+ this.$moveSelection(this.moveCursorFileEnd);
+ };
+ this.selectFileStart = function() {
+ this.$moveSelection(this.moveCursorFileStart);
+ };
+ this.selectWordRight = function() {
+ this.$moveSelection(this.moveCursorWordRight);
+ };
+ this.selectWordLeft = function() {
+ this.$moveSelection(this.moveCursorWordLeft);
+ };
+ this.getWordRange = function(row, column) {
+ if (typeof column == "undefined") {
+ var cursor = row || this.lead;
+ row = cursor.row;
+ column = cursor.column;
+ }
+ return this.session.getWordRange(row, column);
+ };
+ this.selectWord = function() {
+ this.setSelectionRange(this.getWordRange());
+ };
+ this.selectAWord = function() {
+ var cursor = this.getCursor();
+ var range = this.session.getAWordRange(cursor.row, cursor.column);
+ this.setSelectionRange(range);
+ };
+
+ this.getLineRange = function(row, excludeLastChar) {
+ var rowStart = typeof row == "number" ? row : this.lead.row;
+ var rowEnd;
+
+ var foldLine = this.session.getFoldLine(rowStart);
+ if (foldLine) {
+ rowStart = foldLine.start.row;
+ rowEnd = foldLine.end.row;
+ } else {
+ rowEnd = rowStart;
+ }
+ if (excludeLastChar === true)
+ return new Range(
+ rowStart,
+ 0,
+ rowEnd,
+ this.session.getLine(rowEnd).length
+ );
+ else return new Range(rowStart, 0, rowEnd + 1, 0);
+ };
+ this.selectLine = function() {
+ this.setSelectionRange(this.getLineRange());
+ };
+ this.moveCursorUp = function() {
+ this.moveCursorBy(-1, 0);
+ };
+ this.moveCursorDown = function() {
+ this.moveCursorBy(1, 0);
+ };
+ this.wouldMoveIntoSoftTab = function(cursor, tabSize, direction) {
+ var start = cursor.column;
+ var end = cursor.column + tabSize;
+
+ if (direction < 0) {
+ start = cursor.column - tabSize;
+ end = cursor.column;
+ }
+ return (
+ this.session.isTabStop(cursor) &&
+ this.doc
+ .getLine(cursor.row)
+ .slice(start, end)
+ .split(" ").length -
+ 1 ==
+ tabSize
+ );
+ };
+ this.moveCursorLeft = function() {
+ var cursor = this.lead.getPosition(),
+ fold;
+
+ if ((fold = this.session.getFoldAt(cursor.row, cursor.column, -1))) {
+ this.moveCursorTo(fold.start.row, fold.start.column);
+ } else if (cursor.column === 0) {
+ if (cursor.row > 0) {
+ this.moveCursorTo(
+ cursor.row - 1,
+ this.doc.getLine(cursor.row - 1).length
+ );
+ }
+ } else {
+ var tabSize = this.session.getTabSize();
+ if (
+ this.wouldMoveIntoSoftTab(cursor, tabSize, -1) &&
+ !this.session.getNavigateWithinSoftTabs()
+ ) {
+ this.moveCursorBy(0, -tabSize);
+ } else {
+ this.moveCursorBy(0, -1);
+ }
+ }
+ };
+ this.moveCursorRight = function() {
+ var cursor = this.lead.getPosition(),
+ fold;
+ if ((fold = this.session.getFoldAt(cursor.row, cursor.column, 1))) {
+ this.moveCursorTo(fold.end.row, fold.end.column);
+ } else if (this.lead.column == this.doc.getLine(this.lead.row).length) {
+ if (this.lead.row < this.doc.getLength() - 1) {
+ this.moveCursorTo(this.lead.row + 1, 0);
+ }
+ } else {
+ var tabSize = this.session.getTabSize();
+ var cursor = this.lead;
+ if (
+ this.wouldMoveIntoSoftTab(cursor, tabSize, 1) &&
+ !this.session.getNavigateWithinSoftTabs()
+ ) {
+ this.moveCursorBy(0, tabSize);
+ } else {
+ this.moveCursorBy(0, 1);
+ }
+ }
+ };
+ this.moveCursorLineStart = function() {
+ var row = this.lead.row;
+ var column = this.lead.column;
+ var screenRow = this.session.documentToScreenRow(row, column);
+ var firstColumnPosition = this.session.screenToDocumentPosition(
+ screenRow,
+ 0
+ );
+ var beforeCursor = this.session.getDisplayLine(
+ row,
+ null,
+ firstColumnPosition.row,
+ firstColumnPosition.column
+ );
+
+ var leadingSpace = beforeCursor.match(/^\s*/);
+ if (
+ leadingSpace[0].length != column &&
+ !this.session.$useEmacsStyleLineStart
+ )
+ firstColumnPosition.column += leadingSpace[0].length;
+ this.moveCursorToPosition(firstColumnPosition);
+ };
+ this.moveCursorLineEnd = function() {
+ var lead = this.lead;
+ var lineEnd = this.session.getDocumentLastRowColumnPosition(
+ lead.row,
+ lead.column
+ );
+ if (this.lead.column == lineEnd.column) {
+ var line = this.session.getLine(lineEnd.row);
+ if (lineEnd.column == line.length) {
+ var textEnd = line.search(/\s+$/);
+ if (textEnd > 0) lineEnd.column = textEnd;
+ }
+ }
+
+ this.moveCursorTo(lineEnd.row, lineEnd.column);
+ };
+ this.moveCursorFileEnd = function() {
+ var row = this.doc.getLength() - 1;
+ var column = this.doc.getLine(row).length;
+ this.moveCursorTo(row, column);
+ };
+ this.moveCursorFileStart = function() {
+ this.moveCursorTo(0, 0);
+ };
+ this.moveCursorLongWordRight = function() {
+ var row = this.lead.row;
+ var column = this.lead.column;
+ var line = this.doc.getLine(row);
+ var rightOfCursor = line.substring(column);
+
+ this.session.nonTokenRe.lastIndex = 0;
+ this.session.tokenRe.lastIndex = 0;
+ var fold = this.session.getFoldAt(row, column, 1);
+ if (fold) {
+ this.moveCursorTo(fold.end.row, fold.end.column);
+ return;
+ }
+ if (this.session.nonTokenRe.exec(rightOfCursor)) {
+ column += this.session.nonTokenRe.lastIndex;
+ this.session.nonTokenRe.lastIndex = 0;
+ rightOfCursor = line.substring(column);
+ }
+ if (column >= line.length) {
+ this.moveCursorTo(row, line.length);
+ this.moveCursorRight();
+ if (row < this.doc.getLength() - 1) this.moveCursorWordRight();
+ return;
+ }
+ if (this.session.tokenRe.exec(rightOfCursor)) {
+ column += this.session.tokenRe.lastIndex;
+ this.session.tokenRe.lastIndex = 0;
+ }
+
+ this.moveCursorTo(row, column);
+ };
+ this.moveCursorLongWordLeft = function() {
+ var row = this.lead.row;
+ var column = this.lead.column;
+ var fold;
+ if ((fold = this.session.getFoldAt(row, column, -1))) {
+ this.moveCursorTo(fold.start.row, fold.start.column);
+ return;
+ }
+
+ var str = this.session.getFoldStringAt(row, column, -1);
+ if (str == null) {
+ str = this.doc.getLine(row).substring(0, column);
+ }
+
+ var leftOfCursor = lang.stringReverse(str);
+ this.session.nonTokenRe.lastIndex = 0;
+ this.session.tokenRe.lastIndex = 0;
+ if (this.session.nonTokenRe.exec(leftOfCursor)) {
+ column -= this.session.nonTokenRe.lastIndex;
+ leftOfCursor = leftOfCursor.slice(this.session.nonTokenRe.lastIndex);
+ this.session.nonTokenRe.lastIndex = 0;
+ }
+ if (column <= 0) {
+ this.moveCursorTo(row, 0);
+ this.moveCursorLeft();
+ if (row > 0) this.moveCursorWordLeft();
+ return;
+ }
+ if (this.session.tokenRe.exec(leftOfCursor)) {
+ column -= this.session.tokenRe.lastIndex;
+ this.session.tokenRe.lastIndex = 0;
+ }
+
+ this.moveCursorTo(row, column);
+ };
+
+ this.$shortWordEndIndex = function(rightOfCursor) {
+ var index = 0,
+ ch;
+ var whitespaceRe = /\s/;
+ var tokenRe = this.session.tokenRe;
+
+ tokenRe.lastIndex = 0;
+ if (this.session.tokenRe.exec(rightOfCursor)) {
+ index = this.session.tokenRe.lastIndex;
+ } else {
+ while ((ch = rightOfCursor[index]) && whitespaceRe.test(ch)) index++;
+
+ if (index < 1) {
+ tokenRe.lastIndex = 0;
+ while ((ch = rightOfCursor[index]) && !tokenRe.test(ch)) {
+ tokenRe.lastIndex = 0;
+ index++;
+ if (whitespaceRe.test(ch)) {
+ if (index > 2) {
+ index--;
+ break;
+ } else {
+ while ((ch = rightOfCursor[index]) && whitespaceRe.test(ch))
+ index++;
+ if (index > 2) break;
+ }
+ }
+ }
+ }
+ }
+ tokenRe.lastIndex = 0;
+
+ return index;
+ };
+
+ this.moveCursorShortWordRight = function() {
+ var row = this.lead.row;
+ var column = this.lead.column;
+ var line = this.doc.getLine(row);
+ var rightOfCursor = line.substring(column);
+
+ var fold = this.session.getFoldAt(row, column, 1);
+ if (fold) return this.moveCursorTo(fold.end.row, fold.end.column);
+
+ if (column == line.length) {
+ var l = this.doc.getLength();
+ do {
+ row++;
+ rightOfCursor = this.doc.getLine(row);
+ } while (row < l && /^\s*$/.test(rightOfCursor));
+
+ if (!/^\s+/.test(rightOfCursor)) rightOfCursor = "";
+ column = 0;
+ }
+
+ var index = this.$shortWordEndIndex(rightOfCursor);
+
+ this.moveCursorTo(row, column + index);
+ };
+
+ this.moveCursorShortWordLeft = function() {
+ var row = this.lead.row;
+ var column = this.lead.column;
+
+ var fold;
+ if ((fold = this.session.getFoldAt(row, column, -1)))
+ return this.moveCursorTo(fold.start.row, fold.start.column);
+
+ var line = this.session.getLine(row).substring(0, column);
+ if (column === 0) {
+ do {
+ row--;
+ line = this.doc.getLine(row);
+ } while (row > 0 && /^\s*$/.test(line));
+
+ column = line.length;
+ if (!/\s+$/.test(line)) line = "";
+ }
+
+ var leftOfCursor = lang.stringReverse(line);
+ var index = this.$shortWordEndIndex(leftOfCursor);
+
+ return this.moveCursorTo(row, column - index);
+ };
+
+ this.moveCursorWordRight = function() {
+ if (this.session.$selectLongWords) this.moveCursorLongWordRight();
+ else this.moveCursorShortWordRight();
+ };
+
+ this.moveCursorWordLeft = function() {
+ if (this.session.$selectLongWords) this.moveCursorLongWordLeft();
+ else this.moveCursorShortWordLeft();
+ };
+ this.moveCursorBy = function(rows, chars) {
+ var screenPos = this.session.documentToScreenPosition(
+ this.lead.row,
+ this.lead.column
+ );
+
+ var offsetX;
+
+ if (chars === 0) {
+ if (rows !== 0) {
+ if (
+ this.session.$bidiHandler.isBidiRow(screenPos.row, this.lead.row)
+ ) {
+ offsetX = this.session.$bidiHandler.getPosLeft(screenPos.column);
+ screenPos.column = Math.round(
+ offsetX / this.session.$bidiHandler.charWidths[0]
+ );
+ } else {
+ offsetX =
+ screenPos.column * this.session.$bidiHandler.charWidths[0];
+ }
+ }
+
+ if (this.$desiredColumn) screenPos.column = this.$desiredColumn;
+ else this.$desiredColumn = screenPos.column;
+ }
+
+ if (
+ rows != 0 &&
+ this.session.lineWidgets &&
+ this.session.lineWidgets[this.lead.row]
+ ) {
+ var widget = this.session.lineWidgets[this.lead.row];
+ if (rows < 0) rows -= widget.rowsAbove || 0;
+ else if (rows > 0) rows += widget.rowCount - (widget.rowsAbove || 0);
+ }
+
+ var docPos = this.session.screenToDocumentPosition(
+ screenPos.row + rows,
+ screenPos.column,
+ offsetX
+ );
+
+ if (
+ rows !== 0 &&
+ chars === 0 &&
+ docPos.row === this.lead.row &&
+ docPos.column === this.lead.column
+ ) {
+ }
+ this.moveCursorTo(docPos.row, docPos.column + chars, chars === 0);
+ };
+ this.moveCursorToPosition = function(position) {
+ this.moveCursorTo(position.row, position.column);
+ };
+ this.moveCursorTo = function(row, column, keepDesiredColumn) {
+ var fold = this.session.getFoldAt(row, column, 1);
+ if (fold) {
+ row = fold.start.row;
+ column = fold.start.column;
+ }
+
+ this.$keepDesiredColumnOnChange = true;
+ var line = this.session.getLine(row);
+ if (
+ /[\uDC00-\uDFFF]/.test(line.charAt(column)) &&
+ line.charAt(column - 1)
+ ) {
+ if (this.lead.row == row && this.lead.column == column + 1)
+ column = column - 1;
+ else column = column + 1;
+ }
+ this.lead.setPosition(row, column);
+ this.$keepDesiredColumnOnChange = false;
+
+ if (!keepDesiredColumn) this.$desiredColumn = null;
+ };
+ this.moveCursorToScreen = function(row, column, keepDesiredColumn) {
+ var pos = this.session.screenToDocumentPosition(row, column);
+ this.moveCursorTo(pos.row, pos.column, keepDesiredColumn);
+ };
+ this.detach = function() {
+ this.lead.detach();
+ this.anchor.detach();
+ this.session = this.doc = null;
+ };
+
+ this.fromOrientedRange = function(range) {
+ this.setSelectionRange(range, range.cursor == range.start);
+ this.$desiredColumn = range.desiredColumn || this.$desiredColumn;
+ };
+
+ this.toOrientedRange = function(range) {
+ var r = this.getRange();
+ if (range) {
+ range.start.column = r.start.column;
+ range.start.row = r.start.row;
+ range.end.column = r.end.column;
+ range.end.row = r.end.row;
+ } else {
+ range = r;
+ }
+
+ range.cursor = this.isBackwards() ? range.start : range.end;
+ range.desiredColumn = this.$desiredColumn;
+ return range;
+ };
+ this.getRangeOfMovements = function(func) {
+ var start = this.getCursor();
+ try {
+ func(this);
+ var end = this.getCursor();
+ return Range.fromPoints(start, end);
+ } catch (e) {
+ return Range.fromPoints(start, start);
+ } finally {
+ this.moveCursorToPosition(start);
+ }
+ };
+
+ this.toJSON = function() {
+ if (this.rangeCount) {
+ var data = this.ranges.map(function(r) {
+ var r1 = r.clone();
+ r1.isBackwards = r.cursor == r.start;
+ return r1;
+ });
+ } else {
+ var data = this.getRange();
+ data.isBackwards = this.isBackwards();
+ }
+ return data;
+ };
+
+ this.fromJSON = function(data) {
+ if (data.start == undefined) {
+ if (this.rangeList && data.length > 1) {
+ this.toSingleRange(data[0]);
+ for (var i = data.length; i--; ) {
+ var r = Range.fromPoints(data[i].start, data[i].end);
+ if (data[i].isBackwards) r.cursor = r.start;
+ this.addRange(r, true);
+ }
+ return;
+ } else {
+ data = data[0];
+ }
+ }
+ if (this.rangeList) this.toSingleRange(data);
+ this.setSelectionRange(data, data.isBackwards);
+ };
+
+ this.isEqual = function(data) {
+ if ((data.length || this.rangeCount) && data.length != this.rangeCount)
+ return false;
+ if (!data.length || !this.ranges) return this.getRange().isEqual(data);
+
+ for (var i = this.ranges.length; i--; ) {
+ if (!this.ranges[i].isEqual(data[i])) return false;
+ }
+ return true;
+ };
+ }.call(Selection.prototype));
+
+ exports.Selection = Selection;
+ }
+);
+
+ace.define(
+ "ace/tokenizer",
+ ["require", "exports", "module", "ace/config"],
+ function(require, exports, module) {
+ "use strict";
+
+ var config = require("./config");
+ var MAX_TOKEN_COUNT = 2000;
+ var Tokenizer = function(rules) {
+ this.states = rules;
+
+ this.regExps = {};
+ this.matchMappings = {};
+ for (var key in this.states) {
+ var state = this.states[key];
+ var ruleRegExps = [];
+ var matchTotal = 0;
+ var mapping = (this.matchMappings[key] = { defaultToken: "text" });
+ var flag = "g";
+
+ var splitterRurles = [];
+ for (var i = 0; i < state.length; i++) {
+ var rule = state[i];
+ if (rule.defaultToken) mapping.defaultToken = rule.defaultToken;
+ if (rule.caseInsensitive) flag = "gi";
+ if (rule.regex == null) continue;
+
+ if (rule.regex instanceof RegExp)
+ rule.regex = rule.regex.toString().slice(1, -1);
+ var adjustedregex = rule.regex;
+ var matchcount =
+ new RegExp("(?:(" + adjustedregex + ")|(.))").exec("a").length - 2;
+ if (Array.isArray(rule.token)) {
+ if (rule.token.length == 1 || matchcount == 1) {
+ rule.token = rule.token[0];
+ } else if (matchcount - 1 != rule.token.length) {
+ this.reportError(
+ "number of classes and regexp groups doesn't match",
+ {
+ rule: rule,
+ groupCount: matchcount - 1
+ }
+ );
+ rule.token = rule.token[0];
+ } else {
+ rule.tokenArray = rule.token;
+ rule.token = null;
+ rule.onMatch = this.$arrayTokens;
+ }
+ } else if (typeof rule.token == "function" && !rule.onMatch) {
+ if (matchcount > 1) rule.onMatch = this.$applyToken;
+ else rule.onMatch = rule.token;
+ }
+
+ if (matchcount > 1) {
+ if (/\\\d/.test(rule.regex)) {
+ adjustedregex = rule.regex.replace(/\\([0-9]+)/g, function(
+ match,
+ digit
+ ) {
+ return "\\" + (parseInt(digit, 10) + matchTotal + 1);
+ });
+ } else {
+ matchcount = 1;
+ adjustedregex = this.removeCapturingGroups(rule.regex);
+ }
+ if (!rule.splitRegex && typeof rule.token != "string")
+ splitterRurles.push(rule); // flag will be known only at the very end
+ }
+
+ mapping[matchTotal] = i;
+ matchTotal += matchcount;
+
+ ruleRegExps.push(adjustedregex);
+ if (!rule.onMatch) rule.onMatch = null;
+ }
+
+ if (!ruleRegExps.length) {
+ mapping[0] = 0;
+ ruleRegExps.push("$");
+ }
+
+ splitterRurles.forEach(function(rule) {
+ rule.splitRegex = this.createSplitterRegexp(rule.regex, flag);
+ }, this);
+
+ this.regExps[key] = new RegExp(
+ "(" + ruleRegExps.join(")|(") + ")|($)",
+ flag
+ );
+ }
+ };
+
+ (function() {
+ this.$setMaxTokenCount = function(m) {
+ MAX_TOKEN_COUNT = m | 0;
+ };
+
+ this.$applyToken = function(str) {
+ var values = this.splitRegex.exec(str).slice(1);
+ var types = this.token.apply(this, values);
+ if (typeof types === "string") return [{ type: types, value: str }];
+
+ var tokens = [];
+ for (var i = 0, l = types.length; i < l; i++) {
+ if (values[i])
+ tokens[tokens.length] = {
+ type: types[i],
+ value: values[i]
+ };
+ }
+ return tokens;
+ };
+
+ this.$arrayTokens = function(str) {
+ if (!str) return [];
+ var values = this.splitRegex.exec(str);
+ if (!values) return "text";
+ var tokens = [];
+ var types = this.tokenArray;
+ for (var i = 0, l = types.length; i < l; i++) {
+ if (values[i + 1])
+ tokens[tokens.length] = {
+ type: types[i],
+ value: values[i + 1]
+ };
+ }
+ return tokens;
+ };
+
+ this.removeCapturingGroups = function(src) {
+ var r = src.replace(/\\.|\[(?:\\.|[^\\\]])*|\(\?[:=!]|(\()/g, function(
+ x,
+ y
+ ) {
+ return y ? "(?:" : x;
+ });
+ return r;
+ };
+
+ this.createSplitterRegexp = function(src, flag) {
+ if (src.indexOf("(?=") != -1) {
+ var stack = 0;
+ var inChClass = false;
+ var lastCapture = {};
+ src.replace(/(\\.)|(\((?:\?[=!])?)|(\))|([\[\]])/g, function(
+ m,
+ esc,
+ parenOpen,
+ parenClose,
+ square,
+ index
+ ) {
+ if (inChClass) {
+ inChClass = square != "]";
+ } else if (square) {
+ inChClass = true;
+ } else if (parenClose) {
+ if (stack == lastCapture.stack) {
+ lastCapture.end = index + 1;
+ lastCapture.stack = -1;
+ }
+ stack--;
+ } else if (parenOpen) {
+ stack++;
+ if (parenOpen.length != 1) {
+ lastCapture.stack = stack;
+ lastCapture.start = index;
+ }
+ }
+ return m;
+ });
+
+ if (
+ lastCapture.end != null &&
+ /^\)*$/.test(src.substr(lastCapture.end))
+ )
+ src =
+ src.substring(0, lastCapture.start) + src.substr(lastCapture.end);
+ }
+ if (src.charAt(0) != "^") src = "^" + src;
+ if (src.charAt(src.length - 1) != "$") src += "$";
+
+ return new RegExp(src, (flag || "").replace("g", ""));
+ };
+ this.getLineTokens = function(line, startState) {
+ if (startState && typeof startState != "string") {
+ var stack = startState.slice(0);
+ startState = stack[0];
+ if (startState === "#tmp") {
+ stack.shift();
+ startState = stack.shift();
+ }
+ } else var stack = [];
+
+ var currentState = startState || "start";
+ var state = this.states[currentState];
+ if (!state) {
+ currentState = "start";
+ state = this.states[currentState];
+ }
+ var mapping = this.matchMappings[currentState];
+ var re = this.regExps[currentState];
+ re.lastIndex = 0;
+
+ var match,
+ tokens = [];
+ var lastIndex = 0;
+ var matchAttempts = 0;
+
+ var token = { type: null, value: "" };
+
+ while ((match = re.exec(line))) {
+ var type = mapping.defaultToken;
+ var rule = null;
+ var value = match[0];
+ var index = re.lastIndex;
+
+ if (index - value.length > lastIndex) {
+ var skipped = line.substring(lastIndex, index - value.length);
+ if (token.type == type) {
+ token.value += skipped;
+ } else {
+ if (token.type) tokens.push(token);
+ token = { type: type, value: skipped };
+ }
+ }
+
+ for (var i = 0; i < match.length - 2; i++) {
+ if (match[i + 1] === undefined) continue;
+
+ rule = state[mapping[i]];
+
+ if (rule.onMatch)
+ type = rule.onMatch(value, currentState, stack, line);
+ else type = rule.token;
+
+ if (rule.next) {
+ if (typeof rule.next == "string") {
+ currentState = rule.next;
+ } else {
+ currentState = rule.next(currentState, stack);
+ }
+
+ state = this.states[currentState];
+ if (!state) {
+ this.reportError("state doesn't exist", currentState);
+ currentState = "start";
+ state = this.states[currentState];
+ }
+ mapping = this.matchMappings[currentState];
+ lastIndex = index;
+ re = this.regExps[currentState];
+ re.lastIndex = index;
+ }
+ if (rule.consumeLineEnd) lastIndex = index;
+ break;
+ }
+
+ if (value) {
+ if (typeof type === "string") {
+ if ((!rule || rule.merge !== false) && token.type === type) {
+ token.value += value;
+ } else {
+ if (token.type) tokens.push(token);
+ token = { type: type, value: value };
+ }
+ } else if (type) {
+ if (token.type) tokens.push(token);
+ token = { type: null, value: "" };
+ for (var i = 0; i < type.length; i++) tokens.push(type[i]);
+ }
+ }
+
+ if (lastIndex == line.length) break;
+
+ lastIndex = index;
+
+ if (matchAttempts++ > MAX_TOKEN_COUNT) {
+ if (matchAttempts > 2 * line.length) {
+ this.reportError("infinite loop with in ace tokenizer", {
+ startState: startState,
+ line: line
+ });
+ }
+ while (lastIndex < line.length) {
+ if (token.type) tokens.push(token);
+ token = {
+ value: line.substring(lastIndex, (lastIndex += 500)),
+ type: "overflow"
+ };
+ }
+ currentState = "start";
+ stack = [];
+ break;
+ }
+ }
+
+ if (token.type) tokens.push(token);
+
+ if (stack.length > 1) {
+ if (stack[0] !== currentState) stack.unshift("#tmp", currentState);
+ }
+ return {
+ tokens: tokens,
+ state: stack.length ? stack : currentState
+ };
+ };
+
+ this.reportError = config.reportError;
+ }.call(Tokenizer.prototype));
+
+ exports.Tokenizer = Tokenizer;
+ }
+);
+
+ace.define(
+ "ace/mode/text_highlight_rules",
+ ["require", "exports", "module", "ace/lib/lang"],
+ function(require, exports, module) {
+ "use strict";
+
+ var lang = require("../lib/lang");
+
+ var TextHighlightRules = function() {
+ this.$rules = {
+ start: [
+ {
+ token: "empty_line",
+ regex: "^$"
+ },
+ {
+ defaultToken: "text"
+ }
+ ]
+ };
+ };
+
+ (function() {
+ this.addRules = function(rules, prefix) {
+ if (!prefix) {
+ for (var key in rules) this.$rules[key] = rules[key];
+ return;
+ }
+ for (var key in rules) {
+ var state = rules[key];
+ for (var i = 0; i < state.length; i++) {
+ var rule = state[i];
+ if (rule.next || rule.onMatch) {
+ if (typeof rule.next == "string") {
+ if (rule.next.indexOf(prefix) !== 0)
+ rule.next = prefix + rule.next;
+ }
+ if (rule.nextState && rule.nextState.indexOf(prefix) !== 0)
+ rule.nextState = prefix + rule.nextState;
+ }
+ }
+ this.$rules[prefix + key] = state;
+ }
+ };
+
+ this.getRules = function() {
+ return this.$rules;
+ };
+
+ this.embedRules = function(
+ HighlightRules,
+ prefix,
+ escapeRules,
+ states,
+ append
+ ) {
+ var embedRules =
+ typeof HighlightRules == "function"
+ ? new HighlightRules().getRules()
+ : HighlightRules;
+ if (states) {
+ for (var i = 0; i < states.length; i++)
+ states[i] = prefix + states[i];
+ } else {
+ states = [];
+ for (var key in embedRules) states.push(prefix + key);
+ }
+
+ this.addRules(embedRules, prefix);
+
+ if (escapeRules) {
+ var addRules = Array.prototype[append ? "push" : "unshift"];
+ for (var i = 0; i < states.length; i++)
+ addRules.apply(this.$rules[states[i]], lang.deepCopy(escapeRules));
+ }
+
+ if (!this.$embeds) this.$embeds = [];
+ this.$embeds.push(prefix);
+ };
+
+ this.getEmbeds = function() {
+ return this.$embeds;
+ };
+
+ var pushState = function(currentState, stack) {
+ if (currentState != "start" || stack.length)
+ stack.unshift(this.nextState, currentState);
+ return this.nextState;
+ };
+ var popState = function(currentState, stack) {
+ stack.shift();
+ return stack.shift() || "start";
+ };
+
+ this.normalizeRules = function() {
+ var id = 0;
+ var rules = this.$rules;
+ function processState(key) {
+ var state = rules[key];
+ state.processed = true;
+ for (var i = 0; i < state.length; i++) {
+ var rule = state[i];
+ var toInsert = null;
+ if (Array.isArray(rule)) {
+ toInsert = rule;
+ rule = {};
+ }
+ if (!rule.regex && rule.start) {
+ rule.regex = rule.start;
+ if (!rule.next) rule.next = [];
+ rule.next.push(
+ {
+ defaultToken: rule.token
+ },
+ {
+ token: rule.token + ".end",
+ regex: rule.end || rule.start,
+ next: "pop"
+ }
+ );
+ rule.token = rule.token + ".start";
+ rule.push = true;
+ }
+ var next = rule.next || rule.push;
+ if (next && Array.isArray(next)) {
+ var stateName = rule.stateName;
+ if (!stateName) {
+ stateName = rule.token;
+ if (typeof stateName != "string")
+ stateName = stateName[0] || "";
+ if (rules[stateName]) stateName += id++;
+ }
+ rules[stateName] = next;
+ rule.next = stateName;
+ processState(stateName);
+ } else if (next == "pop") {
+ rule.next = popState;
+ }
+
+ if (rule.push) {
+ rule.nextState = rule.next || rule.push;
+ rule.next = pushState;
+ delete rule.push;
+ }
+
+ if (rule.rules) {
+ for (var r in rule.rules) {
+ if (rules[r]) {
+ if (rules[r].push)
+ rules[r].push.apply(rules[r], rule.rules[r]);
+ } else {
+ rules[r] = rule.rules[r];
+ }
+ }
+ }
+ var includeName = typeof rule == "string" ? rule : rule.include;
+ if (includeName) {
+ if (Array.isArray(includeName))
+ toInsert = includeName.map(function(x) {
+ return rules[x];
+ });
+ else toInsert = rules[includeName];
+ }
+
+ if (toInsert) {
+ var args = [i, 1].concat(toInsert);
+ if (rule.noEscape)
+ args = args.filter(function(x) {
+ return !x.next;
+ });
+ state.splice.apply(state, args);
+ i--;
+ }
+
+ if (rule.keywordMap) {
+ rule.token = this.createKeywordMapper(
+ rule.keywordMap,
+ rule.defaultToken || "text",
+ rule.caseInsensitive
+ );
+ delete rule.defaultToken;
+ }
+ }
+ }
+ Object.keys(rules).forEach(processState, this);
+ };
+
+ this.createKeywordMapper = function(
+ map,
+ defaultToken,
+ ignoreCase,
+ splitChar
+ ) {
+ var keywords = Object.create(null);
+ Object.keys(map).forEach(function(className) {
+ var a = map[className];
+ if (ignoreCase) a = a.toLowerCase();
+ var list = a.split(splitChar || "|");
+ for (var i = list.length; i--; ) keywords[list[i]] = className;
+ });
+ if (Object.getPrototypeOf(keywords)) {
+ keywords.__proto__ = null;
+ }
+ this.$keywordList = Object.keys(keywords);
+ map = null;
+ return ignoreCase
+ ? function(value) {
+ return keywords[value.toLowerCase()] || defaultToken;
+ }
+ : function(value) {
+ return keywords[value] || defaultToken;
+ };
+ };
+
+ this.getKeywords = function() {
+ return this.$keywords;
+ };
+ }.call(TextHighlightRules.prototype));
+
+ exports.TextHighlightRules = TextHighlightRules;
+ }
+);
+
+ace.define("ace/mode/behaviour", ["require", "exports", "module"], function(
+ require,
+ exports,
+ module
+) {
+ "use strict";
+
+ var Behaviour = function() {
+ this.$behaviours = {};
+ };
+
+ (function() {
+ this.add = function(name, action, callback) {
+ switch (undefined) {
+ case this.$behaviours:
+ this.$behaviours = {};
+ case this.$behaviours[name]:
+ this.$behaviours[name] = {};
+ }
+ this.$behaviours[name][action] = callback;
+ };
+
+ this.addBehaviours = function(behaviours) {
+ for (var key in behaviours) {
+ for (var action in behaviours[key]) {
+ this.add(key, action, behaviours[key][action]);
+ }
+ }
+ };
+
+ this.remove = function(name) {
+ if (this.$behaviours && this.$behaviours[name]) {
+ delete this.$behaviours[name];
+ }
+ };
+
+ this.inherit = function(mode, filter) {
+ if (typeof mode === "function") {
+ var behaviours = new mode().getBehaviours(filter);
+ } else {
+ var behaviours = mode.getBehaviours(filter);
+ }
+ this.addBehaviours(behaviours);
+ };
+
+ this.getBehaviours = function(filter) {
+ if (!filter) {
+ return this.$behaviours;
+ } else {
+ var ret = {};
+ for (var i = 0; i < filter.length; i++) {
+ if (this.$behaviours[filter[i]]) {
+ ret[filter[i]] = this.$behaviours[filter[i]];
+ }
+ }
+ return ret;
+ }
+ };
+ }.call(Behaviour.prototype));
+
+ exports.Behaviour = Behaviour;
+});
+
+ace.define(
+ "ace/token_iterator",
+ ["require", "exports", "module", "ace/range"],
+ function(require, exports, module) {
+ "use strict";
+
+ var Range = require("./range").Range;
+ var TokenIterator = function(session, initialRow, initialColumn) {
+ this.$session = session;
+ this.$row = initialRow;
+ this.$rowTokens = session.getTokens(initialRow);
+
+ var token = session.getTokenAt(initialRow, initialColumn);
+ this.$tokenIndex = token ? token.index : -1;
+ };
+
+ (function() {
+ this.stepBackward = function() {
+ this.$tokenIndex -= 1;
+
+ while (this.$tokenIndex < 0) {
+ this.$row -= 1;
+ if (this.$row < 0) {
+ this.$row = 0;
+ return null;
+ }
+
+ this.$rowTokens = this.$session.getTokens(this.$row);
+ this.$tokenIndex = this.$rowTokens.length - 1;
+ }
+
+ return this.$rowTokens[this.$tokenIndex];
+ };
+ this.stepForward = function() {
+ this.$tokenIndex += 1;
+ var rowCount;
+ while (this.$tokenIndex >= this.$rowTokens.length) {
+ this.$row += 1;
+ if (!rowCount) rowCount = this.$session.getLength();
+ if (this.$row >= rowCount) {
+ this.$row = rowCount - 1;
+ return null;
+ }
+
+ this.$rowTokens = this.$session.getTokens(this.$row);
+ this.$tokenIndex = 0;
+ }
+
+ return this.$rowTokens[this.$tokenIndex];
+ };
+ this.getCurrentToken = function() {
+ return this.$rowTokens[this.$tokenIndex];
+ };
+ this.getCurrentTokenRow = function() {
+ return this.$row;
+ };
+ this.getCurrentTokenColumn = function() {
+ var rowTokens = this.$rowTokens;
+ var tokenIndex = this.$tokenIndex;
+ var column = rowTokens[tokenIndex].start;
+ if (column !== undefined) return column;
+
+ column = 0;
+ while (tokenIndex > 0) {
+ tokenIndex -= 1;
+ column += rowTokens[tokenIndex].value.length;
+ }
+
+ return column;
+ };
+ this.getCurrentTokenPosition = function() {
+ return { row: this.$row, column: this.getCurrentTokenColumn() };
+ };
+ this.getCurrentTokenRange = function() {
+ var token = this.$rowTokens[this.$tokenIndex];
+ var column = this.getCurrentTokenColumn();
+ return new Range(
+ this.$row,
+ column,
+ this.$row,
+ column + token.value.length
+ );
+ };
+ }.call(TokenIterator.prototype));
+
+ exports.TokenIterator = TokenIterator;
+ }
+);
+
+ace.define(
+ "ace/mode/behaviour/cstyle",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/lib/oop",
+ "ace/mode/behaviour",
+ "ace/token_iterator",
+ "ace/lib/lang"
+ ],
+ function(require, exports, module) {
+ "use strict";
+
+ var oop = require("../../lib/oop");
+ var Behaviour = require("../behaviour").Behaviour;
+ var TokenIterator = require("../../token_iterator").TokenIterator;
+ var lang = require("../../lib/lang");
+
+ var SAFE_INSERT_IN_TOKENS = [
+ "text",
+ "paren.rparen",
+ "rparen",
+ "paren",
+ "punctuation.operator"
+ ];
+ var SAFE_INSERT_BEFORE_TOKENS = [
+ "text",
+ "paren.rparen",
+ "rparen",
+ "paren",
+ "punctuation.operator",
+ "comment"
+ ];
+
+ var context;
+ var contextCache = {};
+ var defaultQuotes = { '"': '"', "'": "'" };
+
+ var initContext = function(editor) {
+ var id = -1;
+ if (editor.multiSelect) {
+ id = editor.selection.index;
+ if (contextCache.rangeCount != editor.multiSelect.rangeCount)
+ contextCache = { rangeCount: editor.multiSelect.rangeCount };
+ }
+ if (contextCache[id]) return (context = contextCache[id]);
+ context = contextCache[id] = {
+ autoInsertedBrackets: 0,
+ autoInsertedRow: -1,
+ autoInsertedLineEnd: "",
+ maybeInsertedBrackets: 0,
+ maybeInsertedRow: -1,
+ maybeInsertedLineStart: "",
+ maybeInsertedLineEnd: ""
+ };
+ };
+
+ var getWrapped = function(selection, selected, opening, closing) {
+ var rowDiff = selection.end.row - selection.start.row;
+ return {
+ text: opening + selected + closing,
+ selection: [
+ 0,
+ selection.start.column + 1,
+ rowDiff,
+ selection.end.column + (rowDiff ? 0 : 1)
+ ]
+ };
+ };
+
+ var CstyleBehaviour = function(options) {
+ this.add("braces", "insertion", function(
+ state,
+ action,
+ editor,
+ session,
+ text
+ ) {
+ var cursor = editor.getCursorPosition();
+ var line = session.doc.getLine(cursor.row);
+ if (text == "{") {
+ initContext(editor);
+ var selection = editor.getSelectionRange();
+ var selected = session.doc.getTextRange(selection);
+ if (
+ selected !== "" &&
+ selected !== "{" &&
+ editor.getWrapBehavioursEnabled()
+ ) {
+ return getWrapped(selection, selected, "{", "}");
+ } else if (CstyleBehaviour.isSaneInsertion(editor, session)) {
+ if (
+ /[\]\}\)]/.test(line[cursor.column]) ||
+ editor.inMultiSelectMode ||
+ (options && options.braces)
+ ) {
+ CstyleBehaviour.recordAutoInsert(editor, session, "}");
+ return {
+ text: "{}",
+ selection: [1, 1]
+ };
+ } else {
+ CstyleBehaviour.recordMaybeInsert(editor, session, "{");
+ return {
+ text: "{",
+ selection: [1, 1]
+ };
+ }
+ }
+ } else if (text == "}") {
+ initContext(editor);
+ var rightChar = line.substring(cursor.column, cursor.column + 1);
+ if (rightChar == "}") {
+ var matching = session.$findOpeningBracket("}", {
+ column: cursor.column + 1,
+ row: cursor.row
+ });
+ if (
+ matching !== null &&
+ CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)
+ ) {
+ CstyleBehaviour.popAutoInsertedClosing();
+ return {
+ text: "",
+ selection: [1, 1]
+ };
+ }
+ }
+ } else if (text == "\n" || text == "\r\n") {
+ initContext(editor);
+ var closing = "";
+ if (CstyleBehaviour.isMaybeInsertedClosing(cursor, line)) {
+ closing = lang.stringRepeat("}", context.maybeInsertedBrackets);
+ CstyleBehaviour.clearMaybeInsertedClosing();
+ }
+ var rightChar = line.substring(cursor.column, cursor.column + 1);
+ if (rightChar === "}") {
+ var openBracePos = session.findMatchingBracket(
+ { row: cursor.row, column: cursor.column + 1 },
+ "}"
+ );
+ if (!openBracePos) return null;
+ var next_indent = this.$getIndent(
+ session.getLine(openBracePos.row)
+ );
+ } else if (closing) {
+ var next_indent = this.$getIndent(line);
+ } else {
+ CstyleBehaviour.clearMaybeInsertedClosing();
+ return;
+ }
+ var indent = next_indent + session.getTabString();
+
+ return {
+ text: "\n" + indent + "\n" + next_indent + closing,
+ selection: [1, indent.length, 1, indent.length]
+ };
+ } else {
+ CstyleBehaviour.clearMaybeInsertedClosing();
+ }
+ });
+
+ this.add("braces", "deletion", function(
+ state,
+ action,
+ editor,
+ session,
+ range
+ ) {
+ var selected = session.doc.getTextRange(range);
+ if (!range.isMultiLine() && selected == "{") {
+ initContext(editor);
+ var line = session.doc.getLine(range.start.row);
+ var rightChar = line.substring(
+ range.end.column,
+ range.end.column + 1
+ );
+ if (rightChar == "}") {
+ range.end.column++;
+ return range;
+ } else {
+ context.maybeInsertedBrackets--;
+ }
+ }
+ });
+
+ this.add("parens", "insertion", function(
+ state,
+ action,
+ editor,
+ session,
+ text
+ ) {
+ if (text == "(") {
+ initContext(editor);
+ var selection = editor.getSelectionRange();
+ var selected = session.doc.getTextRange(selection);
+ if (selected !== "" && editor.getWrapBehavioursEnabled()) {
+ return getWrapped(selection, selected, "(", ")");
+ } else if (CstyleBehaviour.isSaneInsertion(editor, session)) {
+ CstyleBehaviour.recordAutoInsert(editor, session, ")");
+ return {
+ text: "()",
+ selection: [1, 1]
+ };
+ }
+ } else if (text == ")") {
+ initContext(editor);
+ var cursor = editor.getCursorPosition();
+ var line = session.doc.getLine(cursor.row);
+ var rightChar = line.substring(cursor.column, cursor.column + 1);
+ if (rightChar == ")") {
+ var matching = session.$findOpeningBracket(")", {
+ column: cursor.column + 1,
+ row: cursor.row
+ });
+ if (
+ matching !== null &&
+ CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)
+ ) {
+ CstyleBehaviour.popAutoInsertedClosing();
+ return {
+ text: "",
+ selection: [1, 1]
+ };
+ }
+ }
+ }
+ });
+
+ this.add("parens", "deletion", function(
+ state,
+ action,
+ editor,
+ session,
+ range
+ ) {
+ var selected = session.doc.getTextRange(range);
+ if (!range.isMultiLine() && selected == "(") {
+ initContext(editor);
+ var line = session.doc.getLine(range.start.row);
+ var rightChar = line.substring(
+ range.start.column + 1,
+ range.start.column + 2
+ );
+ if (rightChar == ")") {
+ range.end.column++;
+ return range;
+ }
+ }
+ });
+
+ this.add("brackets", "insertion", function(
+ state,
+ action,
+ editor,
+ session,
+ text
+ ) {
+ if (text == "[") {
+ initContext(editor);
+ var selection = editor.getSelectionRange();
+ var selected = session.doc.getTextRange(selection);
+ if (selected !== "" && editor.getWrapBehavioursEnabled()) {
+ return getWrapped(selection, selected, "[", "]");
+ } else if (CstyleBehaviour.isSaneInsertion(editor, session)) {
+ CstyleBehaviour.recordAutoInsert(editor, session, "]");
+ return {
+ text: "[]",
+ selection: [1, 1]
+ };
+ }
+ } else if (text == "]") {
+ initContext(editor);
+ var cursor = editor.getCursorPosition();
+ var line = session.doc.getLine(cursor.row);
+ var rightChar = line.substring(cursor.column, cursor.column + 1);
+ if (rightChar == "]") {
+ var matching = session.$findOpeningBracket("]", {
+ column: cursor.column + 1,
+ row: cursor.row
+ });
+ if (
+ matching !== null &&
+ CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)
+ ) {
+ CstyleBehaviour.popAutoInsertedClosing();
+ return {
+ text: "",
+ selection: [1, 1]
+ };
+ }
+ }
+ }
+ });
+
+ this.add("brackets", "deletion", function(
+ state,
+ action,
+ editor,
+ session,
+ range
+ ) {
+ var selected = session.doc.getTextRange(range);
+ if (!range.isMultiLine() && selected == "[") {
+ initContext(editor);
+ var line = session.doc.getLine(range.start.row);
+ var rightChar = line.substring(
+ range.start.column + 1,
+ range.start.column + 2
+ );
+ if (rightChar == "]") {
+ range.end.column++;
+ return range;
+ }
+ }
+ });
+
+ this.add("string_dquotes", "insertion", function(
+ state,
+ action,
+ editor,
+ session,
+ text
+ ) {
+ var quotes = session.$mode.$quotes || defaultQuotes;
+ if (text.length == 1 && quotes[text]) {
+ if (
+ this.lineCommentStart &&
+ this.lineCommentStart.indexOf(text) != -1
+ )
+ return;
+ initContext(editor);
+ var quote = text;
+ var selection = editor.getSelectionRange();
+ var selected = session.doc.getTextRange(selection);
+ if (
+ selected !== "" &&
+ (selected.length != 1 || !quotes[selected]) &&
+ editor.getWrapBehavioursEnabled()
+ ) {
+ return getWrapped(selection, selected, quote, quote);
+ } else if (!selected) {
+ var cursor = editor.getCursorPosition();
+ var line = session.doc.getLine(cursor.row);
+ var leftChar = line.substring(cursor.column - 1, cursor.column);
+ var rightChar = line.substring(cursor.column, cursor.column + 1);
+
+ var token = session.getTokenAt(cursor.row, cursor.column);
+ var rightToken = session.getTokenAt(cursor.row, cursor.column + 1);
+ if (leftChar == "\\" && token && /escape/.test(token.type))
+ return null;
+
+ var stringBefore = token && /string|escape/.test(token.type);
+ var stringAfter =
+ !rightToken || /string|escape/.test(rightToken.type);
+
+ var pair;
+ if (rightChar == quote) {
+ pair = stringBefore !== stringAfter;
+ if (pair && /string\.end/.test(rightToken.type)) pair = false;
+ } else {
+ if (stringBefore && !stringAfter) return null; // wrap string with different quote
+ if (stringBefore && stringAfter) return null; // do not pair quotes inside strings
+ var wordRe = session.$mode.tokenRe;
+ wordRe.lastIndex = 0;
+ var isWordBefore = wordRe.test(leftChar);
+ wordRe.lastIndex = 0;
+ var isWordAfter = wordRe.test(leftChar);
+ if (isWordBefore || isWordAfter) return null; // before or after alphanumeric
+ if (rightChar && !/[\s;,.})\]\\]/.test(rightChar)) return null; // there is rightChar and it isn't closing
+ var charBefore = line[cursor.column - 2];
+ if (
+ leftChar == quote &&
+ (charBefore == quote || wordRe.test(charBefore))
+ )
+ return null;
+ pair = true;
+ }
+ return {
+ text: pair ? quote + quote : "",
+ selection: [1, 1]
+ };
+ }
+ }
+ });
+
+ this.add("string_dquotes", "deletion", function(
+ state,
+ action,
+ editor,
+ session,
+ range
+ ) {
+ var quotes = session.$mode.$quotes || defaultQuotes;
+
+ var selected = session.doc.getTextRange(range);
+ if (!range.isMultiLine() && quotes.hasOwnProperty(selected)) {
+ initContext(editor);
+ var line = session.doc.getLine(range.start.row);
+ var rightChar = line.substring(
+ range.start.column + 1,
+ range.start.column + 2
+ );
+ if (rightChar == selected) {
+ range.end.column++;
+ return range;
+ }
+ }
+ });
+ };
+
+ CstyleBehaviour.isSaneInsertion = function(editor, session) {
+ var cursor = editor.getCursorPosition();
+ var iterator = new TokenIterator(session, cursor.row, cursor.column);
+ if (
+ !this.$matchTokenType(
+ iterator.getCurrentToken() || "text",
+ SAFE_INSERT_IN_TOKENS
+ )
+ ) {
+ if (/[)}\]]/.test(editor.session.getLine(cursor.row)[cursor.column]))
+ return true;
+ var iterator2 = new TokenIterator(
+ session,
+ cursor.row,
+ cursor.column + 1
+ );
+ if (
+ !this.$matchTokenType(
+ iterator2.getCurrentToken() || "text",
+ SAFE_INSERT_IN_TOKENS
+ )
+ )
+ return false;
+ }
+ iterator.stepForward();
+ return (
+ iterator.getCurrentTokenRow() !== cursor.row ||
+ this.$matchTokenType(
+ iterator.getCurrentToken() || "text",
+ SAFE_INSERT_BEFORE_TOKENS
+ )
+ );
+ };
+
+ CstyleBehaviour.$matchTokenType = function(token, types) {
+ return types.indexOf(token.type || token) > -1;
+ };
+
+ CstyleBehaviour.recordAutoInsert = function(editor, session, bracket) {
+ var cursor = editor.getCursorPosition();
+ var line = session.doc.getLine(cursor.row);
+ if (
+ !this.isAutoInsertedClosing(
+ cursor,
+ line,
+ context.autoInsertedLineEnd[0]
+ )
+ )
+ context.autoInsertedBrackets = 0;
+ context.autoInsertedRow = cursor.row;
+ context.autoInsertedLineEnd = bracket + line.substr(cursor.column);
+ context.autoInsertedBrackets++;
+ };
+
+ CstyleBehaviour.recordMaybeInsert = function(editor, session, bracket) {
+ var cursor = editor.getCursorPosition();
+ var line = session.doc.getLine(cursor.row);
+ if (!this.isMaybeInsertedClosing(cursor, line))
+ context.maybeInsertedBrackets = 0;
+ context.maybeInsertedRow = cursor.row;
+ context.maybeInsertedLineStart = line.substr(0, cursor.column) + bracket;
+ context.maybeInsertedLineEnd = line.substr(cursor.column);
+ context.maybeInsertedBrackets++;
+ };
+
+ CstyleBehaviour.isAutoInsertedClosing = function(cursor, line, bracket) {
+ return (
+ context.autoInsertedBrackets > 0 &&
+ cursor.row === context.autoInsertedRow &&
+ bracket === context.autoInsertedLineEnd[0] &&
+ line.substr(cursor.column) === context.autoInsertedLineEnd
+ );
+ };
+
+ CstyleBehaviour.isMaybeInsertedClosing = function(cursor, line) {
+ return (
+ context.maybeInsertedBrackets > 0 &&
+ cursor.row === context.maybeInsertedRow &&
+ line.substr(cursor.column) === context.maybeInsertedLineEnd &&
+ line.substr(0, cursor.column) == context.maybeInsertedLineStart
+ );
+ };
+
+ CstyleBehaviour.popAutoInsertedClosing = function() {
+ context.autoInsertedLineEnd = context.autoInsertedLineEnd.substr(1);
+ context.autoInsertedBrackets--;
+ };
+
+ CstyleBehaviour.clearMaybeInsertedClosing = function() {
+ if (context) {
+ context.maybeInsertedBrackets = 0;
+ context.maybeInsertedRow = -1;
+ }
+ };
+
+ oop.inherits(CstyleBehaviour, Behaviour);
+
+ exports.CstyleBehaviour = CstyleBehaviour;
+ }
+);
+
+ace.define("ace/unicode", ["require", "exports", "module"], function(
+ require,
+ exports,
+ module
+) {
+ "use strict";
+ var wordChars = [
+ 48,
+ 9,
+ 8,
+ 25,
+ 5,
+ 0,
+ 2,
+ 25,
+ 48,
+ 0,
+ 11,
+ 0,
+ 5,
+ 0,
+ 6,
+ 22,
+ 2,
+ 30,
+ 2,
+ 457,
+ 5,
+ 11,
+ 15,
+ 4,
+ 8,
+ 0,
+ 2,
+ 0,
+ 18,
+ 116,
+ 2,
+ 1,
+ 3,
+ 3,
+ 9,
+ 0,
+ 2,
+ 2,
+ 2,
+ 0,
+ 2,
+ 19,
+ 2,
+ 82,
+ 2,
+ 138,
+ 2,
+ 4,
+ 3,
+ 155,
+ 12,
+ 37,
+ 3,
+ 0,
+ 8,
+ 38,
+ 10,
+ 44,
+ 2,
+ 0,
+ 2,
+ 1,
+ 2,
+ 1,
+ 2,
+ 0,
+ 9,
+ 26,
+ 6,
+ 2,
+ 30,
+ 10,
+ 7,
+ 61,
+ 2,
+ 9,
+ 5,
+ 101,
+ 2,
+ 7,
+ 3,
+ 9,
+ 2,
+ 18,
+ 3,
+ 0,
+ 17,
+ 58,
+ 3,
+ 100,
+ 15,
+ 53,
+ 5,
+ 0,
+ 6,
+ 45,
+ 211,
+ 57,
+ 3,
+ 18,
+ 2,
+ 5,
+ 3,
+ 11,
+ 3,
+ 9,
+ 2,
+ 1,
+ 7,
+ 6,
+ 2,
+ 2,
+ 2,
+ 7,
+ 3,
+ 1,
+ 3,
+ 21,
+ 2,
+ 6,
+ 2,
+ 0,
+ 4,
+ 3,
+ 3,
+ 8,
+ 3,
+ 1,
+ 3,
+ 3,
+ 9,
+ 0,
+ 5,
+ 1,
+ 2,
+ 4,
+ 3,
+ 11,
+ 16,
+ 2,
+ 2,
+ 5,
+ 5,
+ 1,
+ 3,
+ 21,
+ 2,
+ 6,
+ 2,
+ 1,
+ 2,
+ 1,
+ 2,
+ 1,
+ 3,
+ 0,
+ 2,
+ 4,
+ 5,
+ 1,
+ 3,
+ 2,
+ 4,
+ 0,
+ 8,
+ 3,
+ 2,
+ 0,
+ 8,
+ 15,
+ 12,
+ 2,
+ 2,
+ 8,
+ 2,
+ 2,
+ 2,
+ 21,
+ 2,
+ 6,
+ 2,
+ 1,
+ 2,
+ 4,
+ 3,
+ 9,
+ 2,
+ 2,
+ 2,
+ 2,
+ 3,
+ 0,
+ 16,
+ 3,
+ 3,
+ 9,
+ 18,
+ 2,
+ 2,
+ 7,
+ 3,
+ 1,
+ 3,
+ 21,
+ 2,
+ 6,
+ 2,
+ 1,
+ 2,
+ 4,
+ 3,
+ 8,
+ 3,
+ 1,
+ 3,
+ 2,
+ 9,
+ 1,
+ 5,
+ 1,
+ 2,
+ 4,
+ 3,
+ 9,
+ 2,
+ 0,
+ 17,
+ 1,
+ 2,
+ 5,
+ 4,
+ 2,
+ 2,
+ 3,
+ 4,
+ 1,
+ 2,
+ 0,
+ 2,
+ 1,
+ 4,
+ 1,
+ 4,
+ 2,
+ 4,
+ 11,
+ 5,
+ 4,
+ 4,
+ 2,
+ 2,
+ 3,
+ 3,
+ 0,
+ 7,
+ 0,
+ 15,
+ 9,
+ 18,
+ 2,
+ 2,
+ 7,
+ 2,
+ 2,
+ 2,
+ 22,
+ 2,
+ 9,
+ 2,
+ 4,
+ 4,
+ 7,
+ 2,
+ 2,
+ 2,
+ 3,
+ 8,
+ 1,
+ 2,
+ 1,
+ 7,
+ 3,
+ 3,
+ 9,
+ 19,
+ 1,
+ 2,
+ 7,
+ 2,
+ 2,
+ 2,
+ 22,
+ 2,
+ 9,
+ 2,
+ 4,
+ 3,
+ 8,
+ 2,
+ 2,
+ 2,
+ 3,
+ 8,
+ 1,
+ 8,
+ 0,
+ 2,
+ 3,
+ 3,
+ 9,
+ 19,
+ 1,
+ 2,
+ 7,
+ 2,
+ 2,
+ 2,
+ 22,
+ 2,
+ 15,
+ 4,
+ 7,
+ 2,
+ 2,
+ 2,
+ 3,
+ 10,
+ 0,
+ 9,
+ 3,
+ 3,
+ 9,
+ 11,
+ 5,
+ 3,
+ 1,
+ 2,
+ 17,
+ 4,
+ 23,
+ 2,
+ 8,
+ 2,
+ 0,
+ 3,
+ 6,
+ 4,
+ 0,
+ 5,
+ 5,
+ 2,
+ 0,
+ 2,
+ 7,
+ 19,
+ 1,
+ 14,
+ 57,
+ 6,
+ 14,
+ 2,
+ 9,
+ 40,
+ 1,
+ 2,
+ 0,
+ 3,
+ 1,
+ 2,
+ 0,
+ 3,
+ 0,
+ 7,
+ 3,
+ 2,
+ 6,
+ 2,
+ 2,
+ 2,
+ 0,
+ 2,
+ 0,
+ 3,
+ 1,
+ 2,
+ 12,
+ 2,
+ 2,
+ 3,
+ 4,
+ 2,
+ 0,
+ 2,
+ 5,
+ 3,
+ 9,
+ 3,
+ 1,
+ 35,
+ 0,
+ 24,
+ 1,
+ 7,
+ 9,
+ 12,
+ 0,
+ 2,
+ 0,
+ 2,
+ 0,
+ 5,
+ 9,
+ 2,
+ 35,
+ 5,
+ 19,
+ 2,
+ 5,
+ 5,
+ 7,
+ 2,
+ 35,
+ 10,
+ 0,
+ 58,
+ 73,
+ 7,
+ 77,
+ 3,
+ 37,
+ 11,
+ 42,
+ 2,
+ 0,
+ 4,
+ 328,
+ 2,
+ 3,
+ 3,
+ 6,
+ 2,
+ 0,
+ 2,
+ 3,
+ 3,
+ 40,
+ 2,
+ 3,
+ 3,
+ 32,
+ 2,
+ 3,
+ 3,
+ 6,
+ 2,
+ 0,
+ 2,
+ 3,
+ 3,
+ 14,
+ 2,
+ 56,
+ 2,
+ 3,
+ 3,
+ 66,
+ 5,
+ 0,
+ 33,
+ 15,
+ 17,
+ 84,
+ 13,
+ 619,
+ 3,
+ 16,
+ 2,
+ 25,
+ 6,
+ 74,
+ 22,
+ 12,
+ 2,
+ 6,
+ 12,
+ 20,
+ 12,
+ 19,
+ 13,
+ 12,
+ 2,
+ 2,
+ 2,
+ 1,
+ 13,
+ 51,
+ 3,
+ 29,
+ 4,
+ 0,
+ 5,
+ 1,
+ 3,
+ 9,
+ 34,
+ 2,
+ 3,
+ 9,
+ 7,
+ 87,
+ 9,
+ 42,
+ 6,
+ 69,
+ 11,
+ 28,
+ 4,
+ 11,
+ 5,
+ 11,
+ 11,
+ 39,
+ 3,
+ 4,
+ 12,
+ 43,
+ 5,
+ 25,
+ 7,
+ 10,
+ 38,
+ 27,
+ 5,
+ 62,
+ 2,
+ 28,
+ 3,
+ 10,
+ 7,
+ 9,
+ 14,
+ 0,
+ 89,
+ 75,
+ 5,
+ 9,
+ 18,
+ 8,
+ 13,
+ 42,
+ 4,
+ 11,
+ 71,
+ 55,
+ 9,
+ 9,
+ 4,
+ 48,
+ 83,
+ 2,
+ 2,
+ 30,
+ 14,
+ 230,
+ 23,
+ 280,
+ 3,
+ 5,
+ 3,
+ 37,
+ 3,
+ 5,
+ 3,
+ 7,
+ 2,
+ 0,
+ 2,
+ 0,
+ 2,
+ 0,
+ 2,
+ 30,
+ 3,
+ 52,
+ 2,
+ 6,
+ 2,
+ 0,
+ 4,
+ 2,
+ 2,
+ 6,
+ 4,
+ 3,
+ 3,
+ 5,
+ 5,
+ 12,
+ 6,
+ 2,
+ 2,
+ 6,
+ 67,
+ 1,
+ 20,
+ 0,
+ 29,
+ 0,
+ 14,
+ 0,
+ 17,
+ 4,
+ 60,
+ 12,
+ 5,
+ 0,
+ 4,
+ 11,
+ 18,
+ 0,
+ 5,
+ 0,
+ 3,
+ 9,
+ 2,
+ 0,
+ 4,
+ 4,
+ 7,
+ 0,
+ 2,
+ 0,
+ 2,
+ 0,
+ 2,
+ 3,
+ 2,
+ 10,
+ 3,
+ 3,
+ 6,
+ 4,
+ 5,
+ 0,
+ 53,
+ 1,
+ 2684,
+ 46,
+ 2,
+ 46,
+ 2,
+ 132,
+ 7,
+ 6,
+ 15,
+ 37,
+ 11,
+ 53,
+ 10,
+ 0,
+ 17,
+ 22,
+ 10,
+ 6,
+ 2,
+ 6,
+ 2,
+ 6,
+ 2,
+ 6,
+ 2,
+ 6,
+ 2,
+ 6,
+ 2,
+ 6,
+ 2,
+ 6,
+ 2,
+ 31,
+ 48,
+ 0,
+ 470,
+ 1,
+ 36,
+ 5,
+ 2,
+ 4,
+ 6,
+ 1,
+ 5,
+ 85,
+ 3,
+ 1,
+ 3,
+ 2,
+ 2,
+ 89,
+ 2,
+ 3,
+ 6,
+ 40,
+ 4,
+ 93,
+ 18,
+ 23,
+ 57,
+ 15,
+ 513,
+ 6581,
+ 75,
+ 20939,
+ 53,
+ 1164,
+ 68,
+ 45,
+ 3,
+ 268,
+ 4,
+ 27,
+ 21,
+ 31,
+ 3,
+ 13,
+ 13,
+ 1,
+ 2,
+ 24,
+ 9,
+ 69,
+ 11,
+ 1,
+ 38,
+ 8,
+ 3,
+ 102,
+ 3,
+ 1,
+ 111,
+ 44,
+ 25,
+ 51,
+ 13,
+ 68,
+ 12,
+ 9,
+ 7,
+ 23,
+ 4,
+ 0,
+ 5,
+ 45,
+ 3,
+ 35,
+ 13,
+ 28,
+ 4,
+ 64,
+ 15,
+ 10,
+ 39,
+ 54,
+ 10,
+ 13,
+ 3,
+ 9,
+ 7,
+ 22,
+ 4,
+ 1,
+ 5,
+ 66,
+ 25,
+ 2,
+ 227,
+ 42,
+ 2,
+ 1,
+ 3,
+ 9,
+ 7,
+ 11171,
+ 13,
+ 22,
+ 5,
+ 48,
+ 8453,
+ 301,
+ 3,
+ 61,
+ 3,
+ 105,
+ 39,
+ 6,
+ 13,
+ 4,
+ 6,
+ 11,
+ 2,
+ 12,
+ 2,
+ 4,
+ 2,
+ 0,
+ 2,
+ 1,
+ 2,
+ 1,
+ 2,
+ 107,
+ 34,
+ 362,
+ 19,
+ 63,
+ 3,
+ 53,
+ 41,
+ 11,
+ 5,
+ 15,
+ 17,
+ 6,
+ 13,
+ 1,
+ 25,
+ 2,
+ 33,
+ 4,
+ 2,
+ 134,
+ 20,
+ 9,
+ 8,
+ 25,
+ 5,
+ 0,
+ 2,
+ 25,
+ 12,
+ 88,
+ 4,
+ 5,
+ 3,
+ 5,
+ 3,
+ 5,
+ 3,
+ 2
+ ];
+
+ var code = 0;
+ var str = [];
+ for (var i = 0; i < wordChars.length; i += 2) {
+ str.push((code += wordChars[i]));
+ if (wordChars[i + 1]) str.push(45, (code += wordChars[i + 1]));
+ }
+
+ exports.wordChars = String.fromCharCode.apply(null, str);
+});
+
+ace.define(
+ "ace/mode/text",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/config",
+ "ace/tokenizer",
+ "ace/mode/text_highlight_rules",
+ "ace/mode/behaviour/cstyle",
+ "ace/unicode",
+ "ace/lib/lang",
+ "ace/token_iterator",
+ "ace/range"
+ ],
+ function(require, exports, module) {
+ "use strict";
+ var config = require("../config");
+
+ var Tokenizer = require("../tokenizer").Tokenizer;
+ var TextHighlightRules = require("./text_highlight_rules")
+ .TextHighlightRules;
+ var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
+ var unicode = require("../unicode");
+ var lang = require("../lib/lang");
+ var TokenIterator = require("../token_iterator").TokenIterator;
+ var Range = require("../range").Range;
+
+ var Mode = function() {
+ this.HighlightRules = TextHighlightRules;
+ };
+
+ (function() {
+ this.$defaultBehaviour = new CstyleBehaviour();
+
+ this.tokenRe = new RegExp("^[" + unicode.wordChars + "\\$_]+", "g");
+
+ this.nonTokenRe = new RegExp(
+ "^(?:[^" + unicode.wordChars + "\\$_]|\\s])+",
+ "g"
+ );
+
+ this.getTokenizer = function() {
+ if (!this.$tokenizer) {
+ this.$highlightRules =
+ this.$highlightRules ||
+ new this.HighlightRules(this.$highlightRuleConfig);
+ this.$tokenizer = new Tokenizer(this.$highlightRules.getRules());
+ }
+ return this.$tokenizer;
+ };
+
+ this.lineCommentStart = "";
+ this.blockComment = "";
+
+ this.toggleCommentLines = function(state, session, startRow, endRow) {
+ var doc = session.doc;
+
+ var ignoreBlankLines = true;
+ var shouldRemove = true;
+ var minIndent = Infinity;
+ var tabSize = session.getTabSize();
+ var insertAtTabStop = false;
+
+ if (!this.lineCommentStart) {
+ if (!this.blockComment) return false;
+ var lineCommentStart = this.blockComment.start;
+ var lineCommentEnd = this.blockComment.end;
+ var regexpStart = new RegExp(
+ "^(\\s*)(?:" + lang.escapeRegExp(lineCommentStart) + ")"
+ );
+ var regexpEnd = new RegExp(
+ "(?:" + lang.escapeRegExp(lineCommentEnd) + ")\\s*$"
+ );
+
+ var comment = function(line, i) {
+ if (testRemove(line, i)) return;
+ if (!ignoreBlankLines || /\S/.test(line)) {
+ doc.insertInLine({ row: i, column: line.length }, lineCommentEnd);
+ doc.insertInLine({ row: i, column: minIndent }, lineCommentStart);
+ }
+ };
+
+ var uncomment = function(line, i) {
+ var m;
+ if ((m = line.match(regexpEnd)))
+ doc.removeInLine(i, line.length - m[0].length, line.length);
+ if ((m = line.match(regexpStart)))
+ doc.removeInLine(i, m[1].length, m[0].length);
+ };
+
+ var testRemove = function(line, row) {
+ if (regexpStart.test(line)) return true;
+ var tokens = session.getTokens(row);
+ for (var i = 0; i < tokens.length; i++) {
+ if (tokens[i].type === "comment") return true;
+ }
+ };
+ } else {
+ if (Array.isArray(this.lineCommentStart)) {
+ var regexpStart = this.lineCommentStart
+ .map(lang.escapeRegExp)
+ .join("|");
+ var lineCommentStart = this.lineCommentStart[0];
+ } else {
+ var regexpStart = lang.escapeRegExp(this.lineCommentStart);
+ var lineCommentStart = this.lineCommentStart;
+ }
+ regexpStart = new RegExp("^(\\s*)(?:" + regexpStart + ") ?");
+
+ insertAtTabStop = session.getUseSoftTabs();
+
+ var uncomment = function(line, i) {
+ var m = line.match(regexpStart);
+ if (!m) return;
+ var start = m[1].length,
+ end = m[0].length;
+ if (!shouldInsertSpace(line, start, end) && m[0][end - 1] == " ")
+ end--;
+ doc.removeInLine(i, start, end);
+ };
+ var commentWithSpace = lineCommentStart + " ";
+ var comment = function(line, i) {
+ if (!ignoreBlankLines || /\S/.test(line)) {
+ if (shouldInsertSpace(line, minIndent, minIndent))
+ doc.insertInLine(
+ { row: i, column: minIndent },
+ commentWithSpace
+ );
+ else
+ doc.insertInLine(
+ { row: i, column: minIndent },
+ lineCommentStart
+ );
+ }
+ };
+ var testRemove = function(line, i) {
+ return regexpStart.test(line);
+ };
+
+ var shouldInsertSpace = function(line, before, after) {
+ var spaces = 0;
+ while (before-- && line.charAt(before) == " ") spaces++;
+ if (spaces % tabSize != 0) return false;
+ var spaces = 0;
+ while (line.charAt(after++) == " ") spaces++;
+ if (tabSize > 2) return spaces % tabSize != tabSize - 1;
+ else return spaces % tabSize == 0;
+ };
+ }
+
+ function iter(fun) {
+ for (var i = startRow; i <= endRow; i++) fun(doc.getLine(i), i);
+ }
+
+ var minEmptyLength = Infinity;
+ iter(function(line, i) {
+ var indent = line.search(/\S/);
+ if (indent !== -1) {
+ if (indent < minIndent) minIndent = indent;
+ if (shouldRemove && !testRemove(line, i)) shouldRemove = false;
+ } else if (minEmptyLength > line.length) {
+ minEmptyLength = line.length;
+ }
+ });
+
+ if (minIndent == Infinity) {
+ minIndent = minEmptyLength;
+ ignoreBlankLines = false;
+ shouldRemove = false;
+ }
+
+ if (insertAtTabStop && minIndent % tabSize != 0)
+ minIndent = Math.floor(minIndent / tabSize) * tabSize;
+
+ iter(shouldRemove ? uncomment : comment);
+ };
+
+ this.toggleBlockComment = function(state, session, range, cursor) {
+ var comment = this.blockComment;
+ if (!comment) return;
+ if (!comment.start && comment[0]) comment = comment[0];
+
+ var iterator = new TokenIterator(session, cursor.row, cursor.column);
+ var token = iterator.getCurrentToken();
+
+ var sel = session.selection;
+ var initialRange = session.selection.toOrientedRange();
+ var startRow, colDiff;
+
+ if (token && /comment/.test(token.type)) {
+ var startRange, endRange;
+ while (token && /comment/.test(token.type)) {
+ var i = token.value.indexOf(comment.start);
+ if (i != -1) {
+ var row = iterator.getCurrentTokenRow();
+ var column = iterator.getCurrentTokenColumn() + i;
+ startRange = new Range(
+ row,
+ column,
+ row,
+ column + comment.start.length
+ );
+ break;
+ }
+ token = iterator.stepBackward();
+ }
+
+ var iterator = new TokenIterator(session, cursor.row, cursor.column);
+ var token = iterator.getCurrentToken();
+ while (token && /comment/.test(token.type)) {
+ var i = token.value.indexOf(comment.end);
+ if (i != -1) {
+ var row = iterator.getCurrentTokenRow();
+ var column = iterator.getCurrentTokenColumn() + i;
+ endRange = new Range(
+ row,
+ column,
+ row,
+ column + comment.end.length
+ );
+ break;
+ }
+ token = iterator.stepForward();
+ }
+ if (endRange) session.remove(endRange);
+ if (startRange) {
+ session.remove(startRange);
+ startRow = startRange.start.row;
+ colDiff = -comment.start.length;
+ }
+ } else {
+ colDiff = comment.start.length;
+ startRow = range.start.row;
+ session.insert(range.end, comment.end);
+ session.insert(range.start, comment.start);
+ }
+ if (initialRange.start.row == startRow)
+ initialRange.start.column += colDiff;
+ if (initialRange.end.row == startRow)
+ initialRange.end.column += colDiff;
+ session.selection.fromOrientedRange(initialRange);
+ };
+
+ this.getNextLineIndent = function(state, line, tab) {
+ return this.$getIndent(line);
+ };
+
+ this.checkOutdent = function(state, line, input) {
+ return false;
+ };
+
+ this.autoOutdent = function(state, doc, row) {};
+
+ this.$getIndent = function(line) {
+ return line.match(/^\s*/)[0];
+ };
+
+ this.createWorker = function(session) {
+ return null;
+ };
+
+ this.createModeDelegates = function(mapping) {
+ this.$embeds = [];
+ this.$modes = {};
+ for (var i in mapping) {
+ if (mapping[i]) {
+ var Mode = mapping[i];
+ var id = Mode.prototype.$id;
+ var mode = config.$modes[id];
+ if (!mode) config.$modes[id] = mode = new Mode();
+ if (!config.$modes[i]) config.$modes[i] = mode;
+ this.$embeds.push(i);
+ this.$modes[i] = mode;
+ }
+ }
+
+ var delegations = [
+ "toggleBlockComment",
+ "toggleCommentLines",
+ "getNextLineIndent",
+ "checkOutdent",
+ "autoOutdent",
+ "transformAction",
+ "getCompletions"
+ ];
+
+ for (var i = 0; i < delegations.length; i++) {
+ (function(scope) {
+ var functionName = delegations[i];
+ var defaultHandler = scope[functionName];
+ scope[delegations[i]] = function() {
+ return this.$delegator(functionName, arguments, defaultHandler);
+ };
+ })(this);
+ }
+ };
+
+ this.$delegator = function(method, args, defaultHandler) {
+ var state = args[0] || "start";
+ if (typeof state != "string") {
+ if (Array.isArray(state[2])) {
+ var language = state[2][state[2].length - 1];
+ var mode = this.$modes[language];
+ if (mode)
+ return mode[method].apply(
+ mode,
+ [state[1]].concat([].slice.call(args, 1))
+ );
+ }
+ state = state[0] || "start";
+ }
+
+ for (var i = 0; i < this.$embeds.length; i++) {
+ if (!this.$modes[this.$embeds[i]]) continue;
+
+ var split = state.split(this.$embeds[i]);
+ if (!split[0] && split[1]) {
+ args[0] = split[1];
+ var mode = this.$modes[this.$embeds[i]];
+ return mode[method].apply(mode, args);
+ }
+ }
+ var ret = defaultHandler.apply(this, args);
+ return defaultHandler ? ret : undefined;
+ };
+
+ this.transformAction = function(state, action, editor, session, param) {
+ if (this.$behaviour) {
+ var behaviours = this.$behaviour.getBehaviours();
+ for (var key in behaviours) {
+ if (behaviours[key][action]) {
+ var ret = behaviours[key][action].apply(this, arguments);
+ if (ret) {
+ return ret;
+ }
+ }
+ }
+ }
+ };
+
+ this.getKeywords = function(append) {
+ if (!this.completionKeywords) {
+ var rules = this.$tokenizer.rules;
+ var completionKeywords = [];
+ for (var rule in rules) {
+ var ruleItr = rules[rule];
+ for (var r = 0, l = ruleItr.length; r < l; r++) {
+ if (typeof ruleItr[r].token === "string") {
+ if (/keyword|support|storage/.test(ruleItr[r].token))
+ completionKeywords.push(ruleItr[r].regex);
+ } else if (typeof ruleItr[r].token === "object") {
+ for (
+ var a = 0, aLength = ruleItr[r].token.length;
+ a < aLength;
+ a++
+ ) {
+ if (/keyword|support|storage/.test(ruleItr[r].token[a])) {
+ var rule = ruleItr[r].regex.match(/\(.+?\)/g)[a];
+ completionKeywords.push(rule.substr(1, rule.length - 2));
+ }
+ }
+ }
+ }
+ }
+ this.completionKeywords = completionKeywords;
+ }
+ if (!append) return this.$keywordList;
+ return completionKeywords.concat(this.$keywordList || []);
+ };
+
+ this.$createKeywordList = function() {
+ if (!this.$highlightRules) this.getTokenizer();
+ return (this.$keywordList = this.$highlightRules.$keywordList || []);
+ };
+
+ this.getCompletions = function(state, session, pos, prefix) {
+ var keywords = this.$keywordList || this.$createKeywordList();
+ return keywords.map(function(word) {
+ return {
+ name: word,
+ value: word,
+ score: 0,
+ meta: "keyword"
+ };
+ });
+ };
+
+ this.$id = "ace/mode/text";
+ }.call(Mode.prototype));
+
+ exports.Mode = Mode;
+ }
+);
+
+ace.define("ace/apply_delta", ["require", "exports", "module"], function(
+ require,
+ exports,
+ module
+) {
+ "use strict";
+
+ function throwDeltaError(delta, errorText) {
+ console.log("Invalid Delta:", delta);
+ throw "Invalid Delta: " + errorText;
+ }
+
+ function positionInDocument(docLines, position) {
+ return (
+ position.row >= 0 &&
+ position.row < docLines.length &&
+ position.column >= 0 &&
+ position.column <= docLines[position.row].length
+ );
+ }
+
+ function validateDelta(docLines, delta) {
+ if (delta.action != "insert" && delta.action != "remove")
+ throwDeltaError(delta, "delta.action must be 'insert' or 'remove'");
+ if (!(delta.lines instanceof Array))
+ throwDeltaError(delta, "delta.lines must be an Array");
+ if (!delta.start || !delta.end)
+ throwDeltaError(delta, "delta.start/end must be an present");
+ var start = delta.start;
+ if (!positionInDocument(docLines, delta.start))
+ throwDeltaError(delta, "delta.start must be contained in document");
+ var end = delta.end;
+ if (delta.action == "remove" && !positionInDocument(docLines, end))
+ throwDeltaError(
+ delta,
+ "delta.end must contained in document for 'remove' actions"
+ );
+ var numRangeRows = end.row - start.row;
+ var numRangeLastLineChars =
+ end.column - (numRangeRows == 0 ? start.column : 0);
+ if (
+ numRangeRows != delta.lines.length - 1 ||
+ delta.lines[numRangeRows].length != numRangeLastLineChars
+ )
+ throwDeltaError(delta, "delta.range must match delta lines");
+ }
+
+ exports.applyDelta = function(docLines, delta, doNotValidate) {
+ var row = delta.start.row;
+ var startColumn = delta.start.column;
+ var line = docLines[row] || "";
+ switch (delta.action) {
+ case "insert":
+ var lines = delta.lines;
+ if (lines.length === 1) {
+ docLines[row] =
+ line.substring(0, startColumn) +
+ delta.lines[0] +
+ line.substring(startColumn);
+ } else {
+ var args = [row, 1].concat(delta.lines);
+ docLines.splice.apply(docLines, args);
+ docLines[row] = line.substring(0, startColumn) + docLines[row];
+ docLines[row + delta.lines.length - 1] += line.substring(startColumn);
+ }
+ break;
+ case "remove":
+ var endColumn = delta.end.column;
+ var endRow = delta.end.row;
+ if (row === endRow) {
+ docLines[row] =
+ line.substring(0, startColumn) + line.substring(endColumn);
+ } else {
+ docLines.splice(
+ row,
+ endRow - row + 1,
+ line.substring(0, startColumn) +
+ docLines[endRow].substring(endColumn)
+ );
+ }
+ break;
+ }
+ };
+});
+
+ace.define(
+ "ace/anchor",
+ ["require", "exports", "module", "ace/lib/oop", "ace/lib/event_emitter"],
+ function(require, exports, module) {
+ "use strict";
+
+ var oop = require("./lib/oop");
+ var EventEmitter = require("./lib/event_emitter").EventEmitter;
+
+ var Anchor = (exports.Anchor = function(doc, row, column) {
+ this.$onChange = this.onChange.bind(this);
+ this.attach(doc);
+
+ if (typeof column == "undefined") this.setPosition(row.row, row.column);
+ else this.setPosition(row, column);
+ });
+
+ (function() {
+ oop.implement(this, EventEmitter);
+ this.getPosition = function() {
+ return this.$clipPositionToDocument(this.row, this.column);
+ };
+ this.getDocument = function() {
+ return this.document;
+ };
+ this.$insertRight = false;
+ this.onChange = function(delta) {
+ if (delta.start.row == delta.end.row && delta.start.row != this.row)
+ return;
+
+ if (delta.start.row > this.row) return;
+
+ var point = $getTransformedPoint(
+ delta,
+ { row: this.row, column: this.column },
+ this.$insertRight
+ );
+ this.setPosition(point.row, point.column, true);
+ };
+
+ function $pointsInOrder(point1, point2, equalPointsInOrder) {
+ var bColIsAfter = equalPointsInOrder
+ ? point1.column <= point2.column
+ : point1.column < point2.column;
+ return (
+ point1.row < point2.row || (point1.row == point2.row && bColIsAfter)
+ );
+ }
+
+ function $getTransformedPoint(delta, point, moveIfEqual) {
+ var deltaIsInsert = delta.action == "insert";
+ var deltaRowShift =
+ (deltaIsInsert ? 1 : -1) * (delta.end.row - delta.start.row);
+ var deltaColShift =
+ (deltaIsInsert ? 1 : -1) * (delta.end.column - delta.start.column);
+ var deltaStart = delta.start;
+ var deltaEnd = deltaIsInsert ? deltaStart : delta.end; // Collapse insert range.
+ if ($pointsInOrder(point, deltaStart, moveIfEqual)) {
+ return {
+ row: point.row,
+ column: point.column
+ };
+ }
+ if ($pointsInOrder(deltaEnd, point, !moveIfEqual)) {
+ return {
+ row: point.row + deltaRowShift,
+ column:
+ point.column + (point.row == deltaEnd.row ? deltaColShift : 0)
+ };
+ }
+
+ return {
+ row: deltaStart.row,
+ column: deltaStart.column
+ };
+ }
+ this.setPosition = function(row, column, noClip) {
+ var pos;
+ if (noClip) {
+ pos = {
+ row: row,
+ column: column
+ };
+ } else {
+ pos = this.$clipPositionToDocument(row, column);
+ }
+
+ if (this.row == pos.row && this.column == pos.column) return;
+
+ var old = {
+ row: this.row,
+ column: this.column
+ };
+
+ this.row = pos.row;
+ this.column = pos.column;
+ this._signal("change", {
+ old: old,
+ value: pos
+ });
+ };
+ this.detach = function() {
+ this.document.off("change", this.$onChange);
+ };
+ this.attach = function(doc) {
+ this.document = doc || this.document;
+ this.document.on("change", this.$onChange);
+ };
+ this.$clipPositionToDocument = function(row, column) {
+ var pos = {};
+
+ if (row >= this.document.getLength()) {
+ pos.row = Math.max(0, this.document.getLength() - 1);
+ pos.column = this.document.getLine(pos.row).length;
+ } else if (row < 0) {
+ pos.row = 0;
+ pos.column = 0;
+ } else {
+ pos.row = row;
+ pos.column = Math.min(
+ this.document.getLine(pos.row).length,
+ Math.max(0, column)
+ );
+ }
+
+ if (column < 0) pos.column = 0;
+
+ return pos;
+ };
+ }.call(Anchor.prototype));
+ }
+);
+
+ace.define(
+ "ace/document",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/lib/oop",
+ "ace/apply_delta",
+ "ace/lib/event_emitter",
+ "ace/range",
+ "ace/anchor"
+ ],
+ function(require, exports, module) {
+ "use strict";
+
+ var oop = require("./lib/oop");
+ var applyDelta = require("./apply_delta").applyDelta;
+ var EventEmitter = require("./lib/event_emitter").EventEmitter;
+ var Range = require("./range").Range;
+ var Anchor = require("./anchor").Anchor;
+
+ var Document = function(textOrLines) {
+ this.$lines = [""];
+ if (textOrLines.length === 0) {
+ this.$lines = [""];
+ } else if (Array.isArray(textOrLines)) {
+ this.insertMergedLines({ row: 0, column: 0 }, textOrLines);
+ } else {
+ this.insert({ row: 0, column: 0 }, textOrLines);
+ }
+ };
+
+ (function() {
+ oop.implement(this, EventEmitter);
+ this.setValue = function(text) {
+ var len = this.getLength() - 1;
+ this.remove(new Range(0, 0, len, this.getLine(len).length));
+ this.insert({ row: 0, column: 0 }, text);
+ };
+ this.getValue = function() {
+ return this.getAllLines().join(this.getNewLineCharacter());
+ };
+ this.createAnchor = function(row, column) {
+ return new Anchor(this, row, column);
+ };
+ if ("aaa".split(/a/).length === 0) {
+ this.$split = function(text) {
+ return text.replace(/\r\n|\r/g, "\n").split("\n");
+ };
+ } else {
+ this.$split = function(text) {
+ return text.split(/\r\n|\r|\n/);
+ };
+ }
+
+ this.$detectNewLine = function(text) {
+ var match = text.match(/^.*?(\r\n|\r|\n)/m);
+ this.$autoNewLine = match ? match[1] : "\n";
+ this._signal("changeNewLineMode");
+ };
+ this.getNewLineCharacter = function() {
+ switch (this.$newLineMode) {
+ case "windows":
+ return "\r\n";
+ case "unix":
+ return "\n";
+ default:
+ return this.$autoNewLine || "\n";
+ }
+ };
+
+ this.$autoNewLine = "";
+ this.$newLineMode = "auto";
+ this.setNewLineMode = function(newLineMode) {
+ if (this.$newLineMode === newLineMode) return;
+
+ this.$newLineMode = newLineMode;
+ this._signal("changeNewLineMode");
+ };
+ this.getNewLineMode = function() {
+ return this.$newLineMode;
+ };
+ this.isNewLine = function(text) {
+ return text == "\r\n" || text == "\r" || text == "\n";
+ };
+ this.getLine = function(row) {
+ return this.$lines[row] || "";
+ };
+ this.getLines = function(firstRow, lastRow) {
+ return this.$lines.slice(firstRow, lastRow + 1);
+ };
+ this.getAllLines = function() {
+ return this.getLines(0, this.getLength());
+ };
+ this.getLength = function() {
+ return this.$lines.length;
+ };
+ this.getTextRange = function(range) {
+ return this.getLinesForRange(range).join(this.getNewLineCharacter());
+ };
+ this.getLinesForRange = function(range) {
+ var lines;
+ if (range.start.row === range.end.row) {
+ lines = [
+ this.getLine(range.start.row).substring(
+ range.start.column,
+ range.end.column
+ )
+ ];
+ } else {
+ lines = this.getLines(range.start.row, range.end.row);
+ lines[0] = (lines[0] || "").substring(range.start.column);
+ var l = lines.length - 1;
+ if (range.end.row - range.start.row == l)
+ lines[l] = lines[l].substring(0, range.end.column);
+ }
+ return lines;
+ };
+ this.insertLines = function(row, lines) {
+ console.warn(
+ "Use of document.insertLines is deprecated. Use the insertFullLines method instead."
+ );
+ return this.insertFullLines(row, lines);
+ };
+ this.removeLines = function(firstRow, lastRow) {
+ console.warn(
+ "Use of document.removeLines is deprecated. Use the removeFullLines method instead."
+ );
+ return this.removeFullLines(firstRow, lastRow);
+ };
+ this.insertNewLine = function(position) {
+ console.warn(
+ "Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead."
+ );
+ return this.insertMergedLines(position, ["", ""]);
+ };
+ this.insert = function(position, text) {
+ if (this.getLength() <= 1) this.$detectNewLine(text);
+
+ return this.insertMergedLines(position, this.$split(text));
+ };
+ this.insertInLine = function(position, text) {
+ var start = this.clippedPos(position.row, position.column);
+ var end = this.pos(position.row, position.column + text.length);
+
+ this.applyDelta(
+ {
+ start: start,
+ end: end,
+ action: "insert",
+ lines: [text]
+ },
+ true
+ );
+
+ return this.clonePos(end);
+ };
+
+ this.clippedPos = function(row, column) {
+ var length = this.getLength();
+ if (row === undefined) {
+ row = length;
+ } else if (row < 0) {
+ row = 0;
+ } else if (row >= length) {
+ row = length - 1;
+ column = undefined;
+ }
+ var line = this.getLine(row);
+ if (column == undefined) column = line.length;
+ column = Math.min(Math.max(column, 0), line.length);
+ return { row: row, column: column };
+ };
+
+ this.clonePos = function(pos) {
+ return { row: pos.row, column: pos.column };
+ };
+
+ this.pos = function(row, column) {
+ return { row: row, column: column };
+ };
+
+ this.$clipPosition = function(position) {
+ var length = this.getLength();
+ if (position.row >= length) {
+ position.row = Math.max(0, length - 1);
+ position.column = this.getLine(length - 1).length;
+ } else {
+ position.row = Math.max(0, position.row);
+ position.column = Math.min(
+ Math.max(position.column, 0),
+ this.getLine(position.row).length
+ );
+ }
+ return position;
+ };
+ this.insertFullLines = function(row, lines) {
+ row = Math.min(Math.max(row, 0), this.getLength());
+ var column = 0;
+ if (row < this.getLength()) {
+ lines = lines.concat([""]);
+ column = 0;
+ } else {
+ lines = [""].concat(lines);
+ row--;
+ column = this.$lines[row].length;
+ }
+ this.insertMergedLines({ row: row, column: column }, lines);
+ };
+ this.insertMergedLines = function(position, lines) {
+ var start = this.clippedPos(position.row, position.column);
+ var end = {
+ row: start.row + lines.length - 1,
+ column:
+ (lines.length == 1 ? start.column : 0) +
+ lines[lines.length - 1].length
+ };
+
+ this.applyDelta({
+ start: start,
+ end: end,
+ action: "insert",
+ lines: lines
+ });
+
+ return this.clonePos(end);
+ };
+ this.remove = function(range) {
+ var start = this.clippedPos(range.start.row, range.start.column);
+ var end = this.clippedPos(range.end.row, range.end.column);
+ this.applyDelta({
+ start: start,
+ end: end,
+ action: "remove",
+ lines: this.getLinesForRange({ start: start, end: end })
+ });
+ return this.clonePos(start);
+ };
+ this.removeInLine = function(row, startColumn, endColumn) {
+ var start = this.clippedPos(row, startColumn);
+ var end = this.clippedPos(row, endColumn);
+
+ this.applyDelta(
+ {
+ start: start,
+ end: end,
+ action: "remove",
+ lines: this.getLinesForRange({ start: start, end: end })
+ },
+ true
+ );
+
+ return this.clonePos(start);
+ };
+ this.removeFullLines = function(firstRow, lastRow) {
+ firstRow = Math.min(Math.max(0, firstRow), this.getLength() - 1);
+ lastRow = Math.min(Math.max(0, lastRow), this.getLength() - 1);
+ var deleteFirstNewLine =
+ lastRow == this.getLength() - 1 && firstRow > 0;
+ var deleteLastNewLine = lastRow < this.getLength() - 1;
+ var startRow = deleteFirstNewLine ? firstRow - 1 : firstRow;
+ var startCol = deleteFirstNewLine ? this.getLine(startRow).length : 0;
+ var endRow = deleteLastNewLine ? lastRow + 1 : lastRow;
+ var endCol = deleteLastNewLine ? 0 : this.getLine(endRow).length;
+ var range = new Range(startRow, startCol, endRow, endCol);
+ var deletedLines = this.$lines.slice(firstRow, lastRow + 1);
+
+ this.applyDelta({
+ start: range.start,
+ end: range.end,
+ action: "remove",
+ lines: this.getLinesForRange(range)
+ });
+ return deletedLines;
+ };
+ this.removeNewLine = function(row) {
+ if (row < this.getLength() - 1 && row >= 0) {
+ this.applyDelta({
+ start: this.pos(row, this.getLine(row).length),
+ end: this.pos(row + 1, 0),
+ action: "remove",
+ lines: ["", ""]
+ });
+ }
+ };
+ this.replace = function(range, text) {
+ if (!(range instanceof Range))
+ range = Range.fromPoints(range.start, range.end);
+ if (text.length === 0 && range.isEmpty()) return range.start;
+ if (text == this.getTextRange(range)) return range.end;
+
+ this.remove(range);
+ var end;
+ if (text) {
+ end = this.insert(range.start, text);
+ } else {
+ end = range.start;
+ }
+
+ return end;
+ };
+ this.applyDeltas = function(deltas) {
+ for (var i = 0; i < deltas.length; i++) {
+ this.applyDelta(deltas[i]);
+ }
+ };
+ this.revertDeltas = function(deltas) {
+ for (var i = deltas.length - 1; i >= 0; i--) {
+ this.revertDelta(deltas[i]);
+ }
+ };
+ this.applyDelta = function(delta, doNotValidate) {
+ var isInsert = delta.action == "insert";
+ if (
+ isInsert
+ ? delta.lines.length <= 1 && !delta.lines[0]
+ : !Range.comparePoints(delta.start, delta.end)
+ ) {
+ return;
+ }
+
+ if (isInsert && delta.lines.length > 20000) {
+ this.$splitAndapplyLargeDelta(delta, 20000);
+ } else {
+ applyDelta(this.$lines, delta, doNotValidate);
+ this._signal("change", delta);
+ }
+ };
+
+ this.$safeApplyDelta = function(delta) {
+ var docLength = this.$lines.length;
+ if (
+ (delta.action == "remove" &&
+ delta.start.row < docLength &&
+ delta.end.row < docLength) ||
+ (delta.action == "insert" && delta.start.row <= docLength)
+ ) {
+ this.applyDelta(delta);
+ }
+ };
+
+ this.$splitAndapplyLargeDelta = function(delta, MAX) {
+ var lines = delta.lines;
+ var l = lines.length - MAX + 1;
+ var row = delta.start.row;
+ var column = delta.start.column;
+ for (var from = 0, to = 0; from < l; from = to) {
+ to += MAX - 1;
+ var chunk = lines.slice(from, to);
+ chunk.push("");
+ this.applyDelta(
+ {
+ start: this.pos(row + from, column),
+ end: this.pos(row + to, (column = 0)),
+ action: delta.action,
+ lines: chunk
+ },
+ true
+ );
+ }
+ delta.lines = lines.slice(from);
+ delta.start.row = row + from;
+ delta.start.column = column;
+ this.applyDelta(delta, true);
+ };
+ this.revertDelta = function(delta) {
+ this.$safeApplyDelta({
+ start: this.clonePos(delta.start),
+ end: this.clonePos(delta.end),
+ action: delta.action == "insert" ? "remove" : "insert",
+ lines: delta.lines.slice()
+ });
+ };
+ this.indexToPosition = function(index, startRow) {
+ var lines = this.$lines || this.getAllLines();
+ var newlineLength = this.getNewLineCharacter().length;
+ for (var i = startRow || 0, l = lines.length; i < l; i++) {
+ index -= lines[i].length + newlineLength;
+ if (index < 0)
+ return { row: i, column: index + lines[i].length + newlineLength };
+ }
+ return {
+ row: l - 1,
+ column: index + lines[l - 1].length + newlineLength
+ };
+ };
+ this.positionToIndex = function(pos, startRow) {
+ var lines = this.$lines || this.getAllLines();
+ var newlineLength = this.getNewLineCharacter().length;
+ var index = 0;
+ var row = Math.min(pos.row, lines.length);
+ for (var i = startRow || 0; i < row; ++i)
+ index += lines[i].length + newlineLength;
+
+ return index + pos.column;
+ };
+ }.call(Document.prototype));
+
+ exports.Document = Document;
+ }
+);
+
+ace.define(
+ "ace/background_tokenizer",
+ ["require", "exports", "module", "ace/lib/oop", "ace/lib/event_emitter"],
+ function(require, exports, module) {
+ "use strict";
+
+ var oop = require("./lib/oop");
+ var EventEmitter = require("./lib/event_emitter").EventEmitter;
+
+ var BackgroundTokenizer = function(tokenizer, editor) {
+ this.running = false;
+ this.lines = [];
+ this.states = [];
+ this.currentLine = 0;
+ this.tokenizer = tokenizer;
+
+ var self = this;
+
+ this.$worker = function() {
+ if (!self.running) {
+ return;
+ }
+
+ var workerStart = new Date();
+ var currentLine = self.currentLine;
+ var endLine = -1;
+ var doc = self.doc;
+
+ var startLine = currentLine;
+ while (self.lines[currentLine]) currentLine++;
+
+ var len = doc.getLength();
+ var processedLines = 0;
+ self.running = false;
+ while (currentLine < len) {
+ self.$tokenizeRow(currentLine);
+ endLine = currentLine;
+ do {
+ currentLine++;
+ } while (self.lines[currentLine]);
+ processedLines++;
+ if (processedLines % 5 === 0 && new Date() - workerStart > 20) {
+ self.running = setTimeout(self.$worker, 20);
+ break;
+ }
+ }
+ self.currentLine = currentLine;
+
+ if (endLine == -1) endLine = currentLine;
+
+ if (startLine <= endLine) self.fireUpdateEvent(startLine, endLine);
+ };
+ };
+
+ (function() {
+ oop.implement(this, EventEmitter);
+ this.setTokenizer = function(tokenizer) {
+ this.tokenizer = tokenizer;
+ this.lines = [];
+ this.states = [];
+
+ this.start(0);
+ };
+ this.setDocument = function(doc) {
+ this.doc = doc;
+ this.lines = [];
+ this.states = [];
+
+ this.stop();
+ };
+ this.fireUpdateEvent = function(firstRow, lastRow) {
+ var data = {
+ first: firstRow,
+ last: lastRow
+ };
+ this._signal("update", { data: data });
+ };
+ this.start = function(startRow) {
+ this.currentLine = Math.min(
+ startRow || 0,
+ this.currentLine,
+ this.doc.getLength()
+ );
+ this.lines.splice(this.currentLine, this.lines.length);
+ this.states.splice(this.currentLine, this.states.length);
+
+ this.stop();
+ this.running = setTimeout(this.$worker, 700);
+ };
+
+ this.scheduleStart = function() {
+ if (!this.running) this.running = setTimeout(this.$worker, 700);
+ };
+
+ this.$updateOnChange = function(delta) {
+ var startRow = delta.start.row;
+ var len = delta.end.row - startRow;
+
+ if (len === 0) {
+ this.lines[startRow] = null;
+ } else if (delta.action == "remove") {
+ this.lines.splice(startRow, len + 1, null);
+ this.states.splice(startRow, len + 1, null);
+ } else {
+ var args = Array(len + 1);
+ args.unshift(startRow, 1);
+ this.lines.splice.apply(this.lines, args);
+ this.states.splice.apply(this.states, args);
+ }
+
+ this.currentLine = Math.min(
+ startRow,
+ this.currentLine,
+ this.doc.getLength()
+ );
+
+ this.stop();
+ };
+ this.stop = function() {
+ if (this.running) clearTimeout(this.running);
+ this.running = false;
+ };
+ this.getTokens = function(row) {
+ return this.lines[row] || this.$tokenizeRow(row);
+ };
+ this.getState = function(row) {
+ if (this.currentLine == row) this.$tokenizeRow(row);
+ return this.states[row] || "start";
+ };
+
+ this.$tokenizeRow = function(row) {
+ var line = this.doc.getLine(row);
+ var state = this.states[row - 1];
+
+ var data = this.tokenizer.getLineTokens(line, state, row);
+
+ if (this.states[row] + "" !== data.state + "") {
+ this.states[row] = data.state;
+ this.lines[row + 1] = null;
+ if (this.currentLine > row + 1) this.currentLine = row + 1;
+ } else if (this.currentLine == row) {
+ this.currentLine = row + 1;
+ }
+
+ return (this.lines[row] = data.tokens);
+ };
+ }.call(BackgroundTokenizer.prototype));
+
+ exports.BackgroundTokenizer = BackgroundTokenizer;
+ }
+);
+
+ace.define(
+ "ace/search_highlight",
+ ["require", "exports", "module", "ace/lib/lang", "ace/lib/oop", "ace/range"],
+ function(require, exports, module) {
+ "use strict";
+
+ var lang = require("./lib/lang");
+ var oop = require("./lib/oop");
+ var Range = require("./range").Range;
+
+ var SearchHighlight = function(regExp, clazz, type) {
+ this.setRegexp(regExp);
+ this.clazz = clazz;
+ this.type = type || "text";
+ };
+
+ (function() {
+ this.MAX_RANGES = 500;
+
+ this.setRegexp = function(regExp) {
+ if (this.regExp + "" == regExp + "") return;
+ this.regExp = regExp;
+ this.cache = [];
+ };
+
+ this.update = function(html, markerLayer, session, config) {
+ if (!this.regExp) return;
+ var start = config.firstRow,
+ end = config.lastRow;
+
+ for (var i = start; i <= end; i++) {
+ var ranges = this.cache[i];
+ if (ranges == null) {
+ ranges = lang.getMatchOffsets(session.getLine(i), this.regExp);
+ if (ranges.length > this.MAX_RANGES)
+ ranges = ranges.slice(0, this.MAX_RANGES);
+ ranges = ranges.map(function(match) {
+ return new Range(i, match.offset, i, match.offset + match.length);
+ });
+ this.cache[i] = ranges.length ? ranges : "";
+ }
+
+ for (var j = ranges.length; j--; ) {
+ markerLayer.drawSingleLineMarker(
+ html,
+ ranges[j].toScreenRange(session),
+ this.clazz,
+ config
+ );
+ }
+ }
+ };
+ }.call(SearchHighlight.prototype));
+
+ exports.SearchHighlight = SearchHighlight;
+ }
+);
+
+ace.define(
+ "ace/edit_session/fold_line",
+ ["require", "exports", "module", "ace/range"],
+ function(require, exports, module) {
+ "use strict";
+
+ var Range = require("../range").Range;
+ function FoldLine(foldData, folds) {
+ this.foldData = foldData;
+ if (Array.isArray(folds)) {
+ this.folds = folds;
+ } else {
+ folds = this.folds = [folds];
+ }
+
+ var last = folds[folds.length - 1];
+ this.range = new Range(
+ folds[0].start.row,
+ folds[0].start.column,
+ last.end.row,
+ last.end.column
+ );
+ this.start = this.range.start;
+ this.end = this.range.end;
+
+ this.folds.forEach(function(fold) {
+ fold.setFoldLine(this);
+ }, this);
+ }
+
+ (function() {
+ this.shiftRow = function(shift) {
+ this.start.row += shift;
+ this.end.row += shift;
+ this.folds.forEach(function(fold) {
+ fold.start.row += shift;
+ fold.end.row += shift;
+ });
+ };
+
+ this.addFold = function(fold) {
+ if (fold.sameRow) {
+ if (fold.start.row < this.startRow || fold.endRow > this.endRow) {
+ throw new Error(
+ "Can't add a fold to this FoldLine as it has no connection"
+ );
+ }
+ this.folds.push(fold);
+ this.folds.sort(function(a, b) {
+ return -a.range.compareEnd(b.start.row, b.start.column);
+ });
+ if (this.range.compareEnd(fold.start.row, fold.start.column) > 0) {
+ this.end.row = fold.end.row;
+ this.end.column = fold.end.column;
+ } else if (
+ this.range.compareStart(fold.end.row, fold.end.column) < 0
+ ) {
+ this.start.row = fold.start.row;
+ this.start.column = fold.start.column;
+ }
+ } else if (fold.start.row == this.end.row) {
+ this.folds.push(fold);
+ this.end.row = fold.end.row;
+ this.end.column = fold.end.column;
+ } else if (fold.end.row == this.start.row) {
+ this.folds.unshift(fold);
+ this.start.row = fold.start.row;
+ this.start.column = fold.start.column;
+ } else {
+ throw new Error(
+ "Trying to add fold to FoldRow that doesn't have a matching row"
+ );
+ }
+ fold.foldLine = this;
+ };
+
+ this.containsRow = function(row) {
+ return row >= this.start.row && row <= this.end.row;
+ };
+
+ this.walk = function(callback, endRow, endColumn) {
+ var lastEnd = 0,
+ folds = this.folds,
+ fold,
+ cmp,
+ stop,
+ isNewRow = true;
+
+ if (endRow == null) {
+ endRow = this.end.row;
+ endColumn = this.end.column;
+ }
+
+ for (var i = 0; i < folds.length; i++) {
+ fold = folds[i];
+
+ cmp = fold.range.compareStart(endRow, endColumn);
+ if (cmp == -1) {
+ callback(null, endRow, endColumn, lastEnd, isNewRow);
+ return;
+ }
+
+ stop = callback(
+ null,
+ fold.start.row,
+ fold.start.column,
+ lastEnd,
+ isNewRow
+ );
+ stop =
+ !stop &&
+ callback(
+ fold.placeholder,
+ fold.start.row,
+ fold.start.column,
+ lastEnd
+ );
+ if (stop || cmp === 0) {
+ return;
+ }
+ isNewRow = !fold.sameRow;
+ lastEnd = fold.end.column;
+ }
+ callback(null, endRow, endColumn, lastEnd, isNewRow);
+ };
+
+ this.getNextFoldTo = function(row, column) {
+ var fold, cmp;
+ for (var i = 0; i < this.folds.length; i++) {
+ fold = this.folds[i];
+ cmp = fold.range.compareEnd(row, column);
+ if (cmp == -1) {
+ return {
+ fold: fold,
+ kind: "after"
+ };
+ } else if (cmp === 0) {
+ return {
+ fold: fold,
+ kind: "inside"
+ };
+ }
+ }
+ return null;
+ };
+
+ this.addRemoveChars = function(row, column, len) {
+ var ret = this.getNextFoldTo(row, column),
+ fold,
+ folds;
+ if (ret) {
+ fold = ret.fold;
+ if (
+ ret.kind == "inside" &&
+ fold.start.column != column &&
+ fold.start.row != row
+ ) {
+ window.console && window.console.log(row, column, fold);
+ } else if (fold.start.row == row) {
+ folds = this.folds;
+ var i = folds.indexOf(fold);
+ if (i === 0) {
+ this.start.column += len;
+ }
+ for (i; i < folds.length; i++) {
+ fold = folds[i];
+ fold.start.column += len;
+ if (!fold.sameRow) {
+ return;
+ }
+ fold.end.column += len;
+ }
+ this.end.column += len;
+ }
+ }
+ };
+
+ this.split = function(row, column) {
+ var pos = this.getNextFoldTo(row, column);
+
+ if (!pos || pos.kind == "inside") return null;
+
+ var fold = pos.fold;
+ var folds = this.folds;
+ var foldData = this.foldData;
+
+ var i = folds.indexOf(fold);
+ var foldBefore = folds[i - 1];
+ this.end.row = foldBefore.end.row;
+ this.end.column = foldBefore.end.column;
+ folds = folds.splice(i, folds.length - i);
+
+ var newFoldLine = new FoldLine(foldData, folds);
+ foldData.splice(foldData.indexOf(this) + 1, 0, newFoldLine);
+ return newFoldLine;
+ };
+
+ this.merge = function(foldLineNext) {
+ var folds = foldLineNext.folds;
+ for (var i = 0; i < folds.length; i++) {
+ this.addFold(folds[i]);
+ }
+ var foldData = this.foldData;
+ foldData.splice(foldData.indexOf(foldLineNext), 1);
+ };
+
+ this.toString = function() {
+ var ret = [this.range.toString() + ": ["];
+
+ this.folds.forEach(function(fold) {
+ ret.push(" " + fold.toString());
+ });
+ ret.push("]");
+ return ret.join("\n");
+ };
+
+ this.idxToPosition = function(idx) {
+ var lastFoldEndColumn = 0;
+
+ for (var i = 0; i < this.folds.length; i++) {
+ var fold = this.folds[i];
+
+ idx -= fold.start.column - lastFoldEndColumn;
+ if (idx < 0) {
+ return {
+ row: fold.start.row,
+ column: fold.start.column + idx
+ };
+ }
+
+ idx -= fold.placeholder.length;
+ if (idx < 0) {
+ return fold.start;
+ }
+
+ lastFoldEndColumn = fold.end.column;
+ }
+
+ return {
+ row: this.end.row,
+ column: this.end.column + idx
+ };
+ };
+ }.call(FoldLine.prototype));
+
+ exports.FoldLine = FoldLine;
+ }
+);
+
+ace.define(
+ "ace/range_list",
+ ["require", "exports", "module", "ace/range"],
+ function(require, exports, module) {
+ "use strict";
+ var Range = require("./range").Range;
+ var comparePoints = Range.comparePoints;
+
+ var RangeList = function() {
+ this.ranges = [];
+ this.$bias = 1;
+ };
+
+ (function() {
+ this.comparePoints = comparePoints;
+
+ this.pointIndex = function(pos, excludeEdges, startIndex) {
+ var list = this.ranges;
+
+ for (var i = startIndex || 0; i < list.length; i++) {
+ var range = list[i];
+ var cmpEnd = comparePoints(pos, range.end);
+ if (cmpEnd > 0) continue;
+ var cmpStart = comparePoints(pos, range.start);
+ if (cmpEnd === 0) return excludeEdges && cmpStart !== 0 ? -i - 2 : i;
+ if (cmpStart > 0 || (cmpStart === 0 && !excludeEdges)) return i;
+
+ return -i - 1;
+ }
+ return -i - 1;
+ };
+
+ this.add = function(range) {
+ var excludeEdges = !range.isEmpty();
+ var startIndex = this.pointIndex(range.start, excludeEdges);
+ if (startIndex < 0) startIndex = -startIndex - 1;
+
+ var endIndex = this.pointIndex(range.end, excludeEdges, startIndex);
+
+ if (endIndex < 0) endIndex = -endIndex - 1;
+ else endIndex++;
+ return this.ranges.splice(startIndex, endIndex - startIndex, range);
+ };
+
+ this.addList = function(list) {
+ var removed = [];
+ for (var i = list.length; i--; ) {
+ removed.push.apply(removed, this.add(list[i]));
+ }
+ return removed;
+ };
+
+ this.substractPoint = function(pos) {
+ var i = this.pointIndex(pos);
+
+ if (i >= 0) return this.ranges.splice(i, 1);
+ };
+ this.merge = function() {
+ var removed = [];
+ var list = this.ranges;
+
+ list = list.sort(function(a, b) {
+ return comparePoints(a.start, b.start);
+ });
+
+ var next = list[0],
+ range;
+ for (var i = 1; i < list.length; i++) {
+ range = next;
+ next = list[i];
+ var cmp = comparePoints(range.end, next.start);
+ if (cmp < 0) continue;
+
+ if (cmp == 0 && !range.isEmpty() && !next.isEmpty()) continue;
+
+ if (comparePoints(range.end, next.end) < 0) {
+ range.end.row = next.end.row;
+ range.end.column = next.end.column;
+ }
+
+ list.splice(i, 1);
+ removed.push(next);
+ next = range;
+ i--;
+ }
+
+ this.ranges = list;
+
+ return removed;
+ };
+
+ this.contains = function(row, column) {
+ return this.pointIndex({ row: row, column: column }) >= 0;
+ };
+
+ this.containsPoint = function(pos) {
+ return this.pointIndex(pos) >= 0;
+ };
+
+ this.rangeAtPoint = function(pos) {
+ var i = this.pointIndex(pos);
+ if (i >= 0) return this.ranges[i];
+ };
+
+ this.clipRows = function(startRow, endRow) {
+ var list = this.ranges;
+ if (
+ list[0].start.row > endRow ||
+ list[list.length - 1].start.row < startRow
+ )
+ return [];
+
+ var startIndex = this.pointIndex({ row: startRow, column: 0 });
+ if (startIndex < 0) startIndex = -startIndex - 1;
+ var endIndex = this.pointIndex({ row: endRow, column: 0 }, startIndex);
+ if (endIndex < 0) endIndex = -endIndex - 1;
+
+ var clipped = [];
+ for (var i = startIndex; i < endIndex; i++) {
+ clipped.push(list[i]);
+ }
+ return clipped;
+ };
+
+ this.removeAll = function() {
+ return this.ranges.splice(0, this.ranges.length);
+ };
+
+ this.attach = function(session) {
+ if (this.session) this.detach();
+
+ this.session = session;
+ this.onChange = this.$onChange.bind(this);
+
+ this.session.on("change", this.onChange);
+ };
+
+ this.detach = function() {
+ if (!this.session) return;
+ this.session.removeListener("change", this.onChange);
+ this.session = null;
+ };
+
+ this.$onChange = function(delta) {
+ var start = delta.start;
+ var end = delta.end;
+ var startRow = start.row;
+ var endRow = end.row;
+ var ranges = this.ranges;
+ for (var i = 0, n = ranges.length; i < n; i++) {
+ var r = ranges[i];
+ if (r.end.row >= startRow) break;
+ }
+
+ if (delta.action == "insert") {
+ var lineDif = endRow - startRow;
+ var colDiff = -start.column + end.column;
+ for (; i < n; i++) {
+ var r = ranges[i];
+ if (r.start.row > startRow) break;
+
+ if (r.start.row == startRow && r.start.column >= start.column) {
+ if (r.start.column == start.column && this.$bias <= 0) {
+ } else {
+ r.start.column += colDiff;
+ r.start.row += lineDif;
+ }
+ }
+ if (r.end.row == startRow && r.end.column >= start.column) {
+ if (r.end.column == start.column && this.$bias < 0) {
+ continue;
+ }
+ if (r.end.column == start.column && colDiff > 0 && i < n - 1) {
+ if (
+ r.end.column > r.start.column &&
+ r.end.column == ranges[i + 1].start.column
+ )
+ r.end.column -= colDiff;
+ }
+ r.end.column += colDiff;
+ r.end.row += lineDif;
+ }
+ }
+ } else {
+ var lineDif = startRow - endRow;
+ var colDiff = start.column - end.column;
+ for (; i < n; i++) {
+ var r = ranges[i];
+
+ if (r.start.row > endRow) break;
+
+ if (
+ r.end.row < endRow &&
+ (startRow < r.end.row ||
+ (startRow == r.end.row && start.column < r.end.column))
+ ) {
+ r.end.row = startRow;
+ r.end.column = start.column;
+ } else if (r.end.row == endRow) {
+ if (r.end.column <= end.column) {
+ if (lineDif || r.end.column > start.column) {
+ r.end.column = start.column;
+ r.end.row = start.row;
+ }
+ } else {
+ r.end.column += colDiff;
+ r.end.row += lineDif;
+ }
+ } else if (r.end.row > endRow) {
+ r.end.row += lineDif;
+ }
+
+ if (
+ r.start.row < endRow &&
+ (startRow < r.start.row ||
+ (startRow == r.start.row && start.column < r.start.column))
+ ) {
+ r.start.row = startRow;
+ r.start.column = start.column;
+ } else if (r.start.row == endRow) {
+ if (r.start.column <= end.column) {
+ if (lineDif || r.start.column > start.column) {
+ r.start.column = start.column;
+ r.start.row = start.row;
+ }
+ } else {
+ r.start.column += colDiff;
+ r.start.row += lineDif;
+ }
+ } else if (r.start.row > endRow) {
+ r.start.row += lineDif;
+ }
+ }
+ }
+
+ if (lineDif != 0 && i < n) {
+ for (; i < n; i++) {
+ var r = ranges[i];
+ r.start.row += lineDif;
+ r.end.row += lineDif;
+ }
+ }
+ };
+ }.call(RangeList.prototype));
+
+ exports.RangeList = RangeList;
+ }
+);
+
+ace.define(
+ "ace/edit_session/fold",
+ ["require", "exports", "module", "ace/range_list", "ace/lib/oop"],
+ function(require, exports, module) {
+ "use strict";
+
+ var RangeList = require("../range_list").RangeList;
+ var oop = require("../lib/oop");
+ var Fold = (exports.Fold = function(range, placeholder) {
+ this.foldLine = null;
+ this.placeholder = placeholder;
+ this.range = range;
+ this.start = range.start;
+ this.end = range.end;
+
+ this.sameRow = range.start.row == range.end.row;
+ this.subFolds = this.ranges = [];
+ });
+
+ oop.inherits(Fold, RangeList);
+
+ (function() {
+ this.toString = function() {
+ return '"' + this.placeholder + '" ' + this.range.toString();
+ };
+
+ this.setFoldLine = function(foldLine) {
+ this.foldLine = foldLine;
+ this.subFolds.forEach(function(fold) {
+ fold.setFoldLine(foldLine);
+ });
+ };
+
+ this.clone = function() {
+ var range = this.range.clone();
+ var fold = new Fold(range, this.placeholder);
+ this.subFolds.forEach(function(subFold) {
+ fold.subFolds.push(subFold.clone());
+ });
+ fold.collapseChildren = this.collapseChildren;
+ return fold;
+ };
+
+ this.addSubFold = function(fold) {
+ if (this.range.isEqual(fold)) return;
+ consumeRange(fold, this.start);
+
+ var row = fold.start.row,
+ column = fold.start.column;
+ for (var i = 0, cmp = -1; i < this.subFolds.length; i++) {
+ cmp = this.subFolds[i].range.compare(row, column);
+ if (cmp != 1) break;
+ }
+ var afterStart = this.subFolds[i];
+ var firstConsumed = 0;
+
+ if (cmp == 0) {
+ if (afterStart.range.containsRange(fold))
+ return afterStart.addSubFold(fold);
+ else firstConsumed = 1;
+ }
+ var row = fold.range.end.row,
+ column = fold.range.end.column;
+ for (var j = i, cmp = -1; j < this.subFolds.length; j++) {
+ cmp = this.subFolds[j].range.compare(row, column);
+ if (cmp != 1) break;
+ }
+ if (cmp == 0) j++;
+ var consumedFolds = this.subFolds.splice(i, j - i, fold);
+ var last = cmp == 0 ? consumedFolds.length - 1 : consumedFolds.length;
+ for (var k = firstConsumed; k < last; k++) {
+ fold.addSubFold(consumedFolds[k]);
+ }
+ fold.setFoldLine(this.foldLine);
+
+ return fold;
+ };
+
+ this.restoreRange = function(range) {
+ return restoreRange(range, this.start);
+ };
+ }.call(Fold.prototype));
+
+ function consumePoint(point, anchor) {
+ point.row -= anchor.row;
+ if (point.row == 0) point.column -= anchor.column;
+ }
+ function consumeRange(range, anchor) {
+ consumePoint(range.start, anchor);
+ consumePoint(range.end, anchor);
+ }
+ function restorePoint(point, anchor) {
+ if (point.row == 0) point.column += anchor.column;
+ point.row += anchor.row;
+ }
+ function restoreRange(range, anchor) {
+ restorePoint(range.start, anchor);
+ restorePoint(range.end, anchor);
+ }
+ }
+);
+
+ace.define(
+ "ace/edit_session/folding",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/range",
+ "ace/edit_session/fold_line",
+ "ace/edit_session/fold",
+ "ace/token_iterator"
+ ],
+ function(require, exports, module) {
+ "use strict";
+
+ var Range = require("../range").Range;
+ var FoldLine = require("./fold_line").FoldLine;
+ var Fold = require("./fold").Fold;
+ var TokenIterator = require("../token_iterator").TokenIterator;
+
+ function Folding() {
+ this.getFoldAt = function(row, column, side) {
+ var foldLine = this.getFoldLine(row);
+ if (!foldLine) return null;
+
+ var folds = foldLine.folds;
+ for (var i = 0; i < folds.length; i++) {
+ var range = folds[i].range;
+ if (range.contains(row, column)) {
+ if (side == 1 && range.isEnd(row, column) && !range.isEmpty()) {
+ continue;
+ } else if (
+ side == -1 &&
+ range.isStart(row, column) &&
+ !range.isEmpty()
+ ) {
+ continue;
+ }
+ return folds[i];
+ }
+ }
+ };
+ this.getFoldsInRange = function(range) {
+ var start = range.start;
+ var end = range.end;
+ var foldLines = this.$foldData;
+ var foundFolds = [];
+
+ start.column += 1;
+ end.column -= 1;
+
+ for (var i = 0; i < foldLines.length; i++) {
+ var cmp = foldLines[i].range.compareRange(range);
+ if (cmp == 2) {
+ continue;
+ } else if (cmp == -2) {
+ break;
+ }
+
+ var folds = foldLines[i].folds;
+ for (var j = 0; j < folds.length; j++) {
+ var fold = folds[j];
+ cmp = fold.range.compareRange(range);
+ if (cmp == -2) {
+ break;
+ } else if (cmp == 2) {
+ continue;
+ } else if (cmp == 42) {
+ break;
+ }
+ foundFolds.push(fold);
+ }
+ }
+ start.column -= 1;
+ end.column += 1;
+
+ return foundFolds;
+ };
+
+ this.getFoldsInRangeList = function(ranges) {
+ if (Array.isArray(ranges)) {
+ var folds = [];
+ ranges.forEach(function(range) {
+ folds = folds.concat(this.getFoldsInRange(range));
+ }, this);
+ } else {
+ var folds = this.getFoldsInRange(ranges);
+ }
+ return folds;
+ };
+ this.getAllFolds = function() {
+ var folds = [];
+ var foldLines = this.$foldData;
+
+ for (var i = 0; i < foldLines.length; i++)
+ for (var j = 0; j < foldLines[i].folds.length; j++)
+ folds.push(foldLines[i].folds[j]);
+
+ return folds;
+ };
+ this.getFoldStringAt = function(row, column, trim, foldLine) {
+ foldLine = foldLine || this.getFoldLine(row);
+ if (!foldLine) return null;
+
+ var lastFold = {
+ end: { column: 0 }
+ };
+ var str, fold;
+ for (var i = 0; i < foldLine.folds.length; i++) {
+ fold = foldLine.folds[i];
+ var cmp = fold.range.compareEnd(row, column);
+ if (cmp == -1) {
+ str = this.getLine(fold.start.row).substring(
+ lastFold.end.column,
+ fold.start.column
+ );
+ break;
+ } else if (cmp === 0) {
+ return null;
+ }
+ lastFold = fold;
+ }
+ if (!str)
+ str = this.getLine(fold.start.row).substring(lastFold.end.column);
+
+ if (trim == -1) return str.substring(0, column - lastFold.end.column);
+ else if (trim == 1) return str.substring(column - lastFold.end.column);
+ else return str;
+ };
+
+ this.getFoldLine = function(docRow, startFoldLine) {
+ var foldData = this.$foldData;
+ var i = 0;
+ if (startFoldLine) i = foldData.indexOf(startFoldLine);
+ if (i == -1) i = 0;
+ for (i; i < foldData.length; i++) {
+ var foldLine = foldData[i];
+ if (foldLine.start.row <= docRow && foldLine.end.row >= docRow) {
+ return foldLine;
+ } else if (foldLine.end.row > docRow) {
+ return null;
+ }
+ }
+ return null;
+ };
+ this.getNextFoldLine = function(docRow, startFoldLine) {
+ var foldData = this.$foldData;
+ var i = 0;
+ if (startFoldLine) i = foldData.indexOf(startFoldLine);
+ if (i == -1) i = 0;
+ for (i; i < foldData.length; i++) {
+ var foldLine = foldData[i];
+ if (foldLine.end.row >= docRow) {
+ return foldLine;
+ }
+ }
+ return null;
+ };
+
+ this.getFoldedRowCount = function(first, last) {
+ var foldData = this.$foldData,
+ rowCount = last - first + 1;
+ for (var i = 0; i < foldData.length; i++) {
+ var foldLine = foldData[i],
+ end = foldLine.end.row,
+ start = foldLine.start.row;
+ if (end >= last) {
+ if (start < last) {
+ if (start >= first) rowCount -= last - start;
+ else rowCount = 0; // in one fold
+ }
+ break;
+ } else if (end >= first) {
+ if (start >= first)
+ // fold inside range
+ rowCount -= end - start;
+ else rowCount -= end - first + 1;
+ }
+ }
+ return rowCount;
+ };
+
+ this.$addFoldLine = function(foldLine) {
+ this.$foldData.push(foldLine);
+ this.$foldData.sort(function(a, b) {
+ return a.start.row - b.start.row;
+ });
+ return foldLine;
+ };
+ this.addFold = function(placeholder, range) {
+ var foldData = this.$foldData;
+ var added = false;
+ var fold;
+
+ if (placeholder instanceof Fold) fold = placeholder;
+ else {
+ fold = new Fold(range, placeholder);
+ fold.collapseChildren = range.collapseChildren;
+ }
+ this.$clipRangeToDocument(fold.range);
+
+ var startRow = fold.start.row;
+ var startColumn = fold.start.column;
+ var endRow = fold.end.row;
+ var endColumn = fold.end.column;
+
+ var startFold = this.getFoldAt(startRow, startColumn, 1);
+ var endFold = this.getFoldAt(endRow, endColumn, -1);
+ if (startFold && endFold == startFold)
+ return startFold.addSubFold(fold);
+
+ if (startFold && !startFold.range.isStart(startRow, startColumn))
+ this.removeFold(startFold);
+
+ if (endFold && !endFold.range.isEnd(endRow, endColumn))
+ this.removeFold(endFold);
+ var folds = this.getFoldsInRange(fold.range);
+ if (folds.length > 0) {
+ this.removeFolds(folds);
+ folds.forEach(function(subFold) {
+ fold.addSubFold(subFold);
+ });
+ }
+
+ for (var i = 0; i < foldData.length; i++) {
+ var foldLine = foldData[i];
+ if (endRow == foldLine.start.row) {
+ foldLine.addFold(fold);
+ added = true;
+ break;
+ } else if (startRow == foldLine.end.row) {
+ foldLine.addFold(fold);
+ added = true;
+ if (!fold.sameRow) {
+ var foldLineNext = foldData[i + 1];
+ if (foldLineNext && foldLineNext.start.row == endRow) {
+ foldLine.merge(foldLineNext);
+ break;
+ }
+ }
+ break;
+ } else if (endRow <= foldLine.start.row) {
+ break;
+ }
+ }
+
+ if (!added)
+ foldLine = this.$addFoldLine(new FoldLine(this.$foldData, fold));
+
+ if (this.$useWrapMode)
+ this.$updateWrapData(foldLine.start.row, foldLine.start.row);
+ else this.$updateRowLengthCache(foldLine.start.row, foldLine.start.row);
+ this.$modified = true;
+ this._signal("changeFold", { data: fold, action: "add" });
+
+ return fold;
+ };
+
+ this.addFolds = function(folds) {
+ folds.forEach(function(fold) {
+ this.addFold(fold);
+ }, this);
+ };
+
+ this.removeFold = function(fold) {
+ var foldLine = fold.foldLine;
+ var startRow = foldLine.start.row;
+ var endRow = foldLine.end.row;
+
+ var foldLines = this.$foldData;
+ var folds = foldLine.folds;
+ if (folds.length == 1) {
+ foldLines.splice(foldLines.indexOf(foldLine), 1);
+ } else if (foldLine.range.isEnd(fold.end.row, fold.end.column)) {
+ folds.pop();
+ foldLine.end.row = folds[folds.length - 1].end.row;
+ foldLine.end.column = folds[folds.length - 1].end.column;
+ } else if (foldLine.range.isStart(fold.start.row, fold.start.column)) {
+ folds.shift();
+ foldLine.start.row = folds[0].start.row;
+ foldLine.start.column = folds[0].start.column;
+ } else if (fold.sameRow) {
+ folds.splice(folds.indexOf(fold), 1);
+ } else {
+ var newFoldLine = foldLine.split(fold.start.row, fold.start.column);
+ folds = newFoldLine.folds;
+ folds.shift();
+ newFoldLine.start.row = folds[0].start.row;
+ newFoldLine.start.column = folds[0].start.column;
+ }
+
+ if (!this.$updating) {
+ if (this.$useWrapMode) this.$updateWrapData(startRow, endRow);
+ else this.$updateRowLengthCache(startRow, endRow);
+ }
+ this.$modified = true;
+ this._signal("changeFold", { data: fold, action: "remove" });
+ };
+
+ this.removeFolds = function(folds) {
+ var cloneFolds = [];
+ for (var i = 0; i < folds.length; i++) {
+ cloneFolds.push(folds[i]);
+ }
+
+ cloneFolds.forEach(function(fold) {
+ this.removeFold(fold);
+ }, this);
+ this.$modified = true;
+ };
+
+ this.expandFold = function(fold) {
+ this.removeFold(fold);
+ fold.subFolds.forEach(function(subFold) {
+ fold.restoreRange(subFold);
+ this.addFold(subFold);
+ }, this);
+ if (fold.collapseChildren > 0) {
+ this.foldAll(
+ fold.start.row + 1,
+ fold.end.row,
+ fold.collapseChildren - 1
+ );
+ }
+ fold.subFolds = [];
+ };
+
+ this.expandFolds = function(folds) {
+ folds.forEach(function(fold) {
+ this.expandFold(fold);
+ }, this);
+ };
+
+ this.unfold = function(location, expandInner) {
+ var range, folds;
+ if (location == null) {
+ range = new Range(0, 0, this.getLength(), 0);
+ expandInner = true;
+ } else if (typeof location == "number")
+ range = new Range(
+ location,
+ 0,
+ location,
+ this.getLine(location).length
+ );
+ else if ("row" in location)
+ range = Range.fromPoints(location, location);
+ else range = location;
+
+ folds = this.getFoldsInRangeList(range);
+ if (expandInner) {
+ this.removeFolds(folds);
+ } else {
+ var subFolds = folds;
+ while (subFolds.length) {
+ this.expandFolds(subFolds);
+ subFolds = this.getFoldsInRangeList(range);
+ }
+ }
+ if (folds.length) return folds;
+ };
+ this.isRowFolded = function(docRow, startFoldRow) {
+ return !!this.getFoldLine(docRow, startFoldRow);
+ };
+
+ this.getRowFoldEnd = function(docRow, startFoldRow) {
+ var foldLine = this.getFoldLine(docRow, startFoldRow);
+ return foldLine ? foldLine.end.row : docRow;
+ };
+
+ this.getRowFoldStart = function(docRow, startFoldRow) {
+ var foldLine = this.getFoldLine(docRow, startFoldRow);
+ return foldLine ? foldLine.start.row : docRow;
+ };
+
+ this.getFoldDisplayLine = function(
+ foldLine,
+ endRow,
+ endColumn,
+ startRow,
+ startColumn
+ ) {
+ if (startRow == null) startRow = foldLine.start.row;
+ if (startColumn == null) startColumn = 0;
+ if (endRow == null) endRow = foldLine.end.row;
+ if (endColumn == null) endColumn = this.getLine(endRow).length;
+ var doc = this.doc;
+ var textLine = "";
+
+ foldLine.walk(
+ function(placeholder, row, column, lastColumn) {
+ if (row < startRow) return;
+ if (row == startRow) {
+ if (column < startColumn) return;
+ lastColumn = Math.max(startColumn, lastColumn);
+ }
+
+ if (placeholder != null) {
+ textLine += placeholder;
+ } else {
+ textLine += doc.getLine(row).substring(lastColumn, column);
+ }
+ },
+ endRow,
+ endColumn
+ );
+ return textLine;
+ };
+
+ this.getDisplayLine = function(row, endColumn, startRow, startColumn) {
+ var foldLine = this.getFoldLine(row);
+
+ if (!foldLine) {
+ var line;
+ line = this.doc.getLine(row);
+ return line.substring(startColumn || 0, endColumn || line.length);
+ } else {
+ return this.getFoldDisplayLine(
+ foldLine,
+ row,
+ endColumn,
+ startRow,
+ startColumn
+ );
+ }
+ };
+
+ this.$cloneFoldData = function() {
+ var fd = [];
+ fd = this.$foldData.map(function(foldLine) {
+ var folds = foldLine.folds.map(function(fold) {
+ return fold.clone();
+ });
+ return new FoldLine(fd, folds);
+ });
+
+ return fd;
+ };
+
+ this.toggleFold = function(tryToUnfold) {
+ var selection = this.selection;
+ var range = selection.getRange();
+ var fold;
+ var bracketPos;
+
+ if (range.isEmpty()) {
+ var cursor = range.start;
+ fold = this.getFoldAt(cursor.row, cursor.column);
+
+ if (fold) {
+ this.expandFold(fold);
+ return;
+ } else if ((bracketPos = this.findMatchingBracket(cursor))) {
+ if (range.comparePoint(bracketPos) == 1) {
+ range.end = bracketPos;
+ } else {
+ range.start = bracketPos;
+ range.start.column++;
+ range.end.column--;
+ }
+ } else if (
+ (bracketPos = this.findMatchingBracket({
+ row: cursor.row,
+ column: cursor.column + 1
+ }))
+ ) {
+ if (range.comparePoint(bracketPos) == 1) range.end = bracketPos;
+ else range.start = bracketPos;
+
+ range.start.column++;
+ } else {
+ range =
+ this.getCommentFoldRange(cursor.row, cursor.column) || range;
+ }
+ } else {
+ var folds = this.getFoldsInRange(range);
+ if (tryToUnfold && folds.length) {
+ this.expandFolds(folds);
+ return;
+ } else if (folds.length == 1) {
+ fold = folds[0];
+ }
+ }
+
+ if (!fold) fold = this.getFoldAt(range.start.row, range.start.column);
+
+ if (fold && fold.range.toString() == range.toString()) {
+ this.expandFold(fold);
+ return;
+ }
+
+ var placeholder = "...";
+ if (!range.isMultiLine()) {
+ placeholder = this.getTextRange(range);
+ if (placeholder.length < 4) return;
+ placeholder = placeholder.trim().substring(0, 2) + "..";
+ }
+
+ this.addFold(placeholder, range);
+ };
+
+ this.getCommentFoldRange = function(row, column, dir) {
+ var iterator = new TokenIterator(this, row, column);
+ var token = iterator.getCurrentToken();
+ var type = token.type;
+ if (token && /^comment|string/.test(type)) {
+ type = type.match(/comment|string/)[0];
+ if (type == "comment") type += "|doc-start";
+ var re = new RegExp(type);
+ var range = new Range();
+ if (dir != 1) {
+ do {
+ token = iterator.stepBackward();
+ } while (token && re.test(token.type));
+ iterator.stepForward();
+ }
+
+ range.start.row = iterator.getCurrentTokenRow();
+ range.start.column = iterator.getCurrentTokenColumn() + 2;
+
+ iterator = new TokenIterator(this, row, column);
+
+ if (dir != -1) {
+ var lastRow = -1;
+ do {
+ token = iterator.stepForward();
+ if (lastRow == -1) {
+ var state = this.getState(iterator.$row);
+ if (!re.test(state)) lastRow = iterator.$row;
+ } else if (iterator.$row > lastRow) {
+ break;
+ }
+ } while (token && re.test(token.type));
+ token = iterator.stepBackward();
+ } else token = iterator.getCurrentToken();
+
+ range.end.row = iterator.getCurrentTokenRow();
+ range.end.column =
+ iterator.getCurrentTokenColumn() + token.value.length - 2;
+ return range;
+ }
+ };
+
+ this.foldAll = function(startRow, endRow, depth) {
+ if (depth == undefined) depth = 100000; // JSON.stringify doesn't hanle Infinity
+ var foldWidgets = this.foldWidgets;
+ if (!foldWidgets) return; // mode doesn't support folding
+ endRow = endRow || this.getLength();
+ startRow = startRow || 0;
+ for (var row = startRow; row < endRow; row++) {
+ if (foldWidgets[row] == null)
+ foldWidgets[row] = this.getFoldWidget(row);
+ if (foldWidgets[row] != "start") continue;
+
+ var range = this.getFoldWidgetRange(row);
+ if (
+ range &&
+ range.isMultiLine() &&
+ range.end.row <= endRow &&
+ range.start.row >= startRow
+ ) {
+ row = range.end.row;
+ try {
+ var fold = this.addFold("...", range);
+ if (fold) fold.collapseChildren = depth;
+ } catch (e) {}
+ }
+ }
+ };
+ this.$foldStyles = {
+ manual: 1,
+ markbegin: 1,
+ markbeginend: 1
+ };
+ this.$foldStyle = "markbegin";
+ this.setFoldStyle = function(style) {
+ if (!this.$foldStyles[style])
+ throw new Error(
+ "invalid fold style: " +
+ style +
+ "[" +
+ Object.keys(this.$foldStyles).join(", ") +
+ "]"
+ );
+
+ if (this.$foldStyle == style) return;
+
+ this.$foldStyle = style;
+
+ if (style == "manual") this.unfold();
+ var mode = this.$foldMode;
+ this.$setFolding(null);
+ this.$setFolding(mode);
+ };
+
+ this.$setFolding = function(foldMode) {
+ if (this.$foldMode == foldMode) return;
+
+ this.$foldMode = foldMode;
+
+ this.off("change", this.$updateFoldWidgets);
+ this.off("tokenizerUpdate", this.$tokenizerUpdateFoldWidgets);
+ this._signal("changeAnnotation");
+
+ if (!foldMode || this.$foldStyle == "manual") {
+ this.foldWidgets = null;
+ return;
+ }
+
+ this.foldWidgets = [];
+ this.getFoldWidget = foldMode.getFoldWidget.bind(
+ foldMode,
+ this,
+ this.$foldStyle
+ );
+ this.getFoldWidgetRange = foldMode.getFoldWidgetRange.bind(
+ foldMode,
+ this,
+ this.$foldStyle
+ );
+
+ this.$updateFoldWidgets = this.updateFoldWidgets.bind(this);
+ this.$tokenizerUpdateFoldWidgets = this.tokenizerUpdateFoldWidgets.bind(
+ this
+ );
+ this.on("change", this.$updateFoldWidgets);
+ this.on("tokenizerUpdate", this.$tokenizerUpdateFoldWidgets);
+ };
+
+ this.getParentFoldRangeData = function(row, ignoreCurrent) {
+ var fw = this.foldWidgets;
+ if (!fw || (ignoreCurrent && fw[row])) return {};
+
+ var i = row - 1,
+ firstRange;
+ while (i >= 0) {
+ var c = fw[i];
+ if (c == null) c = fw[i] = this.getFoldWidget(i);
+
+ if (c == "start") {
+ var range = this.getFoldWidgetRange(i);
+ if (!firstRange) firstRange = range;
+ if (range && range.end.row >= row) break;
+ }
+ i--;
+ }
+
+ return {
+ range: i !== -1 && range,
+ firstRange: firstRange
+ };
+ };
+
+ this.onFoldWidgetClick = function(row, e) {
+ e = e.domEvent;
+ var options = {
+ children: e.shiftKey,
+ all: e.ctrlKey || e.metaKey,
+ siblings: e.altKey
+ };
+
+ var range = this.$toggleFoldWidget(row, options);
+ if (!range) {
+ var el = e.target || e.srcElement;
+ if (el && /ace_fold-widget/.test(el.className))
+ el.className += " ace_invalid";
+ }
+ };
+
+ this.$toggleFoldWidget = function(row, options) {
+ if (!this.getFoldWidget) return;
+ var type = this.getFoldWidget(row);
+ var line = this.getLine(row);
+
+ var dir = type === "end" ? -1 : 1;
+ var fold = this.getFoldAt(row, dir === -1 ? 0 : line.length, dir);
+
+ if (fold) {
+ if (options.children || options.all) this.removeFold(fold);
+ else this.expandFold(fold);
+ return fold;
+ }
+
+ var range = this.getFoldWidgetRange(row, true);
+ if (range && !range.isMultiLine()) {
+ fold = this.getFoldAt(range.start.row, range.start.column, 1);
+ if (fold && range.isEqual(fold.range)) {
+ this.removeFold(fold);
+ return fold;
+ }
+ }
+
+ if (options.siblings) {
+ var data = this.getParentFoldRangeData(row);
+ if (data.range) {
+ var startRow = data.range.start.row + 1;
+ var endRow = data.range.end.row;
+ }
+ this.foldAll(startRow, endRow, options.all ? 10000 : 0);
+ } else if (options.children) {
+ endRow = range ? range.end.row : this.getLength();
+ this.foldAll(row + 1, endRow, options.all ? 10000 : 0);
+ } else if (range) {
+ if (options.all) range.collapseChildren = 10000;
+ this.addFold("...", range);
+ }
+
+ return range;
+ };
+
+ this.toggleFoldWidget = function(toggleParent) {
+ var row = this.selection.getCursor().row;
+ row = this.getRowFoldStart(row);
+ var range = this.$toggleFoldWidget(row, {});
+
+ if (range) return;
+ var data = this.getParentFoldRangeData(row, true);
+ range = data.range || data.firstRange;
+
+ if (range) {
+ row = range.start.row;
+ var fold = this.getFoldAt(row, this.getLine(row).length, 1);
+
+ if (fold) {
+ this.removeFold(fold);
+ } else {
+ this.addFold("...", range);
+ }
+ }
+ };
+
+ this.updateFoldWidgets = function(delta) {
+ var firstRow = delta.start.row;
+ var len = delta.end.row - firstRow;
+
+ if (len === 0) {
+ this.foldWidgets[firstRow] = null;
+ } else if (delta.action == "remove") {
+ this.foldWidgets.splice(firstRow, len + 1, null);
+ } else {
+ var args = Array(len + 1);
+ args.unshift(firstRow, 1);
+ this.foldWidgets.splice.apply(this.foldWidgets, args);
+ }
+ };
+ this.tokenizerUpdateFoldWidgets = function(e) {
+ var rows = e.data;
+ if (rows.first != rows.last) {
+ if (this.foldWidgets.length > rows.first)
+ this.foldWidgets.splice(rows.first, this.foldWidgets.length);
+ }
+ };
+ }
+
+ exports.Folding = Folding;
+ }
+);
+
+ace.define(
+ "ace/edit_session/bracket_match",
+ ["require", "exports", "module", "ace/token_iterator", "ace/range"],
+ function(require, exports, module) {
+ "use strict";
+
+ var TokenIterator = require("../token_iterator").TokenIterator;
+ var Range = require("../range").Range;
+
+ function BracketMatch() {
+ this.findMatchingBracket = function(position, chr) {
+ if (position.column == 0) return null;
+
+ var charBeforeCursor =
+ chr || this.getLine(position.row).charAt(position.column - 1);
+ if (charBeforeCursor == "") return null;
+
+ var match = charBeforeCursor.match(/([\(\[\{])|([\)\]\}])/);
+ if (!match) return null;
+
+ if (match[1]) return this.$findClosingBracket(match[1], position);
+ else return this.$findOpeningBracket(match[2], position);
+ };
+
+ this.getBracketRange = function(pos) {
+ var line = this.getLine(pos.row);
+ var before = true,
+ range;
+
+ var chr = line.charAt(pos.column - 1);
+ var match = chr && chr.match(/([\(\[\{])|([\)\]\}])/);
+ if (!match) {
+ chr = line.charAt(pos.column);
+ pos = { row: pos.row, column: pos.column + 1 };
+ match = chr && chr.match(/([\(\[\{])|([\)\]\}])/);
+ before = false;
+ }
+ if (!match) return null;
+
+ if (match[1]) {
+ var bracketPos = this.$findClosingBracket(match[1], pos);
+ if (!bracketPos) return null;
+ range = Range.fromPoints(pos, bracketPos);
+ if (!before) {
+ range.end.column++;
+ range.start.column--;
+ }
+ range.cursor = range.end;
+ } else {
+ var bracketPos = this.$findOpeningBracket(match[2], pos);
+ if (!bracketPos) return null;
+ range = Range.fromPoints(bracketPos, pos);
+ if (!before) {
+ range.start.column++;
+ range.end.column--;
+ }
+ range.cursor = range.start;
+ }
+
+ return range;
+ };
+ this.getMatchingBracketRanges = function(pos) {
+ var line = this.getLine(pos.row);
+
+ var chr = line.charAt(pos.column - 1);
+ var match = chr && chr.match(/([\(\[\{])|([\)\]\}])/);
+ if (!match) {
+ chr = line.charAt(pos.column);
+ pos = { row: pos.row, column: pos.column + 1 };
+ match = chr && chr.match(/([\(\[\{])|([\)\]\}])/);
+ }
+
+ if (!match) return null;
+
+ var startRange = new Range(
+ pos.row,
+ pos.column - 1,
+ pos.row,
+ pos.column
+ );
+ var bracketPos = match[1]
+ ? this.$findClosingBracket(match[1], pos)
+ : this.$findOpeningBracket(match[2], pos);
+ if (!bracketPos) return [startRange];
+ var endRange = new Range(
+ bracketPos.row,
+ bracketPos.column,
+ bracketPos.row,
+ bracketPos.column + 1
+ );
+
+ return [startRange, endRange];
+ };
+
+ this.$brackets = {
+ ")": "(",
+ "(": ")",
+ "]": "[",
+ "[": "]",
+ "{": "}",
+ "}": "{",
+ "<": ">",
+ ">": "<"
+ };
+
+ this.$findOpeningBracket = function(bracket, position, typeRe) {
+ var openBracket = this.$brackets[bracket];
+ var depth = 1;
+
+ var iterator = new TokenIterator(this, position.row, position.column);
+ var token = iterator.getCurrentToken();
+ if (!token) token = iterator.stepForward();
+ if (!token) return;
+
+ if (!typeRe) {
+ typeRe = new RegExp(
+ "(\\.?" +
+ token.type
+ .replace(".", "\\.")
+ .replace("rparen", ".paren")
+ .replace(/\b(?:end)\b/, "(?:start|begin|end)") +
+ ")+"
+ );
+ }
+ var valueIndex = position.column - iterator.getCurrentTokenColumn() - 2;
+ var value = token.value;
+
+ while (true) {
+ while (valueIndex >= 0) {
+ var chr = value.charAt(valueIndex);
+ if (chr == openBracket) {
+ depth -= 1;
+ if (depth == 0) {
+ return {
+ row: iterator.getCurrentTokenRow(),
+ column: valueIndex + iterator.getCurrentTokenColumn()
+ };
+ }
+ } else if (chr == bracket) {
+ depth += 1;
+ }
+ valueIndex -= 1;
+ }
+ do {
+ token = iterator.stepBackward();
+ } while (token && !typeRe.test(token.type));
+
+ if (token == null) break;
+
+ value = token.value;
+ valueIndex = value.length - 1;
+ }
+
+ return null;
+ };
+
+ this.$findClosingBracket = function(bracket, position, typeRe) {
+ var closingBracket = this.$brackets[bracket];
+ var depth = 1;
+
+ var iterator = new TokenIterator(this, position.row, position.column);
+ var token = iterator.getCurrentToken();
+ if (!token) token = iterator.stepForward();
+ if (!token) return;
+
+ if (!typeRe) {
+ typeRe = new RegExp(
+ "(\\.?" +
+ token.type
+ .replace(".", "\\.")
+ .replace("lparen", ".paren")
+ .replace(/\b(?:start|begin)\b/, "(?:start|begin|end)") +
+ ")+"
+ );
+ }
+ var valueIndex = position.column - iterator.getCurrentTokenColumn();
+
+ while (true) {
+ var value = token.value;
+ var valueLength = value.length;
+ while (valueIndex < valueLength) {
+ var chr = value.charAt(valueIndex);
+ if (chr == closingBracket) {
+ depth -= 1;
+ if (depth == 0) {
+ return {
+ row: iterator.getCurrentTokenRow(),
+ column: valueIndex + iterator.getCurrentTokenColumn()
+ };
+ }
+ } else if (chr == bracket) {
+ depth += 1;
+ }
+ valueIndex += 1;
+ }
+ do {
+ token = iterator.stepForward();
+ } while (token && !typeRe.test(token.type));
+
+ if (token == null) break;
+
+ valueIndex = 0;
+ }
+
+ return null;
+ };
+ }
+ exports.BracketMatch = BracketMatch;
+ }
+);
+
+ace.define(
+ "ace/edit_session",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/lib/oop",
+ "ace/lib/lang",
+ "ace/bidihandler",
+ "ace/config",
+ "ace/lib/event_emitter",
+ "ace/selection",
+ "ace/mode/text",
+ "ace/range",
+ "ace/document",
+ "ace/background_tokenizer",
+ "ace/search_highlight",
+ "ace/edit_session/folding",
+ "ace/edit_session/bracket_match"
+ ],
+ function(require, exports, module) {
+ "use strict";
+
+ var oop = require("./lib/oop");
+ var lang = require("./lib/lang");
+ var BidiHandler = require("./bidihandler").BidiHandler;
+ var config = require("./config");
+ var EventEmitter = require("./lib/event_emitter").EventEmitter;
+ var Selection = require("./selection").Selection;
+ var TextMode = require("./mode/text").Mode;
+ var Range = require("./range").Range;
+ var Document = require("./document").Document;
+ var BackgroundTokenizer = require("./background_tokenizer")
+ .BackgroundTokenizer;
+ var SearchHighlight = require("./search_highlight").SearchHighlight;
+
+ var EditSession = function(text, mode) {
+ this.$breakpoints = [];
+ this.$decorations = [];
+ this.$frontMarkers = {};
+ this.$backMarkers = {};
+ this.$markerId = 1;
+ this.$undoSelect = true;
+
+ this.$foldData = [];
+ this.id = "session" + ++EditSession.$uid;
+ this.$foldData.toString = function() {
+ return this.join("\n");
+ };
+ this.on("changeFold", this.onChangeFold.bind(this));
+ this.$onChange = this.onChange.bind(this);
+
+ if (typeof text != "object" || !text.getLine) text = new Document(text);
+
+ this.setDocument(text);
+ this.selection = new Selection(this);
+ this.$bidiHandler = new BidiHandler(this);
+
+ config.resetOptions(this);
+ this.setMode(mode);
+ config._signal("session", this);
+ };
+
+ EditSession.$uid = 0;
+
+ (function() {
+ oop.implement(this, EventEmitter);
+ this.setDocument = function(doc) {
+ if (this.doc) this.doc.removeListener("change", this.$onChange);
+
+ this.doc = doc;
+ doc.on("change", this.$onChange);
+
+ if (this.bgTokenizer) this.bgTokenizer.setDocument(this.getDocument());
+
+ this.resetCaches();
+ };
+ this.getDocument = function() {
+ return this.doc;
+ };
+ this.$resetRowCache = function(docRow) {
+ if (!docRow) {
+ this.$docRowCache = [];
+ this.$screenRowCache = [];
+ return;
+ }
+ var l = this.$docRowCache.length;
+ var i = this.$getRowCacheIndex(this.$docRowCache, docRow) + 1;
+ if (l > i) {
+ this.$docRowCache.splice(i, l);
+ this.$screenRowCache.splice(i, l);
+ }
+ };
+
+ this.$getRowCacheIndex = function(cacheArray, val) {
+ var low = 0;
+ var hi = cacheArray.length - 1;
+
+ while (low <= hi) {
+ var mid = (low + hi) >> 1;
+ var c = cacheArray[mid];
+
+ if (val > c) low = mid + 1;
+ else if (val < c) hi = mid - 1;
+ else return mid;
+ }
+
+ return low - 1;
+ };
+
+ this.resetCaches = function() {
+ this.$modified = true;
+ this.$wrapData = [];
+ this.$rowLengthCache = [];
+ this.$resetRowCache(0);
+ if (this.bgTokenizer) this.bgTokenizer.start(0);
+ };
+
+ this.onChangeFold = function(e) {
+ var fold = e.data;
+ this.$resetRowCache(fold.start.row);
+ };
+
+ this.onChange = function(delta) {
+ this.$modified = true;
+ this.$bidiHandler.onChange(delta);
+ this.$resetRowCache(delta.start.row);
+
+ var removedFolds = this.$updateInternalDataOnChange(delta);
+ if (!this.$fromUndo && this.$undoManager) {
+ if (removedFolds && removedFolds.length) {
+ this.$undoManager.add(
+ {
+ action: "removeFolds",
+ folds: removedFolds
+ },
+ this.mergeUndoDeltas
+ );
+ this.mergeUndoDeltas = true;
+ }
+ this.$undoManager.add(delta, this.mergeUndoDeltas);
+ this.mergeUndoDeltas = true;
+
+ this.$informUndoManager.schedule();
+ }
+
+ this.bgTokenizer && this.bgTokenizer.$updateOnChange(delta);
+ this._signal("change", delta);
+ };
+ this.setValue = function(text) {
+ this.doc.setValue(text);
+ this.selection.moveTo(0, 0);
+
+ this.$resetRowCache(0);
+ this.setUndoManager(this.$undoManager);
+ this.getUndoManager().reset();
+ };
+ this.getValue = this.toString = function() {
+ return this.doc.getValue();
+ };
+ this.getSelection = function() {
+ return this.selection;
+ };
+ this.getState = function(row) {
+ return this.bgTokenizer.getState(row);
+ };
+ this.getTokens = function(row) {
+ return this.bgTokenizer.getTokens(row);
+ };
+ this.getTokenAt = function(row, column) {
+ var tokens = this.bgTokenizer.getTokens(row);
+ var token,
+ c = 0;
+ if (column == null) {
+ var i = tokens.length - 1;
+ c = this.getLine(row).length;
+ } else {
+ for (var i = 0; i < tokens.length; i++) {
+ c += tokens[i].value.length;
+ if (c >= column) break;
+ }
+ }
+ token = tokens[i];
+ if (!token) return null;
+ token.index = i;
+ token.start = c - token.value.length;
+ return token;
+ };
+ this.setUndoManager = function(undoManager) {
+ this.$undoManager = undoManager;
+
+ if (this.$informUndoManager) this.$informUndoManager.cancel();
+
+ if (undoManager) {
+ var self = this;
+ undoManager.addSession(this);
+ this.$syncInformUndoManager = function() {
+ self.$informUndoManager.cancel();
+ self.mergeUndoDeltas = false;
+ };
+ this.$informUndoManager = lang.delayedCall(
+ this.$syncInformUndoManager
+ );
+ } else {
+ this.$syncInformUndoManager = function() {};
+ }
+ };
+ this.markUndoGroup = function() {
+ if (this.$syncInformUndoManager) this.$syncInformUndoManager();
+ };
+
+ this.$defaultUndoManager = {
+ undo: function() {},
+ redo: function() {},
+ hasUndo: function() {},
+ hasRedo: function() {},
+ reset: function() {},
+ add: function() {},
+ addSelection: function() {},
+ startNewGroup: function() {},
+ addSession: function() {}
+ };
+ this.getUndoManager = function() {
+ return this.$undoManager || this.$defaultUndoManager;
+ };
+ this.getTabString = function() {
+ if (this.getUseSoftTabs()) {
+ return lang.stringRepeat(" ", this.getTabSize());
+ } else {
+ return "\t";
+ }
+ };
+ this.setUseSoftTabs = function(val) {
+ this.setOption("useSoftTabs", val);
+ };
+ this.getUseSoftTabs = function() {
+ return this.$useSoftTabs && !this.$mode.$indentWithTabs;
+ };
+ this.setTabSize = function(tabSize) {
+ this.setOption("tabSize", tabSize);
+ };
+ this.getTabSize = function() {
+ return this.$tabSize;
+ };
+ this.isTabStop = function(position) {
+ return this.$useSoftTabs && position.column % this.$tabSize === 0;
+ };
+ this.setNavigateWithinSoftTabs = function(navigateWithinSoftTabs) {
+ this.setOption("navigateWithinSoftTabs", navigateWithinSoftTabs);
+ };
+ this.getNavigateWithinSoftTabs = function() {
+ return this.$navigateWithinSoftTabs;
+ };
+
+ this.$overwrite = false;
+ this.setOverwrite = function(overwrite) {
+ this.setOption("overwrite", overwrite);
+ };
+ this.getOverwrite = function() {
+ return this.$overwrite;
+ };
+ this.toggleOverwrite = function() {
+ this.setOverwrite(!this.$overwrite);
+ };
+ this.addGutterDecoration = function(row, className) {
+ if (!this.$decorations[row]) this.$decorations[row] = "";
+ this.$decorations[row] += " " + className;
+ this._signal("changeBreakpoint", {});
+ };
+ this.removeGutterDecoration = function(row, className) {
+ this.$decorations[row] = (this.$decorations[row] || "").replace(
+ " " + className,
+ ""
+ );
+ this._signal("changeBreakpoint", {});
+ };
+ this.getBreakpoints = function() {
+ return this.$breakpoints;
+ };
+ this.setBreakpoints = function(rows) {
+ this.$breakpoints = [];
+ for (var i = 0; i < rows.length; i++) {
+ this.$breakpoints[rows[i]] = "ace_breakpoint";
+ }
+ this._signal("changeBreakpoint", {});
+ };
+ this.clearBreakpoints = function() {
+ this.$breakpoints = [];
+ this._signal("changeBreakpoint", {});
+ };
+ this.setBreakpoint = function(row, className) {
+ if (className === undefined) className = "ace_breakpoint";
+ if (className) this.$breakpoints[row] = className;
+ else delete this.$breakpoints[row];
+ this._signal("changeBreakpoint", {});
+ };
+ this.clearBreakpoint = function(row) {
+ delete this.$breakpoints[row];
+ this._signal("changeBreakpoint", {});
+ };
+ this.addMarker = function(range, clazz, type, inFront) {
+ var id = this.$markerId++;
+
+ var marker = {
+ range: range,
+ type: type || "line",
+ renderer: typeof type == "function" ? type : null,
+ clazz: clazz,
+ inFront: !!inFront,
+ id: id
+ };
+
+ if (inFront) {
+ this.$frontMarkers[id] = marker;
+ this._signal("changeFrontMarker");
+ } else {
+ this.$backMarkers[id] = marker;
+ this._signal("changeBackMarker");
+ }
+
+ return id;
+ };
+ this.addDynamicMarker = function(marker, inFront) {
+ if (!marker.update) return;
+ var id = this.$markerId++;
+ marker.id = id;
+ marker.inFront = !!inFront;
+
+ if (inFront) {
+ this.$frontMarkers[id] = marker;
+ this._signal("changeFrontMarker");
+ } else {
+ this.$backMarkers[id] = marker;
+ this._signal("changeBackMarker");
+ }
+
+ return marker;
+ };
+ this.removeMarker = function(markerId) {
+ var marker =
+ this.$frontMarkers[markerId] || this.$backMarkers[markerId];
+ if (!marker) return;
+
+ var markers = marker.inFront ? this.$frontMarkers : this.$backMarkers;
+ delete markers[markerId];
+ this._signal(marker.inFront ? "changeFrontMarker" : "changeBackMarker");
+ };
+ this.getMarkers = function(inFront) {
+ return inFront ? this.$frontMarkers : this.$backMarkers;
+ };
+
+ this.highlight = function(re) {
+ if (!this.$searchHighlight) {
+ var highlight = new SearchHighlight(
+ null,
+ "ace_selected-word",
+ "text"
+ );
+ this.$searchHighlight = this.addDynamicMarker(highlight);
+ }
+ this.$searchHighlight.setRegexp(re);
+ };
+ this.highlightLines = function(startRow, endRow, clazz, inFront) {
+ if (typeof endRow != "number") {
+ clazz = endRow;
+ endRow = startRow;
+ }
+ if (!clazz) clazz = "ace_step";
+
+ var range = new Range(startRow, 0, endRow, Infinity);
+ range.id = this.addMarker(range, clazz, "fullLine", inFront);
+ return range;
+ };
+ this.setAnnotations = function(annotations) {
+ this.$annotations = annotations;
+ this._signal("changeAnnotation", {});
+ };
+ this.getAnnotations = function() {
+ return this.$annotations || [];
+ };
+ this.clearAnnotations = function() {
+ this.setAnnotations([]);
+ };
+ this.$detectNewLine = function(text) {
+ var match = text.match(/^.*?(\r?\n)/m);
+ if (match) {
+ this.$autoNewLine = match[1];
+ } else {
+ this.$autoNewLine = "\n";
+ }
+ };
+ this.getWordRange = function(row, column) {
+ var line = this.getLine(row);
+
+ var inToken = false;
+ if (column > 0) inToken = !!line.charAt(column - 1).match(this.tokenRe);
+
+ if (!inToken) inToken = !!line.charAt(column).match(this.tokenRe);
+
+ if (inToken) var re = this.tokenRe;
+ else if (/^\s+$/.test(line.slice(column - 1, column + 1)))
+ var re = /\s/;
+ else var re = this.nonTokenRe;
+
+ var start = column;
+ if (start > 0) {
+ do {
+ start--;
+ } while (start >= 0 && line.charAt(start).match(re));
+ start++;
+ }
+
+ var end = column;
+ while (end < line.length && line.charAt(end).match(re)) {
+ end++;
+ }
+
+ return new Range(row, start, row, end);
+ };
+ this.getAWordRange = function(row, column) {
+ var wordRange = this.getWordRange(row, column);
+ var line = this.getLine(wordRange.end.row);
+
+ while (line.charAt(wordRange.end.column).match(/[ \t]/)) {
+ wordRange.end.column += 1;
+ }
+ return wordRange;
+ };
+ this.setNewLineMode = function(newLineMode) {
+ this.doc.setNewLineMode(newLineMode);
+ };
+ this.getNewLineMode = function() {
+ return this.doc.getNewLineMode();
+ };
+ this.setUseWorker = function(useWorker) {
+ this.setOption("useWorker", useWorker);
+ };
+ this.getUseWorker = function() {
+ return this.$useWorker;
+ };
+ this.onReloadTokenizer = function(e) {
+ var rows = e.data;
+ this.bgTokenizer.start(rows.first);
+ this._signal("tokenizerUpdate", e);
+ };
+
+ this.$modes = config.$modes;
+ this.$mode = null;
+ this.$modeId = null;
+ this.setMode = function(mode, cb) {
+ if (mode && typeof mode === "object") {
+ if (mode.getTokenizer) return this.$onChangeMode(mode);
+ var options = mode;
+ var path = options.path;
+ } else {
+ path = mode || "ace/mode/text";
+ }
+ if (!this.$modes["ace/mode/text"])
+ this.$modes["ace/mode/text"] = new TextMode();
+
+ if (this.$modes[path] && !options) {
+ this.$onChangeMode(this.$modes[path]);
+ cb && cb();
+ return;
+ }
+ this.$modeId = path;
+ config.loadModule(
+ ["mode", path],
+ function(m) {
+ if (this.$modeId !== path) return cb && cb();
+ if (this.$modes[path] && !options) {
+ this.$onChangeMode(this.$modes[path]);
+ } else if (m && m.Mode) {
+ m = new m.Mode(options);
+ if (!options) {
+ this.$modes[path] = m;
+ m.$id = path;
+ }
+ this.$onChangeMode(m);
+ }
+ cb && cb();
+ }.bind(this)
+ );
+ if (!this.$mode) this.$onChangeMode(this.$modes["ace/mode/text"], true);
+ };
+
+ this.$onChangeMode = function(mode, $isPlaceholder) {
+ if (!$isPlaceholder) this.$modeId = mode.$id;
+ if (this.$mode === mode) return;
+
+ var oldMode = this.$mode;
+ this.$mode = mode;
+
+ this.$stopWorker();
+
+ if (this.$useWorker) this.$startWorker();
+
+ var tokenizer = mode.getTokenizer();
+
+ if (tokenizer.on !== undefined) {
+ var onReloadTokenizer = this.onReloadTokenizer.bind(this);
+ tokenizer.on("update", onReloadTokenizer);
+ }
+
+ if (!this.bgTokenizer) {
+ this.bgTokenizer = new BackgroundTokenizer(tokenizer);
+ var _self = this;
+ this.bgTokenizer.on("update", function(e) {
+ _self._signal("tokenizerUpdate", e);
+ });
+ } else {
+ this.bgTokenizer.setTokenizer(tokenizer);
+ }
+
+ this.bgTokenizer.setDocument(this.getDocument());
+
+ this.tokenRe = mode.tokenRe;
+ this.nonTokenRe = mode.nonTokenRe;
+
+ if (!$isPlaceholder) {
+ if (mode.attachToSession) mode.attachToSession(this);
+ this.$options.wrapMethod.set.call(this, this.$wrapMethod);
+ this.$setFolding(mode.foldingRules);
+ this.bgTokenizer.start(0);
+ this._emit("changeMode", { oldMode: oldMode, mode: mode });
+ }
+ };
+
+ this.$stopWorker = function() {
+ if (this.$worker) {
+ this.$worker.terminate();
+ this.$worker = null;
+ }
+ };
+
+ this.$startWorker = function() {
+ try {
+ this.$worker = this.$mode.createWorker(this);
+ } catch (e) {
+ config.warn("Could not load worker", e);
+ this.$worker = null;
+ }
+ };
+ this.getMode = function() {
+ return this.$mode;
+ };
+
+ this.$scrollTop = 0;
+ this.setScrollTop = function(scrollTop) {
+ if (this.$scrollTop === scrollTop || isNaN(scrollTop)) return;
+
+ this.$scrollTop = scrollTop;
+ this._signal("changeScrollTop", scrollTop);
+ };
+ this.getScrollTop = function() {
+ return this.$scrollTop;
+ };
+
+ this.$scrollLeft = 0;
+ this.setScrollLeft = function(scrollLeft) {
+ if (this.$scrollLeft === scrollLeft || isNaN(scrollLeft)) return;
+
+ this.$scrollLeft = scrollLeft;
+ this._signal("changeScrollLeft", scrollLeft);
+ };
+ this.getScrollLeft = function() {
+ return this.$scrollLeft;
+ };
+ this.getScreenWidth = function() {
+ this.$computeWidth();
+ if (this.lineWidgets)
+ return Math.max(this.getLineWidgetMaxWidth(), this.screenWidth);
+ return this.screenWidth;
+ };
+
+ this.getLineWidgetMaxWidth = function() {
+ if (this.lineWidgetsWidth != null) return this.lineWidgetsWidth;
+ var width = 0;
+ this.lineWidgets.forEach(function(w) {
+ if (w && w.screenWidth > width) width = w.screenWidth;
+ });
+ return (this.lineWidgetWidth = width);
+ };
+
+ this.$computeWidth = function(force) {
+ if (this.$modified || force) {
+ this.$modified = false;
+
+ if (this.$useWrapMode) return (this.screenWidth = this.$wrapLimit);
+
+ var lines = this.doc.getAllLines();
+ var cache = this.$rowLengthCache;
+ var longestScreenLine = 0;
+ var foldIndex = 0;
+ var foldLine = this.$foldData[foldIndex];
+ var foldStart = foldLine ? foldLine.start.row : Infinity;
+ var len = lines.length;
+
+ for (var i = 0; i < len; i++) {
+ if (i > foldStart) {
+ i = foldLine.end.row + 1;
+ if (i >= len) break;
+ foldLine = this.$foldData[foldIndex++];
+ foldStart = foldLine ? foldLine.start.row : Infinity;
+ }
+
+ if (cache[i] == null)
+ cache[i] = this.$getStringScreenWidth(lines[i])[0];
+
+ if (cache[i] > longestScreenLine) longestScreenLine = cache[i];
+ }
+ this.screenWidth = longestScreenLine;
+ }
+ };
+ this.getLine = function(row) {
+ return this.doc.getLine(row);
+ };
+ this.getLines = function(firstRow, lastRow) {
+ return this.doc.getLines(firstRow, lastRow);
+ };
+ this.getLength = function() {
+ return this.doc.getLength();
+ };
+ this.getTextRange = function(range) {
+ return this.doc.getTextRange(range || this.selection.getRange());
+ };
+ this.insert = function(position, text) {
+ return this.doc.insert(position, text);
+ };
+ this.remove = function(range) {
+ return this.doc.remove(range);
+ };
+ this.removeFullLines = function(firstRow, lastRow) {
+ return this.doc.removeFullLines(firstRow, lastRow);
+ };
+ this.undoChanges = function(deltas, dontSelect) {
+ if (!deltas.length) return;
+
+ this.$fromUndo = true;
+ for (var i = deltas.length - 1; i != -1; i--) {
+ var delta = deltas[i];
+ if (delta.action == "insert" || delta.action == "remove") {
+ this.doc.revertDelta(delta);
+ } else if (delta.folds) {
+ this.addFolds(delta.folds);
+ }
+ }
+ if (!dontSelect && this.$undoSelect) {
+ if (deltas.selectionBefore)
+ this.selection.fromJSON(deltas.selectionBefore);
+ else this.selection.setRange(this.$getUndoSelection(deltas, true));
+ }
+ this.$fromUndo = false;
+ };
+ this.redoChanges = function(deltas, dontSelect) {
+ if (!deltas.length) return;
+
+ this.$fromUndo = true;
+ for (var i = 0; i < deltas.length; i++) {
+ var delta = deltas[i];
+ if (delta.action == "insert" || delta.action == "remove") {
+ this.doc.$safeApplyDelta(delta);
+ }
+ }
+
+ if (!dontSelect && this.$undoSelect) {
+ if (deltas.selectionAfter)
+ this.selection.fromJSON(deltas.selectionAfter);
+ else this.selection.setRange(this.$getUndoSelection(deltas, false));
+ }
+ this.$fromUndo = false;
+ };
+ this.setUndoSelect = function(enable) {
+ this.$undoSelect = enable;
+ };
+
+ this.$getUndoSelection = function(deltas, isUndo) {
+ function isInsert(delta) {
+ return isUndo ? delta.action !== "insert" : delta.action === "insert";
+ }
+
+ var range, point;
+
+ for (var i = 0; i < deltas.length; i++) {
+ var delta = deltas[i];
+ if (!delta.start) continue; // skip folds
+ if (!range) {
+ if (isInsert(delta)) {
+ range = Range.fromPoints(delta.start, delta.end);
+ } else {
+ range = Range.fromPoints(delta.start, delta.start);
+ }
+ continue;
+ }
+
+ if (isInsert(delta)) {
+ point = delta.start;
+ if (range.compare(point.row, point.column) == -1) {
+ range.setStart(point);
+ }
+ point = delta.end;
+ if (range.compare(point.row, point.column) == 1) {
+ range.setEnd(point);
+ }
+ } else {
+ point = delta.start;
+ if (range.compare(point.row, point.column) == -1) {
+ range = Range.fromPoints(delta.start, delta.start);
+ }
+ }
+ }
+ return range;
+ };
+ this.replace = function(range, text) {
+ return this.doc.replace(range, text);
+ };
+ this.moveText = function(fromRange, toPosition, copy) {
+ var text = this.getTextRange(fromRange);
+ var folds = this.getFoldsInRange(fromRange);
+
+ var toRange = Range.fromPoints(toPosition, toPosition);
+ if (!copy) {
+ this.remove(fromRange);
+ var rowDiff = fromRange.start.row - fromRange.end.row;
+ var collDiff = rowDiff
+ ? -fromRange.end.column
+ : fromRange.start.column - fromRange.end.column;
+ if (collDiff) {
+ if (
+ toRange.start.row == fromRange.end.row &&
+ toRange.start.column > fromRange.end.column
+ )
+ toRange.start.column += collDiff;
+ if (
+ toRange.end.row == fromRange.end.row &&
+ toRange.end.column > fromRange.end.column
+ )
+ toRange.end.column += collDiff;
+ }
+ if (rowDiff && toRange.start.row >= fromRange.end.row) {
+ toRange.start.row += rowDiff;
+ toRange.end.row += rowDiff;
+ }
+ }
+
+ toRange.end = this.insert(toRange.start, text);
+ if (folds.length) {
+ var oldStart = fromRange.start;
+ var newStart = toRange.start;
+ var rowDiff = newStart.row - oldStart.row;
+ var collDiff = newStart.column - oldStart.column;
+ this.addFolds(
+ folds.map(function(x) {
+ x = x.clone();
+ if (x.start.row == oldStart.row) x.start.column += collDiff;
+ if (x.end.row == oldStart.row) x.end.column += collDiff;
+ x.start.row += rowDiff;
+ x.end.row += rowDiff;
+ return x;
+ })
+ );
+ }
+
+ return toRange;
+ };
+ this.indentRows = function(startRow, endRow, indentString) {
+ indentString = indentString.replace(/\t/g, this.getTabString());
+ for (var row = startRow; row <= endRow; row++)
+ this.doc.insertInLine({ row: row, column: 0 }, indentString);
+ };
+ this.outdentRows = function(range) {
+ var rowRange = range.collapseRows();
+ var deleteRange = new Range(0, 0, 0, 0);
+ var size = this.getTabSize();
+
+ for (var i = rowRange.start.row; i <= rowRange.end.row; ++i) {
+ var line = this.getLine(i);
+
+ deleteRange.start.row = i;
+ deleteRange.end.row = i;
+ for (var j = 0; j < size; ++j) if (line.charAt(j) != " ") break;
+ if (j < size && line.charAt(j) == "\t") {
+ deleteRange.start.column = j;
+ deleteRange.end.column = j + 1;
+ } else {
+ deleteRange.start.column = 0;
+ deleteRange.end.column = j;
+ }
+ this.remove(deleteRange);
+ }
+ };
+
+ this.$moveLines = function(firstRow, lastRow, dir) {
+ firstRow = this.getRowFoldStart(firstRow);
+ lastRow = this.getRowFoldEnd(lastRow);
+ if (dir < 0) {
+ var row = this.getRowFoldStart(firstRow + dir);
+ if (row < 0) return 0;
+ var diff = row - firstRow;
+ } else if (dir > 0) {
+ var row = this.getRowFoldEnd(lastRow + dir);
+ if (row > this.doc.getLength() - 1) return 0;
+ var diff = row - lastRow;
+ } else {
+ firstRow = this.$clipRowToDocument(firstRow);
+ lastRow = this.$clipRowToDocument(lastRow);
+ var diff = lastRow - firstRow + 1;
+ }
+
+ var range = new Range(firstRow, 0, lastRow, Number.MAX_VALUE);
+ var folds = this.getFoldsInRange(range).map(function(x) {
+ x = x.clone();
+ x.start.row += diff;
+ x.end.row += diff;
+ return x;
+ });
+
+ var lines =
+ dir == 0
+ ? this.doc.getLines(firstRow, lastRow)
+ : this.doc.removeFullLines(firstRow, lastRow);
+ this.doc.insertFullLines(firstRow + diff, lines);
+ folds.length && this.addFolds(folds);
+ return diff;
+ };
+ this.moveLinesUp = function(firstRow, lastRow) {
+ return this.$moveLines(firstRow, lastRow, -1);
+ };
+ this.moveLinesDown = function(firstRow, lastRow) {
+ return this.$moveLines(firstRow, lastRow, 1);
+ };
+ this.duplicateLines = function(firstRow, lastRow) {
+ return this.$moveLines(firstRow, lastRow, 0);
+ };
+
+ this.$clipRowToDocument = function(row) {
+ return Math.max(0, Math.min(row, this.doc.getLength() - 1));
+ };
+
+ this.$clipColumnToRow = function(row, column) {
+ if (column < 0) return 0;
+ return Math.min(this.doc.getLine(row).length, column);
+ };
+
+ this.$clipPositionToDocument = function(row, column) {
+ column = Math.max(0, column);
+
+ if (row < 0) {
+ row = 0;
+ column = 0;
+ } else {
+ var len = this.doc.getLength();
+ if (row >= len) {
+ row = len - 1;
+ column = this.doc.getLine(len - 1).length;
+ } else {
+ column = Math.min(this.doc.getLine(row).length, column);
+ }
+ }
+
+ return {
+ row: row,
+ column: column
+ };
+ };
+
+ this.$clipRangeToDocument = function(range) {
+ if (range.start.row < 0) {
+ range.start.row = 0;
+ range.start.column = 0;
+ } else {
+ range.start.column = this.$clipColumnToRow(
+ range.start.row,
+ range.start.column
+ );
+ }
+
+ var len = this.doc.getLength() - 1;
+ if (range.end.row > len) {
+ range.end.row = len;
+ range.end.column = this.doc.getLine(len).length;
+ } else {
+ range.end.column = this.$clipColumnToRow(
+ range.end.row,
+ range.end.column
+ );
+ }
+ return range;
+ };
+ this.$wrapLimit = 80;
+ this.$useWrapMode = false;
+ this.$wrapLimitRange = {
+ min: null,
+ max: null
+ };
+ this.setUseWrapMode = function(useWrapMode) {
+ if (useWrapMode != this.$useWrapMode) {
+ this.$useWrapMode = useWrapMode;
+ this.$modified = true;
+ this.$resetRowCache(0);
+ if (useWrapMode) {
+ var len = this.getLength();
+ this.$wrapData = Array(len);
+ this.$updateWrapData(0, len - 1);
+ }
+
+ this._signal("changeWrapMode");
+ }
+ };
+ this.getUseWrapMode = function() {
+ return this.$useWrapMode;
+ };
+ this.setWrapLimitRange = function(min, max) {
+ if (
+ this.$wrapLimitRange.min !== min ||
+ this.$wrapLimitRange.max !== max
+ ) {
+ this.$wrapLimitRange = { min: min, max: max };
+ this.$modified = true;
+ this.$bidiHandler.markAsDirty();
+ if (this.$useWrapMode) this._signal("changeWrapMode");
+ }
+ };
+ this.adjustWrapLimit = function(desiredLimit, $printMargin) {
+ var limits = this.$wrapLimitRange;
+ if (limits.max < 0) limits = { min: $printMargin, max: $printMargin };
+ var wrapLimit = this.$constrainWrapLimit(
+ desiredLimit,
+ limits.min,
+ limits.max
+ );
+ if (wrapLimit != this.$wrapLimit && wrapLimit > 1) {
+ this.$wrapLimit = wrapLimit;
+ this.$modified = true;
+ if (this.$useWrapMode) {
+ this.$updateWrapData(0, this.getLength() - 1);
+ this.$resetRowCache(0);
+ this._signal("changeWrapLimit");
+ }
+ return true;
+ }
+ return false;
+ };
+
+ this.$constrainWrapLimit = function(wrapLimit, min, max) {
+ if (min) wrapLimit = Math.max(min, wrapLimit);
+
+ if (max) wrapLimit = Math.min(max, wrapLimit);
+
+ return wrapLimit;
+ };
+ this.getWrapLimit = function() {
+ return this.$wrapLimit;
+ };
+ this.setWrapLimit = function(limit) {
+ this.setWrapLimitRange(limit, limit);
+ };
+ this.getWrapLimitRange = function() {
+ return {
+ min: this.$wrapLimitRange.min,
+ max: this.$wrapLimitRange.max
+ };
+ };
+
+ this.$updateInternalDataOnChange = function(delta) {
+ var useWrapMode = this.$useWrapMode;
+ var action = delta.action;
+ var start = delta.start;
+ var end = delta.end;
+ var firstRow = start.row;
+ var lastRow = end.row;
+ var len = lastRow - firstRow;
+ var removedFolds = null;
+
+ this.$updating = true;
+ if (len != 0) {
+ if (action === "remove") {
+ this[useWrapMode ? "$wrapData" : "$rowLengthCache"].splice(
+ firstRow,
+ len
+ );
+
+ var foldLines = this.$foldData;
+ removedFolds = this.getFoldsInRange(delta);
+ this.removeFolds(removedFolds);
+
+ var foldLine = this.getFoldLine(end.row);
+ var idx = 0;
+ if (foldLine) {
+ foldLine.addRemoveChars(
+ end.row,
+ end.column,
+ start.column - end.column
+ );
+ foldLine.shiftRow(-len);
+
+ var foldLineBefore = this.getFoldLine(firstRow);
+ if (foldLineBefore && foldLineBefore !== foldLine) {
+ foldLineBefore.merge(foldLine);
+ foldLine = foldLineBefore;
+ }
+ idx = foldLines.indexOf(foldLine) + 1;
+ }
+
+ for (idx; idx < foldLines.length; idx++) {
+ var foldLine = foldLines[idx];
+ if (foldLine.start.row >= end.row) {
+ foldLine.shiftRow(-len);
+ }
+ }
+
+ lastRow = firstRow;
+ } else {
+ var args = Array(len);
+ args.unshift(firstRow, 0);
+ var arr = useWrapMode ? this.$wrapData : this.$rowLengthCache;
+ arr.splice.apply(arr, args);
+ var foldLines = this.$foldData;
+ var foldLine = this.getFoldLine(firstRow);
+ var idx = 0;
+ if (foldLine) {
+ var cmp = foldLine.range.compareInside(start.row, start.column);
+ if (cmp == 0) {
+ foldLine = foldLine.split(start.row, start.column);
+ if (foldLine) {
+ foldLine.shiftRow(len);
+ foldLine.addRemoveChars(
+ lastRow,
+ 0,
+ end.column - start.column
+ );
+ }
+ } else if (cmp == -1) {
+ foldLine.addRemoveChars(firstRow, 0, end.column - start.column);
+ foldLine.shiftRow(len);
+ }
+ idx = foldLines.indexOf(foldLine) + 1;
+ }
+
+ for (idx; idx < foldLines.length; idx++) {
+ var foldLine = foldLines[idx];
+ if (foldLine.start.row >= firstRow) {
+ foldLine.shiftRow(len);
+ }
+ }
+ }
+ } else {
+ len = Math.abs(delta.start.column - delta.end.column);
+ if (action === "remove") {
+ removedFolds = this.getFoldsInRange(delta);
+ this.removeFolds(removedFolds);
+
+ len = -len;
+ }
+ var foldLine = this.getFoldLine(firstRow);
+ if (foldLine) {
+ foldLine.addRemoveChars(firstRow, start.column, len);
+ }
+ }
+
+ if (useWrapMode && this.$wrapData.length != this.doc.getLength()) {
+ console.error(
+ "doc.getLength() and $wrapData.length have to be the same!"
+ );
+ }
+ this.$updating = false;
+
+ if (useWrapMode) this.$updateWrapData(firstRow, lastRow);
+ else this.$updateRowLengthCache(firstRow, lastRow);
+
+ return removedFolds;
+ };
+
+ this.$updateRowLengthCache = function(firstRow, lastRow, b) {
+ this.$rowLengthCache[firstRow] = null;
+ this.$rowLengthCache[lastRow] = null;
+ };
+
+ this.$updateWrapData = function(firstRow, lastRow) {
+ var lines = this.doc.getAllLines();
+ var tabSize = this.getTabSize();
+ var wrapData = this.$wrapData;
+ var wrapLimit = this.$wrapLimit;
+ var tokens;
+ var foldLine;
+
+ var row = firstRow;
+ lastRow = Math.min(lastRow, lines.length - 1);
+ while (row <= lastRow) {
+ foldLine = this.getFoldLine(row, foldLine);
+ if (!foldLine) {
+ tokens = this.$getDisplayTokens(lines[row]);
+ wrapData[row] = this.$computeWrapSplits(tokens, wrapLimit, tabSize);
+ row++;
+ } else {
+ tokens = [];
+ foldLine.walk(
+ function(placeholder, row, column, lastColumn) {
+ var walkTokens;
+ if (placeholder != null) {
+ walkTokens = this.$getDisplayTokens(
+ placeholder,
+ tokens.length
+ );
+ walkTokens[0] = PLACEHOLDER_START;
+ for (var i = 1; i < walkTokens.length; i++) {
+ walkTokens[i] = PLACEHOLDER_BODY;
+ }
+ } else {
+ walkTokens = this.$getDisplayTokens(
+ lines[row].substring(lastColumn, column),
+ tokens.length
+ );
+ }
+ tokens = tokens.concat(walkTokens);
+ }.bind(this),
+ foldLine.end.row,
+ lines[foldLine.end.row].length + 1
+ );
+
+ wrapData[foldLine.start.row] = this.$computeWrapSplits(
+ tokens,
+ wrapLimit,
+ tabSize
+ );
+ row = foldLine.end.row + 1;
+ }
+ }
+ };
+ var CHAR = 1,
+ CHAR_EXT = 2,
+ PLACEHOLDER_START = 3,
+ PLACEHOLDER_BODY = 4,
+ PUNCTUATION = 9,
+ SPACE = 10,
+ TAB = 11,
+ TAB_SPACE = 12;
+
+ this.$computeWrapSplits = function(tokens, wrapLimit, tabSize) {
+ if (tokens.length == 0) {
+ return [];
+ }
+
+ var splits = [];
+ var displayLength = tokens.length;
+ var lastSplit = 0,
+ lastDocSplit = 0;
+
+ var isCode = this.$wrapAsCode;
+
+ var indentedSoftWrap = this.$indentedSoftWrap;
+ var maxIndent =
+ wrapLimit <= Math.max(2 * tabSize, 8) || indentedSoftWrap === false
+ ? 0
+ : Math.floor(wrapLimit / 2);
+
+ function getWrapIndent() {
+ var indentation = 0;
+ if (maxIndent === 0) return indentation;
+ if (indentedSoftWrap) {
+ for (var i = 0; i < tokens.length; i++) {
+ var token = tokens[i];
+ if (token == SPACE) indentation += 1;
+ else if (token == TAB) indentation += tabSize;
+ else if (token == TAB_SPACE) continue;
+ else break;
+ }
+ }
+ if (isCode && indentedSoftWrap !== false) indentation += tabSize;
+ return Math.min(indentation, maxIndent);
+ }
+ function addSplit(screenPos) {
+ var len = screenPos - lastSplit;
+ for (var i = lastSplit; i < screenPos; i++) {
+ var ch = tokens[i];
+ if (ch === 12 || ch === 2) len -= 1;
+ }
+
+ if (!splits.length) {
+ indent = getWrapIndent();
+ splits.indent = indent;
+ }
+ lastDocSplit += len;
+ splits.push(lastDocSplit);
+ lastSplit = screenPos;
+ }
+ var indent = 0;
+ while (displayLength - lastSplit > wrapLimit - indent) {
+ var split = lastSplit + wrapLimit - indent;
+ if (tokens[split - 1] >= SPACE && tokens[split] >= SPACE) {
+ addSplit(split);
+ continue;
+ }
+ if (
+ tokens[split] == PLACEHOLDER_START ||
+ tokens[split] == PLACEHOLDER_BODY
+ ) {
+ for (split; split != lastSplit - 1; split--) {
+ if (tokens[split] == PLACEHOLDER_START) {
+ break;
+ }
+ }
+ if (split > lastSplit) {
+ addSplit(split);
+ continue;
+ }
+ split = lastSplit + wrapLimit;
+ for (split; split < tokens.length; split++) {
+ if (tokens[split] != PLACEHOLDER_BODY) {
+ break;
+ }
+ }
+ if (split == tokens.length) {
+ break; // Breaks the while-loop.
+ }
+ addSplit(split);
+ continue;
+ }
+ var minSplit = Math.max(
+ split - (wrapLimit - (wrapLimit >> 2)),
+ lastSplit - 1
+ );
+ while (split > minSplit && tokens[split] < PLACEHOLDER_START) {
+ split--;
+ }
+ if (isCode) {
+ while (split > minSplit && tokens[split] < PLACEHOLDER_START) {
+ split--;
+ }
+ while (split > minSplit && tokens[split] == PUNCTUATION) {
+ split--;
+ }
+ } else {
+ while (split > minSplit && tokens[split] < SPACE) {
+ split--;
+ }
+ }
+ if (split > minSplit) {
+ addSplit(++split);
+ continue;
+ }
+ split = lastSplit + wrapLimit;
+ if (tokens[split] == CHAR_EXT) split--;
+ addSplit(split - indent);
+ }
+ return splits;
+ };
+ this.$getDisplayTokens = function(str, offset) {
+ var arr = [];
+ var tabSize;
+ offset = offset || 0;
+
+ for (var i = 0; i < str.length; i++) {
+ var c = str.charCodeAt(i);
+ if (c == 9) {
+ tabSize = this.getScreenTabSize(arr.length + offset);
+ arr.push(TAB);
+ for (var n = 1; n < tabSize; n++) {
+ arr.push(TAB_SPACE);
+ }
+ } else if (c == 32) {
+ arr.push(SPACE);
+ } else if ((c > 39 && c < 48) || (c > 57 && c < 64)) {
+ arr.push(PUNCTUATION);
+ } else if (c >= 0x1100 && isFullWidth(c)) {
+ arr.push(CHAR, CHAR_EXT);
+ } else {
+ arr.push(CHAR);
+ }
+ }
+ return arr;
+ };
+ this.$getStringScreenWidth = function(
+ str,
+ maxScreenColumn,
+ screenColumn
+ ) {
+ if (maxScreenColumn == 0) return [0, 0];
+ if (maxScreenColumn == null) maxScreenColumn = Infinity;
+ screenColumn = screenColumn || 0;
+
+ var c, column;
+ for (column = 0; column < str.length; column++) {
+ c = str.charCodeAt(column);
+ if (c == 9) {
+ screenColumn += this.getScreenTabSize(screenColumn);
+ } else if (c >= 0x1100 && isFullWidth(c)) {
+ screenColumn += 2;
+ } else {
+ screenColumn += 1;
+ }
+ if (screenColumn > maxScreenColumn) {
+ break;
+ }
+ }
+
+ return [screenColumn, column];
+ };
+
+ this.lineWidgets = null;
+ this.getRowLength = function(row) {
+ var h = 1;
+ if (this.lineWidgets)
+ h += (this.lineWidgets[row] && this.lineWidgets[row].rowCount) || 0;
+
+ if (!this.$useWrapMode || !this.$wrapData[row]) return h;
+ else return this.$wrapData[row].length + h;
+ };
+ this.getRowLineCount = function(row) {
+ if (!this.$useWrapMode || !this.$wrapData[row]) {
+ return 1;
+ } else {
+ return this.$wrapData[row].length + 1;
+ }
+ };
+
+ this.getRowWrapIndent = function(screenRow) {
+ if (this.$useWrapMode) {
+ var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE);
+ var splits = this.$wrapData[pos.row];
+ return splits.length && splits[0] < pos.column ? splits.indent : 0;
+ } else {
+ return 0;
+ }
+ };
+ this.getScreenLastRowColumn = function(screenRow) {
+ var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE);
+ return this.documentToScreenColumn(pos.row, pos.column);
+ };
+ this.getDocumentLastRowColumn = function(docRow, docColumn) {
+ var screenRow = this.documentToScreenRow(docRow, docColumn);
+ return this.getScreenLastRowColumn(screenRow);
+ };
+ this.getDocumentLastRowColumnPosition = function(docRow, docColumn) {
+ var screenRow = this.documentToScreenRow(docRow, docColumn);
+ return this.screenToDocumentPosition(screenRow, Number.MAX_VALUE / 10);
+ };
+ this.getRowSplitData = function(row) {
+ if (!this.$useWrapMode) {
+ return undefined;
+ } else {
+ return this.$wrapData[row];
+ }
+ };
+ this.getScreenTabSize = function(screenColumn) {
+ return this.$tabSize - (screenColumn % this.$tabSize | 0);
+ };
+
+ this.screenToDocumentRow = function(screenRow, screenColumn) {
+ return this.screenToDocumentPosition(screenRow, screenColumn).row;
+ };
+
+ this.screenToDocumentColumn = function(screenRow, screenColumn) {
+ return this.screenToDocumentPosition(screenRow, screenColumn).column;
+ };
+ this.screenToDocumentPosition = function(
+ screenRow,
+ screenColumn,
+ offsetX
+ ) {
+ if (screenRow < 0) return { row: 0, column: 0 };
+
+ var line;
+ var docRow = 0;
+ var docColumn = 0;
+ var column;
+ var row = 0;
+ var rowLength = 0;
+
+ var rowCache = this.$screenRowCache;
+ var i = this.$getRowCacheIndex(rowCache, screenRow);
+ var l = rowCache.length;
+ if (l && i >= 0) {
+ var row = rowCache[i];
+ var docRow = this.$docRowCache[i];
+ var doCache = screenRow > rowCache[l - 1];
+ } else {
+ var doCache = !l;
+ }
+
+ var maxRow = this.getLength() - 1;
+ var foldLine = this.getNextFoldLine(docRow);
+ var foldStart = foldLine ? foldLine.start.row : Infinity;
+
+ while (row <= screenRow) {
+ rowLength = this.getRowLength(docRow);
+ if (row + rowLength > screenRow || docRow >= maxRow) {
+ break;
+ } else {
+ row += rowLength;
+ docRow++;
+ if (docRow > foldStart) {
+ docRow = foldLine.end.row + 1;
+ foldLine = this.getNextFoldLine(docRow, foldLine);
+ foldStart = foldLine ? foldLine.start.row : Infinity;
+ }
+ }
+
+ if (doCache) {
+ this.$docRowCache.push(docRow);
+ this.$screenRowCache.push(row);
+ }
+ }
+
+ if (foldLine && foldLine.start.row <= docRow) {
+ line = this.getFoldDisplayLine(foldLine);
+ docRow = foldLine.start.row;
+ } else if (row + rowLength <= screenRow || docRow > maxRow) {
+ return {
+ row: maxRow,
+ column: this.getLine(maxRow).length
+ };
+ } else {
+ line = this.getLine(docRow);
+ foldLine = null;
+ }
+ var wrapIndent = 0,
+ splitIndex = Math.floor(screenRow - row);
+ if (this.$useWrapMode) {
+ var splits = this.$wrapData[docRow];
+ if (splits) {
+ column = splits[splitIndex];
+ if (splitIndex > 0 && splits.length) {
+ wrapIndent = splits.indent;
+ docColumn = splits[splitIndex - 1] || splits[splits.length - 1];
+ line = line.substring(docColumn);
+ }
+ }
+ }
+
+ if (
+ offsetX !== undefined &&
+ this.$bidiHandler.isBidiRow(row + splitIndex, docRow, splitIndex)
+ )
+ screenColumn = this.$bidiHandler.offsetToCol(offsetX);
+
+ docColumn += this.$getStringScreenWidth(
+ line,
+ screenColumn - wrapIndent
+ )[1];
+ if (this.$useWrapMode && docColumn >= column) docColumn = column - 1;
+
+ if (foldLine) return foldLine.idxToPosition(docColumn);
+
+ return { row: docRow, column: docColumn };
+ };
+ this.documentToScreenPosition = function(docRow, docColumn) {
+ if (typeof docColumn === "undefined")
+ var pos = this.$clipPositionToDocument(docRow.row, docRow.column);
+ else pos = this.$clipPositionToDocument(docRow, docColumn);
+
+ docRow = pos.row;
+ docColumn = pos.column;
+
+ var screenRow = 0;
+ var foldStartRow = null;
+ var fold = null;
+ fold = this.getFoldAt(docRow, docColumn, 1);
+ if (fold) {
+ docRow = fold.start.row;
+ docColumn = fold.start.column;
+ }
+
+ var rowEnd,
+ row = 0;
+
+ var rowCache = this.$docRowCache;
+ var i = this.$getRowCacheIndex(rowCache, docRow);
+ var l = rowCache.length;
+ if (l && i >= 0) {
+ var row = rowCache[i];
+ var screenRow = this.$screenRowCache[i];
+ var doCache = docRow > rowCache[l - 1];
+ } else {
+ var doCache = !l;
+ }
+
+ var foldLine = this.getNextFoldLine(row);
+ var foldStart = foldLine ? foldLine.start.row : Infinity;
+
+ while (row < docRow) {
+ if (row >= foldStart) {
+ rowEnd = foldLine.end.row + 1;
+ if (rowEnd > docRow) break;
+ foldLine = this.getNextFoldLine(rowEnd, foldLine);
+ foldStart = foldLine ? foldLine.start.row : Infinity;
+ } else {
+ rowEnd = row + 1;
+ }
+
+ screenRow += this.getRowLength(row);
+ row = rowEnd;
+
+ if (doCache) {
+ this.$docRowCache.push(row);
+ this.$screenRowCache.push(screenRow);
+ }
+ }
+ var textLine = "";
+ if (foldLine && row >= foldStart) {
+ textLine = this.getFoldDisplayLine(foldLine, docRow, docColumn);
+ foldStartRow = foldLine.start.row;
+ } else {
+ textLine = this.getLine(docRow).substring(0, docColumn);
+ foldStartRow = docRow;
+ }
+ var wrapIndent = 0;
+ if (this.$useWrapMode) {
+ var wrapRow = this.$wrapData[foldStartRow];
+ if (wrapRow) {
+ var screenRowOffset = 0;
+ while (textLine.length >= wrapRow[screenRowOffset]) {
+ screenRow++;
+ screenRowOffset++;
+ }
+ textLine = textLine.substring(
+ wrapRow[screenRowOffset - 1] || 0,
+ textLine.length
+ );
+ wrapIndent = screenRowOffset > 0 ? wrapRow.indent : 0;
+ }
+ }
+
+ if (
+ this.lineWidgets &&
+ this.lineWidgets[row] &&
+ this.lineWidgets[row].rowsAbove
+ )
+ screenRow += this.lineWidgets[row].rowsAbove;
+
+ return {
+ row: screenRow,
+ column: wrapIndent + this.$getStringScreenWidth(textLine)[0]
+ };
+ };
+ this.documentToScreenColumn = function(row, docColumn) {
+ return this.documentToScreenPosition(row, docColumn).column;
+ };
+ this.documentToScreenRow = function(docRow, docColumn) {
+ return this.documentToScreenPosition(docRow, docColumn).row;
+ };
+ this.getScreenLength = function() {
+ var screenRows = 0;
+ var fold = null;
+ if (!this.$useWrapMode) {
+ screenRows = this.getLength();
+ var foldData = this.$foldData;
+ for (var i = 0; i < foldData.length; i++) {
+ fold = foldData[i];
+ screenRows -= fold.end.row - fold.start.row;
+ }
+ } else {
+ var lastRow = this.$wrapData.length;
+ var row = 0,
+ i = 0;
+ var fold = this.$foldData[i++];
+ var foldStart = fold ? fold.start.row : Infinity;
+
+ while (row < lastRow) {
+ var splits = this.$wrapData[row];
+ screenRows += splits ? splits.length + 1 : 1;
+ row++;
+ if (row > foldStart) {
+ row = fold.end.row + 1;
+ fold = this.$foldData[i++];
+ foldStart = fold ? fold.start.row : Infinity;
+ }
+ }
+ }
+ if (this.lineWidgets) screenRows += this.$getWidgetScreenLength();
+
+ return screenRows;
+ };
+ this.$setFontMetrics = function(fm) {
+ if (!this.$enableVarChar) return;
+ this.$getStringScreenWidth = function(
+ str,
+ maxScreenColumn,
+ screenColumn
+ ) {
+ if (maxScreenColumn === 0) return [0, 0];
+ if (!maxScreenColumn) maxScreenColumn = Infinity;
+ screenColumn = screenColumn || 0;
+
+ var c, column;
+ for (column = 0; column < str.length; column++) {
+ c = str.charAt(column);
+ if (c === "\t") {
+ screenColumn += this.getScreenTabSize(screenColumn);
+ } else {
+ screenColumn += fm.getCharacterWidth(c);
+ }
+ if (screenColumn > maxScreenColumn) {
+ break;
+ }
+ }
+
+ return [screenColumn, column];
+ };
+ };
+
+ this.destroy = function() {
+ if (this.bgTokenizer) {
+ this.bgTokenizer.setDocument(null);
+ this.bgTokenizer = null;
+ }
+ this.$stopWorker();
+ this.removeAllListeners();
+ this.selection.detach();
+ };
+
+ this.isFullWidth = isFullWidth;
+ function isFullWidth(c) {
+ if (c < 0x1100) return false;
+ return (
+ (c >= 0x1100 && c <= 0x115f) ||
+ (c >= 0x11a3 && c <= 0x11a7) ||
+ (c >= 0x11fa && c <= 0x11ff) ||
+ (c >= 0x2329 && c <= 0x232a) ||
+ (c >= 0x2e80 && c <= 0x2e99) ||
+ (c >= 0x2e9b && c <= 0x2ef3) ||
+ (c >= 0x2f00 && c <= 0x2fd5) ||
+ (c >= 0x2ff0 && c <= 0x2ffb) ||
+ (c >= 0x3000 && c <= 0x303e) ||
+ (c >= 0x3041 && c <= 0x3096) ||
+ (c >= 0x3099 && c <= 0x30ff) ||
+ (c >= 0x3105 && c <= 0x312d) ||
+ (c >= 0x3131 && c <= 0x318e) ||
+ (c >= 0x3190 && c <= 0x31ba) ||
+ (c >= 0x31c0 && c <= 0x31e3) ||
+ (c >= 0x31f0 && c <= 0x321e) ||
+ (c >= 0x3220 && c <= 0x3247) ||
+ (c >= 0x3250 && c <= 0x32fe) ||
+ (c >= 0x3300 && c <= 0x4dbf) ||
+ (c >= 0x4e00 && c <= 0xa48c) ||
+ (c >= 0xa490 && c <= 0xa4c6) ||
+ (c >= 0xa960 && c <= 0xa97c) ||
+ (c >= 0xac00 && c <= 0xd7a3) ||
+ (c >= 0xd7b0 && c <= 0xd7c6) ||
+ (c >= 0xd7cb && c <= 0xd7fb) ||
+ (c >= 0xf900 && c <= 0xfaff) ||
+ (c >= 0xfe10 && c <= 0xfe19) ||
+ (c >= 0xfe30 && c <= 0xfe52) ||
+ (c >= 0xfe54 && c <= 0xfe66) ||
+ (c >= 0xfe68 && c <= 0xfe6b) ||
+ (c >= 0xff01 && c <= 0xff60) ||
+ (c >= 0xffe0 && c <= 0xffe6)
+ );
+ }
+ }.call(EditSession.prototype));
+
+ require("./edit_session/folding").Folding.call(EditSession.prototype);
+ require("./edit_session/bracket_match").BracketMatch.call(
+ EditSession.prototype
+ );
+
+ config.defineOptions(EditSession.prototype, "session", {
+ wrap: {
+ set: function(value) {
+ if (!value || value == "off") value = false;
+ else if (value == "free") value = true;
+ else if (value == "printMargin") value = -1;
+ else if (typeof value == "string")
+ value = parseInt(value, 10) || false;
+
+ if (this.$wrap == value) return;
+ this.$wrap = value;
+ if (!value) {
+ this.setUseWrapMode(false);
+ } else {
+ var col = typeof value == "number" ? value : null;
+ this.setWrapLimitRange(col, col);
+ this.setUseWrapMode(true);
+ }
+ },
+ get: function() {
+ if (this.getUseWrapMode()) {
+ if (this.$wrap == -1) return "printMargin";
+ if (!this.getWrapLimitRange().min) return "free";
+ return this.$wrap;
+ }
+ return "off";
+ },
+ handlesSet: true
+ },
+ wrapMethod: {
+ set: function(val) {
+ val = val == "auto" ? this.$mode.type != "text" : val != "text";
+ if (val != this.$wrapAsCode) {
+ this.$wrapAsCode = val;
+ if (this.$useWrapMode) {
+ this.$useWrapMode = false;
+ this.setUseWrapMode(true);
+ }
+ }
+ },
+ initialValue: "auto"
+ },
+ indentedSoftWrap: {
+ set: function() {
+ if (this.$useWrapMode) {
+ this.$useWrapMode = false;
+ this.setUseWrapMode(true);
+ }
+ },
+ initialValue: true
+ },
+ firstLineNumber: {
+ set: function() {
+ this._signal("changeBreakpoint");
+ },
+ initialValue: 1
+ },
+ useWorker: {
+ set: function(useWorker) {
+ this.$useWorker = useWorker;
+
+ this.$stopWorker();
+ if (useWorker) this.$startWorker();
+ },
+ initialValue: true
+ },
+ useSoftTabs: { initialValue: true },
+ tabSize: {
+ set: function(tabSize) {
+ tabSize = parseInt(tabSize);
+ if (tabSize > 0 && this.$tabSize !== tabSize) {
+ this.$modified = true;
+ this.$rowLengthCache = [];
+ this.$tabSize = tabSize;
+ this._signal("changeTabSize");
+ }
+ },
+ initialValue: 4,
+ handlesSet: true
+ },
+ navigateWithinSoftTabs: { initialValue: false },
+ foldStyle: {
+ set: function(val) {
+ this.setFoldStyle(val);
+ },
+ handlesSet: true
+ },
+ overwrite: {
+ set: function(val) {
+ this._signal("changeOverwrite");
+ },
+ initialValue: false
+ },
+ newLineMode: {
+ set: function(val) {
+ this.doc.setNewLineMode(val);
+ },
+ get: function() {
+ return this.doc.getNewLineMode();
+ },
+ handlesSet: true
+ },
+ mode: {
+ set: function(val) {
+ this.setMode(val);
+ },
+ get: function() {
+ return this.$modeId;
+ },
+ handlesSet: true
+ }
+ });
+
+ exports.EditSession = EditSession;
+ }
+);
+
+ace.define(
+ "ace/search",
+ ["require", "exports", "module", "ace/lib/lang", "ace/lib/oop", "ace/range"],
+ function(require, exports, module) {
+ "use strict";
+
+ var lang = require("./lib/lang");
+ var oop = require("./lib/oop");
+ var Range = require("./range").Range;
+
+ var Search = function() {
+ this.$options = {};
+ };
+
+ (function() {
+ this.set = function(options) {
+ oop.mixin(this.$options, options);
+ return this;
+ };
+ this.getOptions = function() {
+ return lang.copyObject(this.$options);
+ };
+ this.setOptions = function(options) {
+ this.$options = options;
+ };
+ this.find = function(session) {
+ var options = this.$options;
+ var iterator = this.$matchIterator(session, options);
+ if (!iterator) return false;
+
+ var firstRange = null;
+ iterator.forEach(function(sr, sc, er, ec) {
+ firstRange = new Range(sr, sc, er, ec);
+ if (
+ sc == ec &&
+ options.start &&
+ options.start.start &&
+ options.skipCurrent != false &&
+ firstRange.isEqual(options.start)
+ ) {
+ firstRange = null;
+ return false;
+ }
+
+ return true;
+ });
+
+ return firstRange;
+ };
+ this.findAll = function(session) {
+ var options = this.$options;
+ if (!options.needle) return [];
+ this.$assembleRegExp(options);
+
+ var range = options.range;
+ var lines = range
+ ? session.getLines(range.start.row, range.end.row)
+ : session.doc.getAllLines();
+
+ var ranges = [];
+ var re = options.re;
+ if (options.$isMultiLine) {
+ var len = re.length;
+ var maxRow = lines.length - len;
+ var prevRange;
+ outer: for (var row = re.offset || 0; row <= maxRow; row++) {
+ for (var j = 0; j < len; j++)
+ if (lines[row + j].search(re[j]) == -1) continue outer;
+
+ var startLine = lines[row];
+ var line = lines[row + len - 1];
+ var startIndex =
+ startLine.length - startLine.match(re[0])[0].length;
+ var endIndex = line.match(re[len - 1])[0].length;
+
+ if (
+ prevRange &&
+ prevRange.end.row === row &&
+ prevRange.end.column > startIndex
+ ) {
+ continue;
+ }
+ ranges.push(
+ (prevRange = new Range(row, startIndex, row + len - 1, endIndex))
+ );
+ if (len > 2) row = row + len - 2;
+ }
+ } else {
+ for (var i = 0; i < lines.length; i++) {
+ var matches = lang.getMatchOffsets(lines[i], re);
+ for (var j = 0; j < matches.length; j++) {
+ var match = matches[j];
+ ranges.push(
+ new Range(i, match.offset, i, match.offset + match.length)
+ );
+ }
+ }
+ }
+
+ if (range) {
+ var startColumn = range.start.column;
+ var endColumn = range.start.column;
+ var i = 0,
+ j = ranges.length - 1;
+ while (
+ i < j &&
+ ranges[i].start.column < startColumn &&
+ ranges[i].start.row == range.start.row
+ )
+ i++;
+
+ while (
+ i < j &&
+ ranges[j].end.column > endColumn &&
+ ranges[j].end.row == range.end.row
+ )
+ j--;
+
+ ranges = ranges.slice(i, j + 1);
+ for (i = 0, j = ranges.length; i < j; i++) {
+ ranges[i].start.row += range.start.row;
+ ranges[i].end.row += range.start.row;
+ }
+ }
+
+ return ranges;
+ };
+ this.replace = function(input, replacement) {
+ var options = this.$options;
+
+ var re = this.$assembleRegExp(options);
+ if (options.$isMultiLine) return replacement;
+
+ if (!re) return;
+
+ var match = re.exec(input);
+ if (!match || match[0].length != input.length) return null;
+
+ replacement = input.replace(re, replacement);
+ if (options.preserveCase) {
+ replacement = replacement.split("");
+ for (var i = Math.min(input.length, input.length); i--; ) {
+ var ch = input[i];
+ if (ch && ch.toLowerCase() != ch)
+ replacement[i] = replacement[i].toUpperCase();
+ else replacement[i] = replacement[i].toLowerCase();
+ }
+ replacement = replacement.join("");
+ }
+
+ return replacement;
+ };
+
+ this.$assembleRegExp = function(options, $disableFakeMultiline) {
+ if (options.needle instanceof RegExp)
+ return (options.re = options.needle);
+
+ var needle = options.needle;
+
+ if (!options.needle) return (options.re = false);
+
+ if (!options.regExp) needle = lang.escapeRegExp(needle);
+
+ if (options.wholeWord) needle = addWordBoundary(needle, options);
+
+ var modifier = options.caseSensitive ? "gm" : "gmi";
+
+ options.$isMultiLine = !$disableFakeMultiline && /[\n\r]/.test(needle);
+ if (options.$isMultiLine)
+ return (options.re = this.$assembleMultilineRegExp(needle, modifier));
+
+ try {
+ var re = new RegExp(needle, modifier);
+ } catch (e) {
+ re = false;
+ }
+ return (options.re = re);
+ };
+
+ this.$assembleMultilineRegExp = function(needle, modifier) {
+ var parts = needle.replace(/\r\n|\r|\n/g, "$\n^").split("\n");
+ var re = [];
+ for (var i = 0; i < parts.length; i++)
+ try {
+ re.push(new RegExp(parts[i], modifier));
+ } catch (e) {
+ return false;
+ }
+ return re;
+ };
+
+ this.$matchIterator = function(session, options) {
+ var re = this.$assembleRegExp(options);
+ if (!re) return false;
+ var backwards = options.backwards == true;
+ var skipCurrent = options.skipCurrent != false;
+
+ var range = options.range;
+ var start = options.start;
+ if (!start)
+ start = range
+ ? range[backwards ? "end" : "start"]
+ : session.selection.getRange();
+
+ if (start.start)
+ start = start[skipCurrent != backwards ? "end" : "start"];
+
+ var firstRow = range ? range.start.row : 0;
+ var lastRow = range ? range.end.row : session.getLength() - 1;
+
+ if (backwards) {
+ var forEach = function(callback) {
+ var row = start.row;
+ if (forEachInLine(row, start.column, callback)) return;
+ for (row--; row >= firstRow; row--)
+ if (forEachInLine(row, Number.MAX_VALUE, callback)) return;
+ if (options.wrap == false) return;
+ for (row = lastRow, firstRow = start.row; row >= firstRow; row--)
+ if (forEachInLine(row, Number.MAX_VALUE, callback)) return;
+ };
+ } else {
+ var forEach = function(callback) {
+ var row = start.row;
+ if (forEachInLine(row, start.column, callback)) return;
+ for (row = row + 1; row <= lastRow; row++)
+ if (forEachInLine(row, 0, callback)) return;
+ if (options.wrap == false) return;
+ for (row = firstRow, lastRow = start.row; row <= lastRow; row++)
+ if (forEachInLine(row, 0, callback)) return;
+ };
+ }
+
+ if (options.$isMultiLine) {
+ var len = re.length;
+ var forEachInLine = function(row, offset, callback) {
+ var startRow = backwards ? row - len + 1 : row;
+ if (startRow < 0) return;
+ var line = session.getLine(startRow);
+ var startIndex = line.search(re[0]);
+ if ((!backwards && startIndex < offset) || startIndex === -1)
+ return;
+ for (var i = 1; i < len; i++) {
+ line = session.getLine(startRow + i);
+ if (line.search(re[i]) == -1) return;
+ }
+ var endIndex = line.match(re[len - 1])[0].length;
+ if (backwards && endIndex > offset) return;
+ if (callback(startRow, startIndex, startRow + len - 1, endIndex))
+ return true;
+ };
+ } else if (backwards) {
+ var forEachInLine = function(row, endIndex, callback) {
+ var line = session.getLine(row);
+ var matches = [];
+ var m,
+ last = 0;
+ re.lastIndex = 0;
+ while ((m = re.exec(line))) {
+ var length = m[0].length;
+ last = m.index;
+ if (!length) {
+ if (last >= line.length) break;
+ re.lastIndex = last += 1;
+ }
+ if (m.index + length > endIndex) break;
+ matches.push(m.index, length);
+ }
+ for (var i = matches.length - 1; i >= 0; i -= 2) {
+ var column = matches[i - 1];
+ var length = matches[i];
+ if (callback(row, column, row, column + length)) return true;
+ }
+ };
+ } else {
+ var forEachInLine = function(row, startIndex, callback) {
+ var line = session.getLine(row);
+ var last;
+ var m;
+ re.lastIndex = startIndex;
+ while ((m = re.exec(line))) {
+ var length = m[0].length;
+ last = m.index;
+ if (callback(row, last, row, last + length)) return true;
+ if (!length) {
+ re.lastIndex = last += 1;
+ if (last >= line.length) return false;
+ }
+ }
+ };
+ }
+ return { forEach: forEach };
+ };
+ }.call(Search.prototype));
+
+ function addWordBoundary(needle, options) {
+ function wordBoundary(c) {
+ if (/\w/.test(c) || options.regExp) return "\\b";
+ return "";
+ }
+ return (
+ wordBoundary(needle[0]) +
+ needle +
+ wordBoundary(needle[needle.length - 1])
+ );
+ }
+
+ exports.Search = Search;
+ }
+);
+
+ace.define(
+ "ace/keyboard/hash_handler",
+ ["require", "exports", "module", "ace/lib/keys", "ace/lib/useragent"],
+ function(require, exports, module) {
+ "use strict";
+
+ var keyUtil = require("../lib/keys");
+ var useragent = require("../lib/useragent");
+ var KEY_MODS = keyUtil.KEY_MODS;
+
+ function HashHandler(config, platform) {
+ this.platform = platform || (useragent.isMac ? "mac" : "win");
+ this.commands = {};
+ this.commandKeyBinding = {};
+ this.addCommands(config);
+ this.$singleCommand = true;
+ }
+
+ function MultiHashHandler(config, platform) {
+ HashHandler.call(this, config, platform);
+ this.$singleCommand = false;
+ }
+
+ MultiHashHandler.prototype = HashHandler.prototype;
+
+ (function() {
+ this.addCommand = function(command) {
+ if (this.commands[command.name]) this.removeCommand(command);
+
+ this.commands[command.name] = command;
+
+ if (command.bindKey) this._buildKeyHash(command);
+ };
+
+ this.removeCommand = function(command, keepCommand) {
+ var name =
+ command && (typeof command === "string" ? command : command.name);
+ command = this.commands[name];
+ if (!keepCommand) delete this.commands[name];
+ var ckb = this.commandKeyBinding;
+ for (var keyId in ckb) {
+ var cmdGroup = ckb[keyId];
+ if (cmdGroup == command) {
+ delete ckb[keyId];
+ } else if (Array.isArray(cmdGroup)) {
+ var i = cmdGroup.indexOf(command);
+ if (i != -1) {
+ cmdGroup.splice(i, 1);
+ if (cmdGroup.length == 1) ckb[keyId] = cmdGroup[0];
+ }
+ }
+ }
+ };
+
+ this.bindKey = function(key, command, position) {
+ if (typeof key == "object" && key) {
+ if (position == undefined) position = key.position;
+ key = key[this.platform];
+ }
+ if (!key) return;
+ if (typeof command == "function")
+ return this.addCommand({
+ exec: command,
+ bindKey: key,
+ name: command.name || key
+ });
+
+ key.split("|").forEach(function(keyPart) {
+ var chain = "";
+ if (keyPart.indexOf(" ") != -1) {
+ var parts = keyPart.split(/\s+/);
+ keyPart = parts.pop();
+ parts.forEach(function(keyPart) {
+ var binding = this.parseKeys(keyPart);
+ var id = KEY_MODS[binding.hashId] + binding.key;
+ chain += (chain ? " " : "") + id;
+ this._addCommandToBinding(chain, "chainKeys");
+ }, this);
+ chain += " ";
+ }
+ var binding = this.parseKeys(keyPart);
+ var id = KEY_MODS[binding.hashId] + binding.key;
+ this._addCommandToBinding(chain + id, command, position);
+ }, this);
+ };
+
+ function getPosition(command) {
+ return (
+ (typeof command == "object" &&
+ command.bindKey &&
+ command.bindKey.position) ||
+ (command.isDefault ? -100 : 0)
+ );
+ }
+ this._addCommandToBinding = function(keyId, command, position) {
+ var ckb = this.commandKeyBinding,
+ i;
+ if (!command) {
+ delete ckb[keyId];
+ } else if (!ckb[keyId] || this.$singleCommand) {
+ ckb[keyId] = command;
+ } else {
+ if (!Array.isArray(ckb[keyId])) {
+ ckb[keyId] = [ckb[keyId]];
+ } else if ((i = ckb[keyId].indexOf(command)) != -1) {
+ ckb[keyId].splice(i, 1);
+ }
+
+ if (typeof position != "number") {
+ position = getPosition(command);
+ }
+
+ var commands = ckb[keyId];
+ for (i = 0; i < commands.length; i++) {
+ var other = commands[i];
+ var otherPos = getPosition(other);
+ if (otherPos > position) break;
+ }
+ commands.splice(i, 0, command);
+ }
+ };
+
+ this.addCommands = function(commands) {
+ commands &&
+ Object.keys(commands).forEach(function(name) {
+ var command = commands[name];
+ if (!command) return;
+
+ if (typeof command === "string") return this.bindKey(command, name);
+
+ if (typeof command === "function") command = { exec: command };
+
+ if (typeof command !== "object") return;
+
+ if (!command.name) command.name = name;
+
+ this.addCommand(command);
+ }, this);
+ };
+
+ this.removeCommands = function(commands) {
+ Object.keys(commands).forEach(function(name) {
+ this.removeCommand(commands[name]);
+ }, this);
+ };
+
+ this.bindKeys = function(keyList) {
+ Object.keys(keyList).forEach(function(key) {
+ this.bindKey(key, keyList[key]);
+ }, this);
+ };
+
+ this._buildKeyHash = function(command) {
+ this.bindKey(command.bindKey, command);
+ };
+ this.parseKeys = function(keys) {
+ var parts = keys
+ .toLowerCase()
+ .split(/[\-\+]([\-\+])?/)
+ .filter(function(x) {
+ return x;
+ });
+ var key = parts.pop();
+
+ var keyCode = keyUtil[key];
+ if (keyUtil.FUNCTION_KEYS[keyCode])
+ key = keyUtil.FUNCTION_KEYS[keyCode].toLowerCase();
+ else if (!parts.length) return { key: key, hashId: -1 };
+ else if (parts.length == 1 && parts[0] == "shift")
+ return { key: key.toUpperCase(), hashId: -1 };
+
+ var hashId = 0;
+ for (var i = parts.length; i--; ) {
+ var modifier = keyUtil.KEY_MODS[parts[i]];
+ if (modifier == null) {
+ if (typeof console != "undefined")
+ console.error("invalid modifier " + parts[i] + " in " + keys);
+ return false;
+ }
+ hashId |= modifier;
+ }
+ return { key: key, hashId: hashId };
+ };
+
+ this.findKeyCommand = function findKeyCommand(hashId, keyString) {
+ var key = KEY_MODS[hashId] + keyString;
+ return this.commandKeyBinding[key];
+ };
+
+ this.handleKeyboard = function(data, hashId, keyString, keyCode) {
+ if (keyCode < 0) return;
+ var key = KEY_MODS[hashId] + keyString;
+ var command = this.commandKeyBinding[key];
+ if (data.$keyChain) {
+ data.$keyChain += " " + key;
+ command = this.commandKeyBinding[data.$keyChain] || command;
+ }
+
+ if (command) {
+ if (
+ command == "chainKeys" ||
+ command[command.length - 1] == "chainKeys"
+ ) {
+ data.$keyChain = data.$keyChain || key;
+ return { command: "null" };
+ }
+ }
+
+ if (data.$keyChain) {
+ if ((!hashId || hashId == 4) && keyString.length == 1)
+ data.$keyChain = data.$keyChain.slice(0, -key.length - 1);
+ // wait for input
+ else if (hashId == -1 || keyCode > 0) data.$keyChain = ""; // reset keyChain
+ }
+ return { command: command };
+ };
+
+ this.getStatusText = function(editor, data) {
+ return data.$keyChain || "";
+ };
+ }.call(HashHandler.prototype));
+
+ exports.HashHandler = HashHandler;
+ exports.MultiHashHandler = MultiHashHandler;
+ }
+);
+
+ace.define(
+ "ace/commands/command_manager",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/lib/oop",
+ "ace/keyboard/hash_handler",
+ "ace/lib/event_emitter"
+ ],
+ function(require, exports, module) {
+ "use strict";
+
+ var oop = require("../lib/oop");
+ var MultiHashHandler = require("../keyboard/hash_handler").MultiHashHandler;
+ var EventEmitter = require("../lib/event_emitter").EventEmitter;
+
+ var CommandManager = function(platform, commands) {
+ MultiHashHandler.call(this, commands, platform);
+ this.byName = this.commands;
+ this.setDefaultHandler("exec", function(e) {
+ return e.command.exec(e.editor, e.args || {});
+ });
+ };
+
+ oop.inherits(CommandManager, MultiHashHandler);
+
+ (function() {
+ oop.implement(this, EventEmitter);
+
+ this.exec = function(command, editor, args) {
+ if (Array.isArray(command)) {
+ for (var i = command.length; i--; ) {
+ if (this.exec(command[i], editor, args)) return true;
+ }
+ return false;
+ }
+
+ if (typeof command === "string") command = this.commands[command];
+
+ if (!command) return false;
+
+ if (editor && editor.$readOnly && !command.readOnly) return false;
+
+ if (
+ this.$checkCommandState != false &&
+ command.isAvailable &&
+ !command.isAvailable(editor)
+ )
+ return false;
+
+ var e = { editor: editor, command: command, args: args };
+ e.returnValue = this._emit("exec", e);
+ this._signal("afterExec", e);
+
+ return e.returnValue === false ? false : true;
+ };
+
+ this.toggleRecording = function(editor) {
+ if (this.$inReplay) return;
+
+ editor && editor._emit("changeStatus");
+ if (this.recording) {
+ this.macro.pop();
+ this.off("exec", this.$addCommandToMacro);
+
+ if (!this.macro.length) this.macro = this.oldMacro;
+
+ return (this.recording = false);
+ }
+ if (!this.$addCommandToMacro) {
+ this.$addCommandToMacro = function(e) {
+ this.macro.push([e.command, e.args]);
+ }.bind(this);
+ }
+
+ this.oldMacro = this.macro;
+ this.macro = [];
+ this.on("exec", this.$addCommandToMacro);
+ return (this.recording = true);
+ };
+
+ this.replay = function(editor) {
+ if (this.$inReplay || !this.macro) return;
+
+ if (this.recording) return this.toggleRecording(editor);
+
+ try {
+ this.$inReplay = true;
+ this.macro.forEach(function(x) {
+ if (typeof x == "string") this.exec(x, editor);
+ else this.exec(x[0], editor, x[1]);
+ }, this);
+ } finally {
+ this.$inReplay = false;
+ }
+ };
+
+ this.trimMacro = function(m) {
+ return m.map(function(x) {
+ if (typeof x[0] != "string") x[0] = x[0].name;
+ if (!x[1]) x = x[0];
+ return x;
+ });
+ };
+ }.call(CommandManager.prototype));
+
+ exports.CommandManager = CommandManager;
+ }
+);
+
+ace.define(
+ "ace/commands/default_commands",
+ ["require", "exports", "module", "ace/lib/lang", "ace/config", "ace/range"],
+ function(require, exports, module) {
+ "use strict";
+
+ var lang = require("../lib/lang");
+ var config = require("../config");
+ var Range = require("../range").Range;
+
+ function bindKey(win, mac) {
+ return { win: win, mac: mac };
+ }
+ exports.commands = [
+ {
+ name: "showSettingsMenu",
+ bindKey: bindKey("Ctrl-,", "Command-,"),
+ exec: function(editor) {
+ config.loadModule("ace/ext/settings_menu", function(module) {
+ module.init(editor);
+ editor.showSettingsMenu();
+ });
+ },
+ readOnly: true
+ },
+ {
+ name: "goToNextError",
+ bindKey: bindKey("Alt-E", "F4"),
+ exec: function(editor) {
+ config.loadModule("./ext/error_marker", function(module) {
+ module.showErrorMarker(editor, 1);
+ });
+ },
+ scrollIntoView: "animate",
+ readOnly: true
+ },
+ {
+ name: "goToPreviousError",
+ bindKey: bindKey("Alt-Shift-E", "Shift-F4"),
+ exec: function(editor) {
+ config.loadModule("./ext/error_marker", function(module) {
+ module.showErrorMarker(editor, -1);
+ });
+ },
+ scrollIntoView: "animate",
+ readOnly: true
+ },
+ {
+ name: "selectall",
+ description: "Select all",
+ bindKey: bindKey("Ctrl-A", "Command-A"),
+ exec: function(editor) {
+ editor.selectAll();
+ },
+ readOnly: true
+ },
+ {
+ name: "centerselection",
+ description: "Center selection",
+ bindKey: bindKey(null, "Ctrl-L"),
+ exec: function(editor) {
+ editor.centerSelection();
+ },
+ readOnly: true
+ },
+ {
+ name: "gotoline",
+ description: "Go to line...",
+ bindKey: bindKey("Ctrl-L", "Command-L"),
+ exec: function(editor, line) {
+ if (typeof line === "number" && !isNaN(line)) editor.gotoLine(line);
+ editor.prompt({ $type: "gotoLine" });
+ },
+ readOnly: true
+ },
+ {
+ name: "fold",
+ bindKey: bindKey("Alt-L|Ctrl-F1", "Command-Alt-L|Command-F1"),
+ exec: function(editor) {
+ editor.session.toggleFold(false);
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "center",
+ readOnly: true
+ },
+ {
+ name: "unfold",
+ bindKey: bindKey(
+ "Alt-Shift-L|Ctrl-Shift-F1",
+ "Command-Alt-Shift-L|Command-Shift-F1"
+ ),
+ exec: function(editor) {
+ editor.session.toggleFold(true);
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "center",
+ readOnly: true
+ },
+ {
+ name: "toggleFoldWidget",
+ bindKey: bindKey("F2", "F2"),
+ exec: function(editor) {
+ editor.session.toggleFoldWidget();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "center",
+ readOnly: true
+ },
+ {
+ name: "toggleParentFoldWidget",
+ bindKey: bindKey("Alt-F2", "Alt-F2"),
+ exec: function(editor) {
+ editor.session.toggleFoldWidget(true);
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "center",
+ readOnly: true
+ },
+ {
+ name: "foldall",
+ description: "Fold all",
+ bindKey: bindKey(null, "Ctrl-Command-Option-0"),
+ exec: function(editor) {
+ editor.session.foldAll();
+ },
+ scrollIntoView: "center",
+ readOnly: true
+ },
+ {
+ name: "foldOther",
+ description: "Fold other",
+ bindKey: bindKey("Alt-0", "Command-Option-0"),
+ exec: function(editor) {
+ editor.session.foldAll();
+ editor.session.unfold(editor.selection.getAllRanges());
+ },
+ scrollIntoView: "center",
+ readOnly: true
+ },
+ {
+ name: "unfoldall",
+ description: "Unfold all",
+ bindKey: bindKey("Alt-Shift-0", "Command-Option-Shift-0"),
+ exec: function(editor) {
+ editor.session.unfold();
+ },
+ scrollIntoView: "center",
+ readOnly: true
+ },
+ {
+ name: "findnext",
+ description: "Find next",
+ bindKey: bindKey("Ctrl-K", "Command-G"),
+ exec: function(editor) {
+ editor.findNext();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "center",
+ readOnly: true
+ },
+ {
+ name: "findprevious",
+ description: "Find previous",
+ bindKey: bindKey("Ctrl-Shift-K", "Command-Shift-G"),
+ exec: function(editor) {
+ editor.findPrevious();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "center",
+ readOnly: true
+ },
+ {
+ name: "selectOrFindNext",
+ description: "Select or find next",
+ bindKey: bindKey("Alt-K", "Ctrl-G"),
+ exec: function(editor) {
+ if (editor.selection.isEmpty()) editor.selection.selectWord();
+ else editor.findNext();
+ },
+ readOnly: true
+ },
+ {
+ name: "selectOrFindPrevious",
+ description: "Select or find previous",
+ bindKey: bindKey("Alt-Shift-K", "Ctrl-Shift-G"),
+ exec: function(editor) {
+ if (editor.selection.isEmpty()) editor.selection.selectWord();
+ else editor.findPrevious();
+ },
+ readOnly: true
+ },
+ {
+ name: "find",
+ description: "Find",
+ bindKey: bindKey("Ctrl-F", "Command-F"),
+ exec: function(editor) {
+ config.loadModule("ace/ext/searchbox", function(e) {
+ e.Search(editor);
+ });
+ },
+ readOnly: true
+ },
+ {
+ name: "overwrite",
+ description: "Overwrite",
+ bindKey: "Insert",
+ exec: function(editor) {
+ editor.toggleOverwrite();
+ },
+ readOnly: true
+ },
+ {
+ name: "selecttostart",
+ description: "Select to start",
+ bindKey: bindKey(
+ "Ctrl-Shift-Home",
+ "Command-Shift-Home|Command-Shift-Up"
+ ),
+ exec: function(editor) {
+ editor.getSelection().selectFileStart();
+ },
+ multiSelectAction: "forEach",
+ readOnly: true,
+ scrollIntoView: "animate",
+ aceCommandGroup: "fileJump"
+ },
+ {
+ name: "gotostart",
+ description: "Go to start",
+ bindKey: bindKey("Ctrl-Home", "Command-Home|Command-Up"),
+ exec: function(editor) {
+ editor.navigateFileStart();
+ },
+ multiSelectAction: "forEach",
+ readOnly: true,
+ scrollIntoView: "animate",
+ aceCommandGroup: "fileJump"
+ },
+ {
+ name: "selectup",
+ description: "Select up",
+ bindKey: bindKey("Shift-Up", "Shift-Up|Ctrl-Shift-P"),
+ exec: function(editor) {
+ editor.getSelection().selectUp();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "golineup",
+ description: "Go line up",
+ bindKey: bindKey("Up", "Up|Ctrl-P"),
+ exec: function(editor, args) {
+ editor.navigateUp(args.times);
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "selecttoend",
+ description: "Select to end",
+ bindKey: bindKey(
+ "Ctrl-Shift-End",
+ "Command-Shift-End|Command-Shift-Down"
+ ),
+ exec: function(editor) {
+ editor.getSelection().selectFileEnd();
+ },
+ multiSelectAction: "forEach",
+ readOnly: true,
+ scrollIntoView: "animate",
+ aceCommandGroup: "fileJump"
+ },
+ {
+ name: "gotoend",
+ description: "Go to end",
+ bindKey: bindKey("Ctrl-End", "Command-End|Command-Down"),
+ exec: function(editor) {
+ editor.navigateFileEnd();
+ },
+ multiSelectAction: "forEach",
+ readOnly: true,
+ scrollIntoView: "animate",
+ aceCommandGroup: "fileJump"
+ },
+ {
+ name: "selectdown",
+ description: "Select down",
+ bindKey: bindKey("Shift-Down", "Shift-Down|Ctrl-Shift-N"),
+ exec: function(editor) {
+ editor.getSelection().selectDown();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "golinedown",
+ description: "Go line down",
+ bindKey: bindKey("Down", "Down|Ctrl-N"),
+ exec: function(editor, args) {
+ editor.navigateDown(args.times);
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "selectwordleft",
+ description: "Select word left",
+ bindKey: bindKey("Ctrl-Shift-Left", "Option-Shift-Left"),
+ exec: function(editor) {
+ editor.getSelection().selectWordLeft();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "gotowordleft",
+ description: "Go to word left",
+ bindKey: bindKey("Ctrl-Left", "Option-Left"),
+ exec: function(editor) {
+ editor.navigateWordLeft();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "selecttolinestart",
+ description: "Select to line start",
+ bindKey: bindKey("Alt-Shift-Left", "Command-Shift-Left|Ctrl-Shift-A"),
+ exec: function(editor) {
+ editor.getSelection().selectLineStart();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "gotolinestart",
+ description: "Go to line start",
+ bindKey: bindKey("Alt-Left|Home", "Command-Left|Home|Ctrl-A"),
+ exec: function(editor) {
+ editor.navigateLineStart();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "selectleft",
+ description: "Select left",
+ bindKey: bindKey("Shift-Left", "Shift-Left|Ctrl-Shift-B"),
+ exec: function(editor) {
+ editor.getSelection().selectLeft();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "gotoleft",
+ description: "Go to left",
+ bindKey: bindKey("Left", "Left|Ctrl-B"),
+ exec: function(editor, args) {
+ editor.navigateLeft(args.times);
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "selectwordright",
+ description: "Select word right",
+ bindKey: bindKey("Ctrl-Shift-Right", "Option-Shift-Right"),
+ exec: function(editor) {
+ editor.getSelection().selectWordRight();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "gotowordright",
+ description: "Go to word right",
+ bindKey: bindKey("Ctrl-Right", "Option-Right"),
+ exec: function(editor) {
+ editor.navigateWordRight();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "selecttolineend",
+ description: "Select to line end",
+ bindKey: bindKey(
+ "Alt-Shift-Right",
+ "Command-Shift-Right|Shift-End|Ctrl-Shift-E"
+ ),
+ exec: function(editor) {
+ editor.getSelection().selectLineEnd();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "gotolineend",
+ description: "Go to line end",
+ bindKey: bindKey("Alt-Right|End", "Command-Right|End|Ctrl-E"),
+ exec: function(editor) {
+ editor.navigateLineEnd();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "selectright",
+ description: "Select right",
+ bindKey: bindKey("Shift-Right", "Shift-Right"),
+ exec: function(editor) {
+ editor.getSelection().selectRight();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "gotoright",
+ description: "Go to right",
+ bindKey: bindKey("Right", "Right|Ctrl-F"),
+ exec: function(editor, args) {
+ editor.navigateRight(args.times);
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "selectpagedown",
+ description: "Select page down",
+ bindKey: "Shift-PageDown",
+ exec: function(editor) {
+ editor.selectPageDown();
+ },
+ readOnly: true
+ },
+ {
+ name: "pagedown",
+ description: "Page down",
+ bindKey: bindKey(null, "Option-PageDown"),
+ exec: function(editor) {
+ editor.scrollPageDown();
+ },
+ readOnly: true
+ },
+ {
+ name: "gotopagedown",
+ description: "Go to page down",
+ bindKey: bindKey("PageDown", "PageDown|Ctrl-V"),
+ exec: function(editor) {
+ editor.gotoPageDown();
+ },
+ readOnly: true
+ },
+ {
+ name: "selectpageup",
+ description: "Select page up",
+ bindKey: "Shift-PageUp",
+ exec: function(editor) {
+ editor.selectPageUp();
+ },
+ readOnly: true
+ },
+ {
+ name: "pageup",
+ description: "Page up",
+ bindKey: bindKey(null, "Option-PageUp"),
+ exec: function(editor) {
+ editor.scrollPageUp();
+ },
+ readOnly: true
+ },
+ {
+ name: "gotopageup",
+ description: "Go to page up",
+ bindKey: "PageUp",
+ exec: function(editor) {
+ editor.gotoPageUp();
+ },
+ readOnly: true
+ },
+ {
+ name: "scrollup",
+ description: "Scroll up",
+ bindKey: bindKey("Ctrl-Up", null),
+ exec: function(e) {
+ e.renderer.scrollBy(0, -2 * e.renderer.layerConfig.lineHeight);
+ },
+ readOnly: true
+ },
+ {
+ name: "scrolldown",
+ description: "Scroll down",
+ bindKey: bindKey("Ctrl-Down", null),
+ exec: function(e) {
+ e.renderer.scrollBy(0, 2 * e.renderer.layerConfig.lineHeight);
+ },
+ readOnly: true
+ },
+ {
+ name: "selectlinestart",
+ description: "Select line start",
+ bindKey: "Shift-Home",
+ exec: function(editor) {
+ editor.getSelection().selectLineStart();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "selectlineend",
+ description: "Select line end",
+ bindKey: "Shift-End",
+ exec: function(editor) {
+ editor.getSelection().selectLineEnd();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "togglerecording",
+ description: "Toggle recording",
+ bindKey: bindKey("Ctrl-Alt-E", "Command-Option-E"),
+ exec: function(editor) {
+ editor.commands.toggleRecording(editor);
+ },
+ readOnly: true
+ },
+ {
+ name: "replaymacro",
+ description: "Replay macro",
+ bindKey: bindKey("Ctrl-Shift-E", "Command-Shift-E"),
+ exec: function(editor) {
+ editor.commands.replay(editor);
+ },
+ readOnly: true
+ },
+ {
+ name: "jumptomatching",
+ description: "Jump to matching",
+ bindKey: bindKey("Ctrl-\\|Ctrl-P", "Command-\\"),
+ exec: function(editor) {
+ editor.jumpToMatching();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "animate",
+ readOnly: true
+ },
+ {
+ name: "selecttomatching",
+ description: "Select to matching",
+ bindKey: bindKey("Ctrl-Shift-\\|Ctrl-Shift-P", "Command-Shift-\\"),
+ exec: function(editor) {
+ editor.jumpToMatching(true);
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "animate",
+ readOnly: true
+ },
+ {
+ name: "expandToMatching",
+ description: "Expand to matching",
+ bindKey: bindKey("Ctrl-Shift-M", "Ctrl-Shift-M"),
+ exec: function(editor) {
+ editor.jumpToMatching(true, true);
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "animate",
+ readOnly: true
+ },
+ {
+ name: "passKeysToBrowser",
+ description: "Pass keys to browser",
+ bindKey: bindKey(null, null),
+ exec: function() {},
+ passEvent: true,
+ readOnly: true
+ },
+ {
+ name: "copy",
+ description: "Copy",
+ exec: function(editor) {},
+ readOnly: true
+ },
+ {
+ name: "cut",
+ description: "Cut",
+ exec: function(editor) {
+ var cutLine =
+ editor.$copyWithEmptySelection && editor.selection.isEmpty();
+ var range = cutLine
+ ? editor.selection.getLineRange()
+ : editor.selection.getRange();
+ editor._emit("cut", range);
+
+ if (!range.isEmpty()) editor.session.remove(range);
+ editor.clearSelection();
+ },
+ scrollIntoView: "cursor",
+ multiSelectAction: "forEach"
+ },
+ {
+ name: "paste",
+ description: "Paste",
+ exec: function(editor, args) {
+ editor.$handlePaste(args);
+ },
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "removeline",
+ description: "Remove line",
+ bindKey: bindKey("Ctrl-D", "Command-D"),
+ exec: function(editor) {
+ editor.removeLines();
+ },
+ scrollIntoView: "cursor",
+ multiSelectAction: "forEachLine"
+ },
+ {
+ name: "duplicateSelection",
+ description: "Duplicate selection",
+ bindKey: bindKey("Ctrl-Shift-D", "Command-Shift-D"),
+ exec: function(editor) {
+ editor.duplicateSelection();
+ },
+ scrollIntoView: "cursor",
+ multiSelectAction: "forEach"
+ },
+ {
+ name: "sortlines",
+ description: "Sort lines",
+ bindKey: bindKey("Ctrl-Alt-S", "Command-Alt-S"),
+ exec: function(editor) {
+ editor.sortLines();
+ },
+ scrollIntoView: "selection",
+ multiSelectAction: "forEachLine"
+ },
+ {
+ name: "togglecomment",
+ description: "Toggle comment",
+ bindKey: bindKey("Ctrl-/", "Command-/"),
+ exec: function(editor) {
+ editor.toggleCommentLines();
+ },
+ multiSelectAction: "forEachLine",
+ scrollIntoView: "selectionPart"
+ },
+ {
+ name: "toggleBlockComment",
+ description: "Toggle block comment",
+ bindKey: bindKey("Ctrl-Shift-/", "Command-Shift-/"),
+ exec: function(editor) {
+ editor.toggleBlockComment();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "selectionPart"
+ },
+ {
+ name: "modifyNumberUp",
+ description: "Modify number up",
+ bindKey: bindKey("Ctrl-Shift-Up", "Alt-Shift-Up"),
+ exec: function(editor) {
+ editor.modifyNumber(1);
+ },
+ scrollIntoView: "cursor",
+ multiSelectAction: "forEach"
+ },
+ {
+ name: "modifyNumberDown",
+ description: "Modify number down",
+ bindKey: bindKey("Ctrl-Shift-Down", "Alt-Shift-Down"),
+ exec: function(editor) {
+ editor.modifyNumber(-1);
+ },
+ scrollIntoView: "cursor",
+ multiSelectAction: "forEach"
+ },
+ {
+ name: "replace",
+ description: "Replace",
+ bindKey: bindKey("Ctrl-H", "Command-Option-F"),
+ exec: function(editor) {
+ config.loadModule("ace/ext/searchbox", function(e) {
+ e.Search(editor, true);
+ });
+ }
+ },
+ {
+ name: "undo",
+ description: "Undo",
+ bindKey: bindKey("Ctrl-Z", "Command-Z"),
+ exec: function(editor) {
+ editor.undo();
+ }
+ },
+ {
+ name: "redo",
+ description: "Redo",
+ bindKey: bindKey("Ctrl-Shift-Z|Ctrl-Y", "Command-Shift-Z|Command-Y"),
+ exec: function(editor) {
+ editor.redo();
+ }
+ },
+ {
+ name: "copylinesup",
+ description: "Copy lines up",
+ bindKey: bindKey("Alt-Shift-Up", "Command-Option-Up"),
+ exec: function(editor) {
+ editor.copyLinesUp();
+ },
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "movelinesup",
+ description: "Move lines up",
+ bindKey: bindKey("Alt-Up", "Option-Up"),
+ exec: function(editor) {
+ editor.moveLinesUp();
+ },
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "copylinesdown",
+ description: "Copy lines down",
+ bindKey: bindKey("Alt-Shift-Down", "Command-Option-Down"),
+ exec: function(editor) {
+ editor.copyLinesDown();
+ },
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "movelinesdown",
+ description: "Move lines down",
+ bindKey: bindKey("Alt-Down", "Option-Down"),
+ exec: function(editor) {
+ editor.moveLinesDown();
+ },
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "del",
+ description: "Delete",
+ bindKey: bindKey("Delete", "Delete|Ctrl-D|Shift-Delete"),
+ exec: function(editor) {
+ editor.remove("right");
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "backspace",
+ description: "Backspace",
+ bindKey: bindKey(
+ "Shift-Backspace|Backspace",
+ "Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H"
+ ),
+ exec: function(editor) {
+ editor.remove("left");
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "cut_or_delete",
+ description: "Cut or delete",
+ bindKey: bindKey("Shift-Delete", null),
+ exec: function(editor) {
+ if (editor.selection.isEmpty()) {
+ editor.remove("left");
+ } else {
+ return false;
+ }
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "removetolinestart",
+ description: "Remove to line start",
+ bindKey: bindKey("Alt-Backspace", "Command-Backspace"),
+ exec: function(editor) {
+ editor.removeToLineStart();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "removetolineend",
+ description: "Remove to line end",
+ bindKey: bindKey("Alt-Delete", "Ctrl-K|Command-Delete"),
+ exec: function(editor) {
+ editor.removeToLineEnd();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "removetolinestarthard",
+ description: "Remove to line start hard",
+ bindKey: bindKey("Ctrl-Shift-Backspace", null),
+ exec: function(editor) {
+ var range = editor.selection.getRange();
+ range.start.column = 0;
+ editor.session.remove(range);
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "removetolineendhard",
+ description: "Remove to line end hard",
+ bindKey: bindKey("Ctrl-Shift-Delete", null),
+ exec: function(editor) {
+ var range = editor.selection.getRange();
+ range.end.column = Number.MAX_VALUE;
+ editor.session.remove(range);
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "removewordleft",
+ description: "Remove word left",
+ bindKey: bindKey("Ctrl-Backspace", "Alt-Backspace|Ctrl-Alt-Backspace"),
+ exec: function(editor) {
+ editor.removeWordLeft();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "removewordright",
+ description: "Remove word right",
+ bindKey: bindKey("Ctrl-Delete", "Alt-Delete"),
+ exec: function(editor) {
+ editor.removeWordRight();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "outdent",
+ description: "Outdent",
+ bindKey: bindKey("Shift-Tab", "Shift-Tab"),
+ exec: function(editor) {
+ editor.blockOutdent();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "selectionPart"
+ },
+ {
+ name: "indent",
+ description: "Indent",
+ bindKey: bindKey("Tab", "Tab"),
+ exec: function(editor) {
+ editor.indent();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "selectionPart"
+ },
+ {
+ name: "blockoutdent",
+ description: "Block outdent",
+ bindKey: bindKey("Ctrl-[", "Ctrl-["),
+ exec: function(editor) {
+ editor.blockOutdent();
+ },
+ multiSelectAction: "forEachLine",
+ scrollIntoView: "selectionPart"
+ },
+ {
+ name: "blockindent",
+ description: "Block indent",
+ bindKey: bindKey("Ctrl-]", "Ctrl-]"),
+ exec: function(editor) {
+ editor.blockIndent();
+ },
+ multiSelectAction: "forEachLine",
+ scrollIntoView: "selectionPart"
+ },
+ {
+ name: "insertstring",
+ description: "Insert string",
+ exec: function(editor, str) {
+ editor.insert(str);
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "inserttext",
+ description: "Insert text",
+ exec: function(editor, args) {
+ editor.insert(lang.stringRepeat(args.text || "", args.times || 1));
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "splitline",
+ description: "Split line",
+ bindKey: bindKey(null, "Ctrl-O"),
+ exec: function(editor) {
+ editor.splitLine();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "transposeletters",
+ description: "Transpose letters",
+ bindKey: bindKey("Alt-Shift-X", "Ctrl-T"),
+ exec: function(editor) {
+ editor.transposeLetters();
+ },
+ multiSelectAction: function(editor) {
+ editor.transposeSelections(1);
+ },
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "touppercase",
+ description: "To uppercase",
+ bindKey: bindKey("Ctrl-U", "Ctrl-U"),
+ exec: function(editor) {
+ editor.toUpperCase();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "tolowercase",
+ description: "To lowercase",
+ bindKey: bindKey("Ctrl-Shift-U", "Ctrl-Shift-U"),
+ exec: function(editor) {
+ editor.toLowerCase();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "autoindent",
+ description: "Auto Indent",
+ bindKey: bindKey(null, null),
+ exec: function(editor) {
+ editor.autoIndent();
+ },
+ multiSelectAction: "forEachLine",
+ scrollIntoView: "animate"
+ },
+ {
+ name: "expandtoline",
+ description: "Expand to line",
+ bindKey: bindKey("Ctrl-Shift-L", "Command-Shift-L"),
+ exec: function(editor) {
+ var range = editor.selection.getRange();
+
+ range.start.column = range.end.column = 0;
+ range.end.row++;
+ editor.selection.setRange(range, false);
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "joinlines",
+ description: "Join lines",
+ bindKey: bindKey(null, null),
+ exec: function(editor) {
+ var isBackwards = editor.selection.isBackwards();
+ var selectionStart = isBackwards
+ ? editor.selection.getSelectionLead()
+ : editor.selection.getSelectionAnchor();
+ var selectionEnd = isBackwards
+ ? editor.selection.getSelectionAnchor()
+ : editor.selection.getSelectionLead();
+ var firstLineEndCol = editor.session.doc.getLine(selectionStart.row)
+ .length;
+ var selectedText = editor.session.doc.getTextRange(
+ editor.selection.getRange()
+ );
+ var selectedCount = selectedText.replace(/\n\s*/, " ").length;
+ var insertLine = editor.session.doc.getLine(selectionStart.row);
+
+ for (var i = selectionStart.row + 1; i <= selectionEnd.row + 1; i++) {
+ var curLine = lang.stringTrimLeft(
+ lang.stringTrimRight(editor.session.doc.getLine(i))
+ );
+ if (curLine.length !== 0) {
+ curLine = " " + curLine;
+ }
+ insertLine += curLine;
+ }
+
+ if (selectionEnd.row + 1 < editor.session.doc.getLength() - 1) {
+ insertLine += editor.session.doc.getNewLineCharacter();
+ }
+
+ editor.clearSelection();
+ editor.session.doc.replace(
+ new Range(selectionStart.row, 0, selectionEnd.row + 2, 0),
+ insertLine
+ );
+
+ if (selectedCount > 0) {
+ editor.selection.moveCursorTo(
+ selectionStart.row,
+ selectionStart.column
+ );
+ editor.selection.selectTo(
+ selectionStart.row,
+ selectionStart.column + selectedCount
+ );
+ } else {
+ firstLineEndCol =
+ editor.session.doc.getLine(selectionStart.row).length >
+ firstLineEndCol
+ ? firstLineEndCol + 1
+ : firstLineEndCol;
+ editor.selection.moveCursorTo(selectionStart.row, firstLineEndCol);
+ }
+ },
+ multiSelectAction: "forEach",
+ readOnly: true
+ },
+ {
+ name: "invertSelection",
+ description: "Invert selection",
+ bindKey: bindKey(null, null),
+ exec: function(editor) {
+ var endRow = editor.session.doc.getLength() - 1;
+ var endCol = editor.session.doc.getLine(endRow).length;
+ var ranges = editor.selection.rangeList.ranges;
+ var newRanges = [];
+ if (ranges.length < 1) {
+ ranges = [editor.selection.getRange()];
+ }
+
+ for (var i = 0; i < ranges.length; i++) {
+ if (i == ranges.length - 1) {
+ if (
+ !(
+ ranges[i].end.row === endRow &&
+ ranges[i].end.column === endCol
+ )
+ ) {
+ newRanges.push(
+ new Range(
+ ranges[i].end.row,
+ ranges[i].end.column,
+ endRow,
+ endCol
+ )
+ );
+ }
+ }
+
+ if (i === 0) {
+ if (
+ !(ranges[i].start.row === 0 && ranges[i].start.column === 0)
+ ) {
+ newRanges.push(
+ new Range(0, 0, ranges[i].start.row, ranges[i].start.column)
+ );
+ }
+ } else {
+ newRanges.push(
+ new Range(
+ ranges[i - 1].end.row,
+ ranges[i - 1].end.column,
+ ranges[i].start.row,
+ ranges[i].start.column
+ )
+ );
+ }
+ }
+
+ editor.exitMultiSelectMode();
+ editor.clearSelection();
+
+ for (var i = 0; i < newRanges.length; i++) {
+ editor.selection.addRange(newRanges[i], false);
+ }
+ },
+ readOnly: true,
+ scrollIntoView: "none"
+ },
+ {
+ name: "addLineAfter",
+ exec: function(editor) {
+ editor.selection.clearSelection();
+ editor.navigateLineEnd();
+ editor.insert("\n");
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "addLineBefore",
+ exec: function(editor) {
+ editor.selection.clearSelection();
+ var cursor = editor.getCursorPosition();
+ editor.selection.moveTo(cursor.row - 1, Number.MAX_VALUE);
+ editor.insert("\n");
+ if (cursor.row === 0) editor.navigateUp();
+ },
+ multiSelectAction: "forEach",
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "openCommandPallete",
+ description: "Open command pallete",
+ bindKey: bindKey("F1", "F1"),
+ exec: function(editor) {
+ editor.prompt({ $type: "commands" });
+ },
+ readOnly: true
+ },
+ {
+ name: "modeSelect",
+ description: "Change language mode...",
+ bindKey: bindKey(null, null),
+ exec: function(editor) {
+ editor.prompt({ $type: "modes" });
+ },
+ readOnly: true
+ }
+ ];
+ }
+);
+
+ace.define(
+ "ace/editor",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/lib/fixoldbrowsers",
+ "ace/lib/oop",
+ "ace/lib/dom",
+ "ace/lib/lang",
+ "ace/lib/useragent",
+ "ace/keyboard/textinput",
+ "ace/mouse/mouse_handler",
+ "ace/mouse/fold_handler",
+ "ace/keyboard/keybinding",
+ "ace/edit_session",
+ "ace/search",
+ "ace/range",
+ "ace/lib/event_emitter",
+ "ace/commands/command_manager",
+ "ace/commands/default_commands",
+ "ace/config",
+ "ace/token_iterator",
+ "ace/clipboard"
+ ],
+ function(require, exports, module) {
+ "use strict";
+
+ require("./lib/fixoldbrowsers");
+
+ var oop = require("./lib/oop");
+ var dom = require("./lib/dom");
+ var lang = require("./lib/lang");
+ var useragent = require("./lib/useragent");
+ var TextInput = require("./keyboard/textinput").TextInput;
+ var MouseHandler = require("./mouse/mouse_handler").MouseHandler;
+ var FoldHandler = require("./mouse/fold_handler").FoldHandler;
+ var KeyBinding = require("./keyboard/keybinding").KeyBinding;
+ var EditSession = require("./edit_session").EditSession;
+ var Search = require("./search").Search;
+ var Range = require("./range").Range;
+ var EventEmitter = require("./lib/event_emitter").EventEmitter;
+ var CommandManager = require("./commands/command_manager").CommandManager;
+ var defaultCommands = require("./commands/default_commands").commands;
+ var config = require("./config");
+ var TokenIterator = require("./token_iterator").TokenIterator;
+
+ var clipboard = require("./clipboard");
+ var Editor = function(renderer, session, options) {
+ this.$toDestroy = [];
+ var container = renderer.getContainerElement();
+ this.container = container;
+ this.renderer = renderer;
+ this.id = "editor" + ++Editor.$uid;
+
+ this.commands = new CommandManager(
+ useragent.isMac ? "mac" : "win",
+ defaultCommands
+ );
+ if (typeof document == "object") {
+ this.textInput = new TextInput(renderer.getTextAreaContainer(), this);
+ this.renderer.textarea = this.textInput.getElement();
+ this.$mouseHandler = new MouseHandler(this);
+ new FoldHandler(this);
+ }
+
+ this.keyBinding = new KeyBinding(this);
+
+ this.$search = new Search().set({
+ wrap: true
+ });
+
+ this.$historyTracker = this.$historyTracker.bind(this);
+ this.commands.on("exec", this.$historyTracker);
+
+ this.$initOperationListeners();
+
+ this._$emitInputEvent = lang.delayedCall(
+ function() {
+ this._signal("input", {});
+ if (this.session && this.session.bgTokenizer)
+ this.session.bgTokenizer.scheduleStart();
+ }.bind(this)
+ );
+
+ this.on("change", function(_, _self) {
+ _self._$emitInputEvent.schedule(31);
+ });
+
+ this.setSession(
+ session || (options && options.session) || new EditSession("")
+ );
+ config.resetOptions(this);
+ if (options) this.setOptions(options);
+ config._signal("editor", this);
+ };
+
+ Editor.$uid = 0;
+
+ (function() {
+ oop.implement(this, EventEmitter);
+
+ this.$initOperationListeners = function() {
+ this.commands.on("exec", this.startOperation.bind(this), true);
+ this.commands.on("afterExec", this.endOperation.bind(this), true);
+
+ this.$opResetTimer = lang.delayedCall(
+ this.endOperation.bind(this, true)
+ );
+ this.on(
+ "change",
+ function() {
+ if (!this.curOp) {
+ this.startOperation();
+ this.curOp.selectionBefore = this.$lastSel;
+ }
+ this.curOp.docChanged = true;
+ }.bind(this),
+ true
+ );
+
+ this.on(
+ "changeSelection",
+ function() {
+ if (!this.curOp) {
+ this.startOperation();
+ this.curOp.selectionBefore = this.$lastSel;
+ }
+ this.curOp.selectionChanged = true;
+ }.bind(this),
+ true
+ );
+ };
+
+ this.curOp = null;
+ this.prevOp = {};
+ this.startOperation = function(commandEvent) {
+ if (this.curOp) {
+ if (!commandEvent || this.curOp.command) return;
+ this.prevOp = this.curOp;
+ }
+ if (!commandEvent) {
+ this.previousCommand = null;
+ commandEvent = {};
+ }
+
+ this.$opResetTimer.schedule();
+ this.curOp = this.session.curOp = {
+ command: commandEvent.command || {},
+ args: commandEvent.args,
+ scrollTop: this.renderer.scrollTop
+ };
+ this.curOp.selectionBefore = this.selection.toJSON();
+ };
+
+ this.endOperation = function(e) {
+ if (this.curOp && this.session) {
+ if ((e && e.returnValue === false) || !this.session)
+ return (this.curOp = null);
+ if (
+ e == true &&
+ this.curOp.command &&
+ this.curOp.command.name == "mouse"
+ )
+ return;
+ this._signal("beforeEndOperation");
+ if (!this.curOp) return;
+ var command = this.curOp.command;
+ var scrollIntoView = command && command.scrollIntoView;
+ if (scrollIntoView) {
+ switch (scrollIntoView) {
+ case "center-animate":
+ scrollIntoView = "animate";
+ case "center":
+ this.renderer.scrollCursorIntoView(null, 0.5);
+ break;
+ case "animate":
+ case "cursor":
+ this.renderer.scrollCursorIntoView();
+ break;
+ case "selectionPart":
+ var range = this.selection.getRange();
+ var config = this.renderer.layerConfig;
+ if (
+ range.start.row >= config.lastRow ||
+ range.end.row <= config.firstRow
+ ) {
+ this.renderer.scrollSelectionIntoView(
+ this.selection.anchor,
+ this.selection.lead
+ );
+ }
+ break;
+ default:
+ break;
+ }
+ if (scrollIntoView == "animate")
+ this.renderer.animateScrolling(this.curOp.scrollTop);
+ }
+ var sel = this.selection.toJSON();
+ this.curOp.selectionAfter = sel;
+ this.$lastSel = this.selection.toJSON();
+ this.session.getUndoManager().addSelection(sel);
+ this.prevOp = this.curOp;
+ this.curOp = null;
+ }
+ };
+ this.$mergeableCommands = ["backspace", "del", "insertstring"];
+ this.$historyTracker = function(e) {
+ if (!this.$mergeUndoDeltas) return;
+
+ var prev = this.prevOp;
+ var mergeableCommands = this.$mergeableCommands;
+ var shouldMerge = prev.command && e.command.name == prev.command.name;
+ if (e.command.name == "insertstring") {
+ var text = e.args;
+ if (this.mergeNextCommand === undefined) this.mergeNextCommand = true;
+
+ shouldMerge =
+ shouldMerge &&
+ this.mergeNextCommand && // previous command allows to coalesce with
+ (!/\s/.test(text) || /\s/.test(prev.args)); // previous insertion was of same type
+
+ this.mergeNextCommand = true;
+ } else {
+ shouldMerge =
+ shouldMerge && mergeableCommands.indexOf(e.command.name) !== -1; // the command is mergeable
+ }
+
+ if (
+ this.$mergeUndoDeltas != "always" &&
+ Date.now() - this.sequenceStartTime > 2000
+ ) {
+ shouldMerge = false; // the sequence is too long
+ }
+
+ if (shouldMerge) this.session.mergeUndoDeltas = true;
+ else if (mergeableCommands.indexOf(e.command.name) !== -1)
+ this.sequenceStartTime = Date.now();
+ };
+ this.setKeyboardHandler = function(keyboardHandler, cb) {
+ if (
+ keyboardHandler &&
+ typeof keyboardHandler === "string" &&
+ keyboardHandler != "ace"
+ ) {
+ this.$keybindingId = keyboardHandler;
+ var _self = this;
+ config.loadModule(["keybinding", keyboardHandler], function(module) {
+ if (_self.$keybindingId == keyboardHandler)
+ _self.keyBinding.setKeyboardHandler(module && module.handler);
+ cb && cb();
+ });
+ } else {
+ this.$keybindingId = null;
+ this.keyBinding.setKeyboardHandler(keyboardHandler);
+ cb && cb();
+ }
+ };
+ this.getKeyboardHandler = function() {
+ return this.keyBinding.getKeyboardHandler();
+ };
+ this.setSession = function(session) {
+ if (this.session == session) return;
+ if (this.curOp) this.endOperation();
+ this.curOp = {};
+
+ var oldSession = this.session;
+ if (oldSession) {
+ this.session.off("change", this.$onDocumentChange);
+ this.session.off("changeMode", this.$onChangeMode);
+ this.session.off("tokenizerUpdate", this.$onTokenizerUpdate);
+ this.session.off("changeTabSize", this.$onChangeTabSize);
+ this.session.off("changeWrapLimit", this.$onChangeWrapLimit);
+ this.session.off("changeWrapMode", this.$onChangeWrapMode);
+ this.session.off("changeFold", this.$onChangeFold);
+ this.session.off("changeFrontMarker", this.$onChangeFrontMarker);
+ this.session.off("changeBackMarker", this.$onChangeBackMarker);
+ this.session.off("changeBreakpoint", this.$onChangeBreakpoint);
+ this.session.off("changeAnnotation", this.$onChangeAnnotation);
+ this.session.off("changeOverwrite", this.$onCursorChange);
+ this.session.off("changeScrollTop", this.$onScrollTopChange);
+ this.session.off("changeScrollLeft", this.$onScrollLeftChange);
+
+ var selection = this.session.getSelection();
+ selection.off("changeCursor", this.$onCursorChange);
+ selection.off("changeSelection", this.$onSelectionChange);
+ }
+
+ this.session = session;
+ if (session) {
+ this.$onDocumentChange = this.onDocumentChange.bind(this);
+ session.on("change", this.$onDocumentChange);
+ this.renderer.setSession(session);
+
+ this.$onChangeMode = this.onChangeMode.bind(this);
+ session.on("changeMode", this.$onChangeMode);
+
+ this.$onTokenizerUpdate = this.onTokenizerUpdate.bind(this);
+ session.on("tokenizerUpdate", this.$onTokenizerUpdate);
+
+ this.$onChangeTabSize = this.renderer.onChangeTabSize.bind(
+ this.renderer
+ );
+ session.on("changeTabSize", this.$onChangeTabSize);
+
+ this.$onChangeWrapLimit = this.onChangeWrapLimit.bind(this);
+ session.on("changeWrapLimit", this.$onChangeWrapLimit);
+
+ this.$onChangeWrapMode = this.onChangeWrapMode.bind(this);
+ session.on("changeWrapMode", this.$onChangeWrapMode);
+
+ this.$onChangeFold = this.onChangeFold.bind(this);
+ session.on("changeFold", this.$onChangeFold);
+
+ this.$onChangeFrontMarker = this.onChangeFrontMarker.bind(this);
+ this.session.on("changeFrontMarker", this.$onChangeFrontMarker);
+
+ this.$onChangeBackMarker = this.onChangeBackMarker.bind(this);
+ this.session.on("changeBackMarker", this.$onChangeBackMarker);
+
+ this.$onChangeBreakpoint = this.onChangeBreakpoint.bind(this);
+ this.session.on("changeBreakpoint", this.$onChangeBreakpoint);
+
+ this.$onChangeAnnotation = this.onChangeAnnotation.bind(this);
+ this.session.on("changeAnnotation", this.$onChangeAnnotation);
+
+ this.$onCursorChange = this.onCursorChange.bind(this);
+ this.session.on("changeOverwrite", this.$onCursorChange);
+
+ this.$onScrollTopChange = this.onScrollTopChange.bind(this);
+ this.session.on("changeScrollTop", this.$onScrollTopChange);
+
+ this.$onScrollLeftChange = this.onScrollLeftChange.bind(this);
+ this.session.on("changeScrollLeft", this.$onScrollLeftChange);
+
+ this.selection = session.getSelection();
+ this.selection.on("changeCursor", this.$onCursorChange);
+
+ this.$onSelectionChange = this.onSelectionChange.bind(this);
+ this.selection.on("changeSelection", this.$onSelectionChange);
+
+ this.onChangeMode();
+
+ this.onCursorChange();
+
+ this.onScrollTopChange();
+ this.onScrollLeftChange();
+ this.onSelectionChange();
+ this.onChangeFrontMarker();
+ this.onChangeBackMarker();
+ this.onChangeBreakpoint();
+ this.onChangeAnnotation();
+ this.session.getUseWrapMode() && this.renderer.adjustWrapLimit();
+ this.renderer.updateFull();
+ } else {
+ this.selection = null;
+ this.renderer.setSession(session);
+ }
+
+ this._signal("changeSession", {
+ session: session,
+ oldSession: oldSession
+ });
+
+ this.curOp = null;
+
+ oldSession && oldSession._signal("changeEditor", { oldEditor: this });
+ session && session._signal("changeEditor", { editor: this });
+
+ if (session && session.bgTokenizer) session.bgTokenizer.scheduleStart();
+ };
+ this.getSession = function() {
+ return this.session;
+ };
+ this.setValue = function(val, cursorPos) {
+ this.session.doc.setValue(val);
+
+ if (!cursorPos) this.selectAll();
+ else if (cursorPos == 1) this.navigateFileEnd();
+ else if (cursorPos == -1) this.navigateFileStart();
+
+ return val;
+ };
+ this.getValue = function() {
+ return this.session.getValue();
+ };
+ this.getSelection = function() {
+ return this.selection;
+ };
+ this.resize = function(force) {
+ this.renderer.onResize(force);
+ };
+ this.setTheme = function(theme, cb) {
+ this.renderer.setTheme(theme, cb);
+ };
+ this.getTheme = function() {
+ return this.renderer.getTheme();
+ };
+ this.setStyle = function(style) {
+ this.renderer.setStyle(style);
+ };
+ this.unsetStyle = function(style) {
+ this.renderer.unsetStyle(style);
+ };
+ this.getFontSize = function() {
+ return (
+ this.getOption("fontSize") ||
+ dom.computedStyle(this.container).fontSize
+ );
+ };
+ this.setFontSize = function(size) {
+ this.setOption("fontSize", size);
+ };
+
+ this.$highlightBrackets = function() {
+ if (this.$highlightPending) {
+ return;
+ }
+ var self = this;
+ this.$highlightPending = true;
+ setTimeout(function() {
+ self.$highlightPending = false;
+ var session = self.session;
+ if (!session || !session.bgTokenizer) return;
+ if (session.$bracketHighlight) {
+ session.$bracketHighlight.markerIds.forEach(function(id) {
+ session.removeMarker(id);
+ });
+ session.$bracketHighlight = null;
+ }
+ var ranges = session.getMatchingBracketRanges(
+ self.getCursorPosition()
+ );
+ if (!ranges && session.$mode.getMatching)
+ ranges = session.$mode.getMatching(self.session);
+ if (!ranges) return;
+
+ var markerType = "ace_bracket";
+ if (!Array.isArray(ranges)) {
+ ranges = [ranges];
+ } else if (ranges.length == 1) {
+ markerType = "ace_error_bracket";
+ }
+ if (ranges.length == 2) {
+ if (Range.comparePoints(ranges[0].end, ranges[1].start) == 0)
+ ranges = [Range.fromPoints(ranges[0].start, ranges[1].end)];
+ else if (Range.comparePoints(ranges[0].start, ranges[1].end) == 0)
+ ranges = [Range.fromPoints(ranges[1].start, ranges[0].end)];
+ }
+
+ session.$bracketHighlight = {
+ ranges: ranges,
+ markerIds: ranges.map(function(range) {
+ return session.addMarker(range, markerType, "text");
+ })
+ };
+ }, 50);
+ };
+ this.$highlightTags = function() {
+ if (this.$highlightTagPending) return;
+ var self = this;
+ this.$highlightTagPending = true;
+ setTimeout(function() {
+ self.$highlightTagPending = false;
+
+ var session = self.session;
+ if (!session || !session.bgTokenizer) return;
+
+ var pos = self.getCursorPosition();
+ var iterator = new TokenIterator(self.session, pos.row, pos.column);
+ var token = iterator.getCurrentToken();
+
+ if (!token || !/\b(?:tag-open|tag-name)/.test(token.type)) {
+ session.removeMarker(session.$tagHighlight);
+ session.$tagHighlight = null;
+ return;
+ }
+
+ if (token.type.indexOf("tag-open") != -1) {
+ token = iterator.stepForward();
+ if (!token) return;
+ }
+
+ var tag = token.value;
+ var depth = 0;
+ var prevToken = iterator.stepBackward();
+
+ if (prevToken.value == "<") {
+ do {
+ prevToken = token;
+ token = iterator.stepForward();
+
+ if (
+ token &&
+ token.value === tag &&
+ token.type.indexOf("tag-name") !== -1
+ ) {
+ if (prevToken.value === "<") {
+ depth++;
+ } else if (prevToken.value === "") {
+ depth--;
+ }
+ }
+ } while (token && depth >= 0);
+ } else {
+ do {
+ token = prevToken;
+ prevToken = iterator.stepBackward();
+
+ if (
+ token &&
+ token.value === tag &&
+ token.type.indexOf("tag-name") !== -1
+ ) {
+ if (prevToken.value === "<") {
+ depth++;
+ } else if (prevToken.value === "") {
+ depth--;
+ }
+ }
+ } while (prevToken && depth <= 0);
+ iterator.stepForward();
+ }
+
+ if (!token) {
+ session.removeMarker(session.$tagHighlight);
+ session.$tagHighlight = null;
+ return;
+ }
+
+ var row = iterator.getCurrentTokenRow();
+ var column = iterator.getCurrentTokenColumn();
+ var range = new Range(row, column, row, column + token.value.length);
+ var sbm = session.$backMarkers[session.$tagHighlight];
+ if (
+ session.$tagHighlight &&
+ sbm != undefined &&
+ range.compareRange(sbm.range) !== 0
+ ) {
+ session.removeMarker(session.$tagHighlight);
+ session.$tagHighlight = null;
+ }
+
+ if (!session.$tagHighlight)
+ session.$tagHighlight = session.addMarker(
+ range,
+ "ace_bracket",
+ "text"
+ );
+ }, 50);
+ };
+ this.focus = function() {
+ var _self = this;
+ setTimeout(function() {
+ if (!_self.isFocused()) _self.textInput.focus();
+ });
+ this.textInput.focus();
+ };
+ this.isFocused = function() {
+ return this.textInput.isFocused();
+ };
+ this.blur = function() {
+ this.textInput.blur();
+ };
+ this.onFocus = function(e) {
+ if (this.$isFocused) return;
+ this.$isFocused = true;
+ this.renderer.showCursor();
+ this.renderer.visualizeFocus();
+ this._emit("focus", e);
+ };
+ this.onBlur = function(e) {
+ if (!this.$isFocused) return;
+ this.$isFocused = false;
+ this.renderer.hideCursor();
+ this.renderer.visualizeBlur();
+ this._emit("blur", e);
+ };
+
+ this.$cursorChange = function() {
+ this.renderer.updateCursor();
+ this.$highlightBrackets();
+ this.$highlightTags();
+ this.$updateHighlightActiveLine();
+ };
+ this.onDocumentChange = function(delta) {
+ var wrap = this.session.$useWrapMode;
+ var lastRow =
+ delta.start.row == delta.end.row ? delta.end.row : Infinity;
+ this.renderer.updateLines(delta.start.row, lastRow, wrap);
+
+ this._signal("change", delta);
+ this.$cursorChange();
+ };
+
+ this.onTokenizerUpdate = function(e) {
+ var rows = e.data;
+ this.renderer.updateLines(rows.first, rows.last);
+ };
+
+ this.onScrollTopChange = function() {
+ this.renderer.scrollToY(this.session.getScrollTop());
+ };
+
+ this.onScrollLeftChange = function() {
+ this.renderer.scrollToX(this.session.getScrollLeft());
+ };
+ this.onCursorChange = function() {
+ this.$cursorChange();
+ this._signal("changeSelection");
+ };
+
+ this.$updateHighlightActiveLine = function() {
+ var session = this.getSession();
+
+ var highlight;
+ if (this.$highlightActiveLine) {
+ if (this.$selectionStyle != "line" || !this.selection.isMultiLine())
+ highlight = this.getCursorPosition();
+ if (
+ this.renderer.theme &&
+ this.renderer.theme.$selectionColorConflict &&
+ !this.selection.isEmpty()
+ )
+ highlight = false;
+ if (
+ this.renderer.$maxLines &&
+ this.session.getLength() === 1 &&
+ !(this.renderer.$minLines > 1)
+ )
+ highlight = false;
+ }
+
+ if (session.$highlightLineMarker && !highlight) {
+ session.removeMarker(session.$highlightLineMarker.id);
+ session.$highlightLineMarker = null;
+ } else if (!session.$highlightLineMarker && highlight) {
+ var range = new Range(
+ highlight.row,
+ highlight.column,
+ highlight.row,
+ Infinity
+ );
+ range.id = session.addMarker(range, "ace_active-line", "screenLine");
+ session.$highlightLineMarker = range;
+ } else if (highlight) {
+ session.$highlightLineMarker.start.row = highlight.row;
+ session.$highlightLineMarker.end.row = highlight.row;
+ session.$highlightLineMarker.start.column = highlight.column;
+ session._signal("changeBackMarker");
+ }
+ };
+
+ this.onSelectionChange = function(e) {
+ var session = this.session;
+
+ if (session.$selectionMarker) {
+ session.removeMarker(session.$selectionMarker);
+ }
+ session.$selectionMarker = null;
+
+ if (!this.selection.isEmpty()) {
+ var range = this.selection.getRange();
+ var style = this.getSelectionStyle();
+ session.$selectionMarker = session.addMarker(
+ range,
+ "ace_selection",
+ style
+ );
+ } else {
+ this.$updateHighlightActiveLine();
+ }
+
+ var re =
+ this.$highlightSelectedWord && this.$getSelectionHighLightRegexp();
+ this.session.highlight(re);
+
+ this._signal("changeSelection");
+ };
+
+ this.$getSelectionHighLightRegexp = function() {
+ var session = this.session;
+
+ var selection = this.getSelectionRange();
+ if (selection.isEmpty() || selection.isMultiLine()) return;
+
+ var startColumn = selection.start.column;
+ var endColumn = selection.end.column;
+ var line = session.getLine(selection.start.row);
+
+ var needle = line.substring(startColumn, endColumn);
+ if (needle.length > 5000 || !/[\w\d]/.test(needle)) return;
+
+ var re = this.$search.$assembleRegExp({
+ wholeWord: true,
+ caseSensitive: true,
+ needle: needle
+ });
+
+ var wordWithBoundary = line.substring(startColumn - 1, endColumn + 1);
+ if (!re.test(wordWithBoundary)) return;
+
+ return re;
+ };
+
+ this.onChangeFrontMarker = function() {
+ this.renderer.updateFrontMarkers();
+ };
+
+ this.onChangeBackMarker = function() {
+ this.renderer.updateBackMarkers();
+ };
+
+ this.onChangeBreakpoint = function() {
+ this.renderer.updateBreakpoints();
+ };
+
+ this.onChangeAnnotation = function() {
+ this.renderer.setAnnotations(this.session.getAnnotations());
+ };
+
+ this.onChangeMode = function(e) {
+ this.renderer.updateText();
+ this._emit("changeMode", e);
+ };
+
+ this.onChangeWrapLimit = function() {
+ this.renderer.updateFull();
+ };
+
+ this.onChangeWrapMode = function() {
+ this.renderer.onResize(true);
+ };
+
+ this.onChangeFold = function() {
+ this.$updateHighlightActiveLine();
+ this.renderer.updateFull();
+ };
+ this.getSelectedText = function() {
+ return this.session.getTextRange(this.getSelectionRange());
+ };
+ this.getCopyText = function() {
+ var text = this.getSelectedText();
+ var nl = this.session.doc.getNewLineCharacter();
+ var copyLine = false;
+ if (!text && this.$copyWithEmptySelection) {
+ copyLine = true;
+ var ranges = this.selection.getAllRanges();
+ for (var i = 0; i < ranges.length; i++) {
+ var range = ranges[i];
+ if (i && ranges[i - 1].start.row == range.start.row) continue;
+ text += this.session.getLine(range.start.row) + nl;
+ }
+ }
+ var e = { text: text };
+ this._signal("copy", e);
+ clipboard.lineMode = copyLine ? e.text : "";
+ return e.text;
+ };
+ this.onCopy = function() {
+ this.commands.exec("copy", this);
+ };
+ this.onCut = function() {
+ this.commands.exec("cut", this);
+ };
+ this.onPaste = function(text, event) {
+ var e = { text: text, event: event };
+ this.commands.exec("paste", this, e);
+ };
+
+ this.$handlePaste = function(e) {
+ if (typeof e == "string") e = { text: e };
+ this._signal("paste", e);
+ var text = e.text;
+
+ var lineMode = text == clipboard.lineMode;
+ var session = this.session;
+ if (!this.inMultiSelectMode || this.inVirtualSelectionMode) {
+ if (lineMode)
+ session.insert({ row: this.selection.lead.row, column: 0 }, text);
+ else this.insert(text);
+ } else if (lineMode) {
+ this.selection.rangeList.ranges.forEach(function(range) {
+ session.insert({ row: range.start.row, column: 0 }, text);
+ });
+ } else {
+ var lines = text.split(/\r\n|\r|\n/);
+ var ranges = this.selection.rangeList.ranges;
+
+ var isFullLine = lines.length == 2 && (!lines[0] || !lines[1]);
+ if (lines.length != ranges.length || isFullLine)
+ return this.commands.exec("insertstring", this, text);
+
+ for (var i = ranges.length; i--; ) {
+ var range = ranges[i];
+ if (!range.isEmpty()) session.remove(range);
+
+ session.insert(range.start, lines[i]);
+ }
+ }
+ };
+
+ this.execCommand = function(command, args) {
+ return this.commands.exec(command, this, args);
+ };
+ this.insert = function(text, pasted) {
+ var session = this.session;
+ var mode = session.getMode();
+ var cursor = this.getCursorPosition();
+
+ if (this.getBehavioursEnabled() && !pasted) {
+ var transform = mode.transformAction(
+ session.getState(cursor.row),
+ "insertion",
+ this,
+ session,
+ text
+ );
+ if (transform) {
+ if (text !== transform.text) {
+ if (!this.inVirtualSelectionMode) {
+ this.session.mergeUndoDeltas = false;
+ this.mergeNextCommand = false;
+ }
+ }
+ text = transform.text;
+ }
+ }
+
+ if (text == "\t") text = this.session.getTabString();
+ if (!this.selection.isEmpty()) {
+ var range = this.getSelectionRange();
+ cursor = this.session.remove(range);
+ this.clearSelection();
+ } else if (this.session.getOverwrite() && text.indexOf("\n") == -1) {
+ var range = new Range.fromPoints(cursor, cursor);
+ range.end.column += text.length;
+ this.session.remove(range);
+ }
+
+ if (text == "\n" || text == "\r\n") {
+ var line = session.getLine(cursor.row);
+ if (cursor.column > line.search(/\S|$/)) {
+ var d = line.substr(cursor.column).search(/\S|$/);
+ session.doc.removeInLine(
+ cursor.row,
+ cursor.column,
+ cursor.column + d
+ );
+ }
+ }
+ this.clearSelection();
+
+ var start = cursor.column;
+ var lineState = session.getState(cursor.row);
+ var line = session.getLine(cursor.row);
+ var shouldOutdent = mode.checkOutdent(lineState, line, text);
+ session.insert(cursor, text);
+
+ if (transform && transform.selection) {
+ if (transform.selection.length == 2) {
+ // Transform relative to the current column
+ this.selection.setSelectionRange(
+ new Range(
+ cursor.row,
+ start + transform.selection[0],
+ cursor.row,
+ start + transform.selection[1]
+ )
+ );
+ } else {
+ // Transform relative to the current row.
+ this.selection.setSelectionRange(
+ new Range(
+ cursor.row + transform.selection[0],
+ transform.selection[1],
+ cursor.row + transform.selection[2],
+ transform.selection[3]
+ )
+ );
+ }
+ }
+ if (this.$enableAutoIndent) {
+ if (session.getDocument().isNewLine(text)) {
+ var lineIndent = mode.getNextLineIndent(
+ lineState,
+ line.slice(0, cursor.column),
+ session.getTabString()
+ );
+
+ session.insert({ row: cursor.row + 1, column: 0 }, lineIndent);
+ }
+ if (shouldOutdent) mode.autoOutdent(lineState, session, cursor.row);
+ }
+ };
+
+ this.autoIndent = function() {
+ var session = this.session;
+ var mode = session.getMode();
+
+ var startRow, endRow;
+ if (this.selection.isEmpty()) {
+ startRow = 0;
+ endRow = session.doc.getLength() - 1;
+ } else {
+ var selectedRange = this.getSelectionRange();
+
+ startRow = selectedRange.start.row;
+ endRow = selectedRange.end.row;
+ }
+
+ var prevLineState = "";
+ var prevLine = "";
+ var lineIndent = "";
+ var line, currIndent, range;
+ var tab = session.getTabString();
+
+ for (var row = startRow; row <= endRow; row++) {
+ if (row > 0) {
+ prevLineState = session.getState(row - 1);
+ prevLine = session.getLine(row - 1);
+ lineIndent = mode.getNextLineIndent(prevLineState, prevLine, tab);
+ }
+
+ line = session.getLine(row);
+ currIndent = mode.$getIndent(line);
+ if (lineIndent !== currIndent) {
+ if (currIndent.length > 0) {
+ range = new Range(row, 0, row, currIndent.length);
+ session.remove(range);
+ }
+ if (lineIndent.length > 0) {
+ session.insert({ row: row, column: 0 }, lineIndent);
+ }
+ }
+
+ mode.autoOutdent(prevLineState, session, row);
+ }
+ };
+
+ this.onTextInput = function(text, composition) {
+ if (!composition) return this.keyBinding.onTextInput(text);
+
+ this.startOperation({ command: { name: "insertstring" } });
+ var applyComposition = this.applyComposition.bind(
+ this,
+ text,
+ composition
+ );
+ if (this.selection.rangeCount) this.forEachSelection(applyComposition);
+ else applyComposition();
+ this.endOperation();
+ };
+
+ this.applyComposition = function(text, composition) {
+ if (composition.extendLeft || composition.extendRight) {
+ var r = this.selection.getRange();
+ r.start.column -= composition.extendLeft;
+ r.end.column += composition.extendRight;
+ if (r.start.column < 0) {
+ r.start.row--;
+ r.start.column += this.session.getLine(r.start.row).length + 1;
+ }
+ this.selection.setRange(r);
+ if (!text && !r.isEmpty()) this.remove();
+ }
+ if (text || !this.selection.isEmpty()) this.insert(text, true);
+ if (composition.restoreStart || composition.restoreEnd) {
+ var r = this.selection.getRange();
+ r.start.column -= composition.restoreStart;
+ r.end.column -= composition.restoreEnd;
+ this.selection.setRange(r);
+ }
+ };
+
+ this.onCommandKey = function(e, hashId, keyCode) {
+ return this.keyBinding.onCommandKey(e, hashId, keyCode);
+ };
+ this.setOverwrite = function(overwrite) {
+ this.session.setOverwrite(overwrite);
+ };
+ this.getOverwrite = function() {
+ return this.session.getOverwrite();
+ };
+ this.toggleOverwrite = function() {
+ this.session.toggleOverwrite();
+ };
+ this.setScrollSpeed = function(speed) {
+ this.setOption("scrollSpeed", speed);
+ };
+ this.getScrollSpeed = function() {
+ return this.getOption("scrollSpeed");
+ };
+ this.setDragDelay = function(dragDelay) {
+ this.setOption("dragDelay", dragDelay);
+ };
+ this.getDragDelay = function() {
+ return this.getOption("dragDelay");
+ };
+ this.setSelectionStyle = function(val) {
+ this.setOption("selectionStyle", val);
+ };
+ this.getSelectionStyle = function() {
+ return this.getOption("selectionStyle");
+ };
+ this.setHighlightActiveLine = function(shouldHighlight) {
+ this.setOption("highlightActiveLine", shouldHighlight);
+ };
+ this.getHighlightActiveLine = function() {
+ return this.getOption("highlightActiveLine");
+ };
+ this.setHighlightGutterLine = function(shouldHighlight) {
+ this.setOption("highlightGutterLine", shouldHighlight);
+ };
+
+ this.getHighlightGutterLine = function() {
+ return this.getOption("highlightGutterLine");
+ };
+ this.setHighlightSelectedWord = function(shouldHighlight) {
+ this.setOption("highlightSelectedWord", shouldHighlight);
+ };
+ this.getHighlightSelectedWord = function() {
+ return this.$highlightSelectedWord;
+ };
+
+ this.setAnimatedScroll = function(shouldAnimate) {
+ this.renderer.setAnimatedScroll(shouldAnimate);
+ };
+
+ this.getAnimatedScroll = function() {
+ return this.renderer.getAnimatedScroll();
+ };
+ this.setShowInvisibles = function(showInvisibles) {
+ this.renderer.setShowInvisibles(showInvisibles);
+ };
+ this.getShowInvisibles = function() {
+ return this.renderer.getShowInvisibles();
+ };
+
+ this.setDisplayIndentGuides = function(display) {
+ this.renderer.setDisplayIndentGuides(display);
+ };
+
+ this.getDisplayIndentGuides = function() {
+ return this.renderer.getDisplayIndentGuides();
+ };
+ this.setShowPrintMargin = function(showPrintMargin) {
+ this.renderer.setShowPrintMargin(showPrintMargin);
+ };
+ this.getShowPrintMargin = function() {
+ return this.renderer.getShowPrintMargin();
+ };
+ this.setPrintMarginColumn = function(showPrintMargin) {
+ this.renderer.setPrintMarginColumn(showPrintMargin);
+ };
+ this.getPrintMarginColumn = function() {
+ return this.renderer.getPrintMarginColumn();
+ };
+ this.setReadOnly = function(readOnly) {
+ this.setOption("readOnly", readOnly);
+ };
+ this.getReadOnly = function() {
+ return this.getOption("readOnly");
+ };
+ this.setBehavioursEnabled = function(enabled) {
+ this.setOption("behavioursEnabled", enabled);
+ };
+ this.getBehavioursEnabled = function() {
+ return this.getOption("behavioursEnabled");
+ };
+ this.setWrapBehavioursEnabled = function(enabled) {
+ this.setOption("wrapBehavioursEnabled", enabled);
+ };
+ this.getWrapBehavioursEnabled = function() {
+ return this.getOption("wrapBehavioursEnabled");
+ };
+ this.setShowFoldWidgets = function(show) {
+ this.setOption("showFoldWidgets", show);
+ };
+ this.getShowFoldWidgets = function() {
+ return this.getOption("showFoldWidgets");
+ };
+
+ this.setFadeFoldWidgets = function(fade) {
+ this.setOption("fadeFoldWidgets", fade);
+ };
+
+ this.getFadeFoldWidgets = function() {
+ return this.getOption("fadeFoldWidgets");
+ };
+ this.remove = function(dir) {
+ if (this.selection.isEmpty()) {
+ if (dir == "left") this.selection.selectLeft();
+ else this.selection.selectRight();
+ }
+
+ var range = this.getSelectionRange();
+ if (this.getBehavioursEnabled()) {
+ var session = this.session;
+ var state = session.getState(range.start.row);
+ var new_range = session
+ .getMode()
+ .transformAction(state, "deletion", this, session, range);
+
+ if (range.end.column === 0) {
+ var text = session.getTextRange(range);
+ if (text[text.length - 1] == "\n") {
+ var line = session.getLine(range.end.row);
+ if (/^\s+$/.test(line)) {
+ range.end.column = line.length;
+ }
+ }
+ }
+ if (new_range) range = new_range;
+ }
+
+ this.session.remove(range);
+ this.clearSelection();
+ };
+ this.removeWordRight = function() {
+ if (this.selection.isEmpty()) this.selection.selectWordRight();
+
+ this.session.remove(this.getSelectionRange());
+ this.clearSelection();
+ };
+ this.removeWordLeft = function() {
+ if (this.selection.isEmpty()) this.selection.selectWordLeft();
+
+ this.session.remove(this.getSelectionRange());
+ this.clearSelection();
+ };
+ this.removeToLineStart = function() {
+ if (this.selection.isEmpty()) this.selection.selectLineStart();
+ if (this.selection.isEmpty()) this.selection.selectLeft();
+ this.session.remove(this.getSelectionRange());
+ this.clearSelection();
+ };
+ this.removeToLineEnd = function() {
+ if (this.selection.isEmpty()) this.selection.selectLineEnd();
+
+ var range = this.getSelectionRange();
+ if (
+ range.start.column == range.end.column &&
+ range.start.row == range.end.row
+ ) {
+ range.end.column = 0;
+ range.end.row++;
+ }
+
+ this.session.remove(range);
+ this.clearSelection();
+ };
+ this.splitLine = function() {
+ if (!this.selection.isEmpty()) {
+ this.session.remove(this.getSelectionRange());
+ this.clearSelection();
+ }
+
+ var cursor = this.getCursorPosition();
+ this.insert("\n");
+ this.moveCursorToPosition(cursor);
+ };
+ this.transposeLetters = function() {
+ if (!this.selection.isEmpty()) {
+ return;
+ }
+
+ var cursor = this.getCursorPosition();
+ var column = cursor.column;
+ if (column === 0) return;
+
+ var line = this.session.getLine(cursor.row);
+ var swap, range;
+ if (column < line.length) {
+ swap = line.charAt(column) + line.charAt(column - 1);
+ range = new Range(cursor.row, column - 1, cursor.row, column + 1);
+ } else {
+ swap = line.charAt(column - 1) + line.charAt(column - 2);
+ range = new Range(cursor.row, column - 2, cursor.row, column);
+ }
+ this.session.replace(range, swap);
+ this.session.selection.moveToPosition(range.end);
+ };
+ this.toLowerCase = function() {
+ var originalRange = this.getSelectionRange();
+ if (this.selection.isEmpty()) {
+ this.selection.selectWord();
+ }
+
+ var range = this.getSelectionRange();
+ var text = this.session.getTextRange(range);
+ this.session.replace(range, text.toLowerCase());
+ this.selection.setSelectionRange(originalRange);
+ };
+ this.toUpperCase = function() {
+ var originalRange = this.getSelectionRange();
+ if (this.selection.isEmpty()) {
+ this.selection.selectWord();
+ }
+
+ var range = this.getSelectionRange();
+ var text = this.session.getTextRange(range);
+ this.session.replace(range, text.toUpperCase());
+ this.selection.setSelectionRange(originalRange);
+ };
+ this.indent = function() {
+ var session = this.session;
+ var range = this.getSelectionRange();
+
+ if (range.start.row < range.end.row) {
+ var rows = this.$getSelectedRows();
+ session.indentRows(rows.first, rows.last, "\t");
+ return;
+ } else if (range.start.column < range.end.column) {
+ var text = session.getTextRange(range);
+ if (!/^\s+$/.test(text)) {
+ var rows = this.$getSelectedRows();
+ session.indentRows(rows.first, rows.last, "\t");
+ return;
+ }
+ }
+
+ var line = session.getLine(range.start.row);
+ var position = range.start;
+ var size = session.getTabSize();
+ var column = session.documentToScreenColumn(
+ position.row,
+ position.column
+ );
+
+ if (this.session.getUseSoftTabs()) {
+ var count = size - (column % size);
+ var indentString = lang.stringRepeat(" ", count);
+ } else {
+ var count = column % size;
+ while (line[range.start.column - 1] == " " && count) {
+ range.start.column--;
+ count--;
+ }
+ this.selection.setSelectionRange(range);
+ indentString = "\t";
+ }
+ return this.insert(indentString);
+ };
+ this.blockIndent = function() {
+ var rows = this.$getSelectedRows();
+ this.session.indentRows(rows.first, rows.last, "\t");
+ };
+ this.blockOutdent = function() {
+ var selection = this.session.getSelection();
+ this.session.outdentRows(selection.getRange());
+ };
+ this.sortLines = function() {
+ var rows = this.$getSelectedRows();
+ var session = this.session;
+
+ var lines = [];
+ for (var i = rows.first; i <= rows.last; i++)
+ lines.push(session.getLine(i));
+
+ lines.sort(function(a, b) {
+ if (a.toLowerCase() < b.toLowerCase()) return -1;
+ if (a.toLowerCase() > b.toLowerCase()) return 1;
+ return 0;
+ });
+
+ var deleteRange = new Range(0, 0, 0, 0);
+ for (var i = rows.first; i <= rows.last; i++) {
+ var line = session.getLine(i);
+ deleteRange.start.row = i;
+ deleteRange.end.row = i;
+ deleteRange.end.column = line.length;
+ session.replace(deleteRange, lines[i - rows.first]);
+ }
+ };
+ this.toggleCommentLines = function() {
+ var state = this.session.getState(this.getCursorPosition().row);
+ var rows = this.$getSelectedRows();
+ this.session
+ .getMode()
+ .toggleCommentLines(state, this.session, rows.first, rows.last);
+ };
+
+ this.toggleBlockComment = function() {
+ var cursor = this.getCursorPosition();
+ var state = this.session.getState(cursor.row);
+ var range = this.getSelectionRange();
+ this.session
+ .getMode()
+ .toggleBlockComment(state, this.session, range, cursor);
+ };
+ this.getNumberAt = function(row, column) {
+ var _numberRx = /[\-]?[0-9]+(?:\.[0-9]+)?/g;
+ _numberRx.lastIndex = 0;
+
+ var s = this.session.getLine(row);
+ while (_numberRx.lastIndex < column) {
+ var m = _numberRx.exec(s);
+ if (m.index <= column && m.index + m[0].length >= column) {
+ var number = {
+ value: m[0],
+ start: m.index,
+ end: m.index + m[0].length
+ };
+ return number;
+ }
+ }
+ return null;
+ };
+ this.modifyNumber = function(amount) {
+ var row = this.selection.getCursor().row;
+ var column = this.selection.getCursor().column;
+ var charRange = new Range(row, column - 1, row, column);
+
+ var c = this.session.getTextRange(charRange);
+ if (!isNaN(parseFloat(c)) && isFinite(c)) {
+ var nr = this.getNumberAt(row, column);
+ if (nr) {
+ var fp =
+ nr.value.indexOf(".") >= 0
+ ? nr.start + nr.value.indexOf(".") + 1
+ : nr.end;
+ var decimals = nr.start + nr.value.length - fp;
+
+ var t = parseFloat(nr.value);
+ t *= Math.pow(10, decimals);
+
+ if (fp !== nr.end && column < fp) {
+ amount *= Math.pow(10, nr.end - column - 1);
+ } else {
+ amount *= Math.pow(10, nr.end - column);
+ }
+
+ t += amount;
+ t /= Math.pow(10, decimals);
+ var nnr = t.toFixed(decimals);
+ var replaceRange = new Range(row, nr.start, row, nr.end);
+ this.session.replace(replaceRange, nnr);
+ this.moveCursorTo(
+ row,
+ Math.max(nr.start + 1, column + nnr.length - nr.value.length)
+ );
+ }
+ } else {
+ this.toggleWord();
+ }
+ };
+
+ this.$toggleWordPairs = [
+ ["first", "last"],
+ ["true", "false"],
+ ["yes", "no"],
+ ["width", "height"],
+ ["top", "bottom"],
+ ["right", "left"],
+ ["on", "off"],
+ ["x", "y"],
+ ["get", "set"],
+ ["max", "min"],
+ ["horizontal", "vertical"],
+ ["show", "hide"],
+ ["add", "remove"],
+ ["up", "down"],
+ ["before", "after"],
+ ["even", "odd"],
+ ["in", "out"],
+ ["inside", "outside"],
+ ["next", "previous"],
+ ["increase", "decrease"],
+ ["attach", "detach"],
+ ["&&", "||"],
+ ["==", "!="]
+ ];
+
+ this.toggleWord = function() {
+ var row = this.selection.getCursor().row;
+ var column = this.selection.getCursor().column;
+ this.selection.selectWord();
+ var currentState = this.getSelectedText();
+ var currWordStart = this.selection.getWordRange().start.column;
+ var wordParts = currentState
+ .replace(/([a-z]+|[A-Z]+)(?=[A-Z_]|$)/g, "$1 ")
+ .split(/\s/);
+ var delta = column - currWordStart - 1;
+ if (delta < 0) delta = 0;
+ var curLength = 0,
+ itLength = 0;
+ var that = this;
+ if (currentState.match(/[A-Za-z0-9_]+/)) {
+ wordParts.forEach(function(item, i) {
+ itLength = curLength + item.length;
+ if (delta >= curLength && delta <= itLength) {
+ currentState = item;
+ that.selection.clearSelection();
+ that.moveCursorTo(row, curLength + currWordStart);
+ that.selection.selectTo(row, itLength + currWordStart);
+ }
+ curLength = itLength;
+ });
+ }
+
+ var wordPairs = this.$toggleWordPairs;
+ var reg;
+ for (var i = 0; i < wordPairs.length; i++) {
+ var item = wordPairs[i];
+ for (var j = 0; j <= 1; j++) {
+ var negate = +!j;
+ var firstCondition = currentState.match(
+ new RegExp(
+ "^\\s?_?(" + lang.escapeRegExp(item[j]) + ")\\s?$",
+ "i"
+ )
+ );
+ if (firstCondition) {
+ var secondCondition = currentState.match(
+ new RegExp(
+ "([_]|^|\\s)(" +
+ lang.escapeRegExp(firstCondition[1]) +
+ ")($|\\s)",
+ "g"
+ )
+ );
+ if (secondCondition) {
+ reg = currentState.replace(
+ new RegExp(lang.escapeRegExp(item[j]), "i"),
+ function(result) {
+ var res = item[negate];
+ if (result.toUpperCase() == result) {
+ res = res.toUpperCase();
+ } else if (
+ result.charAt(0).toUpperCase() == result.charAt(0)
+ ) {
+ res =
+ res.substr(0, 0) +
+ item[negate].charAt(0).toUpperCase() +
+ res.substr(1);
+ }
+ return res;
+ }
+ );
+ this.insert(reg);
+ reg = "";
+ }
+ }
+ }
+ }
+ };
+ this.removeLines = function() {
+ var rows = this.$getSelectedRows();
+ this.session.removeFullLines(rows.first, rows.last);
+ this.clearSelection();
+ };
+
+ this.duplicateSelection = function() {
+ var sel = this.selection;
+ var doc = this.session;
+ var range = sel.getRange();
+ var reverse = sel.isBackwards();
+ if (range.isEmpty()) {
+ var row = range.start.row;
+ doc.duplicateLines(row, row);
+ } else {
+ var point = reverse ? range.start : range.end;
+ var endPoint = doc.insert(point, doc.getTextRange(range), false);
+ range.start = point;
+ range.end = endPoint;
+
+ sel.setSelectionRange(range, reverse);
+ }
+ };
+ this.moveLinesDown = function() {
+ this.$moveLines(1, false);
+ };
+ this.moveLinesUp = function() {
+ this.$moveLines(-1, false);
+ };
+ this.moveText = function(range, toPosition, copy) {
+ return this.session.moveText(range, toPosition, copy);
+ };
+ this.copyLinesUp = function() {
+ this.$moveLines(-1, true);
+ };
+ this.copyLinesDown = function() {
+ this.$moveLines(1, true);
+ };
+ this.$moveLines = function(dir, copy) {
+ var rows, moved;
+ var selection = this.selection;
+ if (!selection.inMultiSelectMode || this.inVirtualSelectionMode) {
+ var range = selection.toOrientedRange();
+ rows = this.$getSelectedRows(range);
+ moved = this.session.$moveLines(
+ rows.first,
+ rows.last,
+ copy ? 0 : dir
+ );
+ if (copy && dir == -1) moved = 0;
+ range.moveBy(moved, 0);
+ selection.fromOrientedRange(range);
+ } else {
+ var ranges = selection.rangeList.ranges;
+ selection.rangeList.detach(this.session);
+ this.inVirtualSelectionMode = true;
+
+ var diff = 0;
+ var totalDiff = 0;
+ var l = ranges.length;
+ for (var i = 0; i < l; i++) {
+ var rangeIndex = i;
+ ranges[i].moveBy(diff, 0);
+ rows = this.$getSelectedRows(ranges[i]);
+ var first = rows.first;
+ var last = rows.last;
+ while (++i < l) {
+ if (totalDiff) ranges[i].moveBy(totalDiff, 0);
+ var subRows = this.$getSelectedRows(ranges[i]);
+ if (copy && subRows.first != last) break;
+ else if (!copy && subRows.first > last + 1) break;
+ last = subRows.last;
+ }
+ i--;
+ diff = this.session.$moveLines(first, last, copy ? 0 : dir);
+ if (copy && dir == -1) rangeIndex = i + 1;
+ while (rangeIndex <= i) {
+ ranges[rangeIndex].moveBy(diff, 0);
+ rangeIndex++;
+ }
+ if (!copy) diff = 0;
+ totalDiff += diff;
+ }
+
+ selection.fromOrientedRange(selection.ranges[0]);
+ selection.rangeList.attach(this.session);
+ this.inVirtualSelectionMode = false;
+ }
+ };
+ this.$getSelectedRows = function(range) {
+ range = (range || this.getSelectionRange()).collapseRows();
+
+ return {
+ first: this.session.getRowFoldStart(range.start.row),
+ last: this.session.getRowFoldEnd(range.end.row)
+ };
+ };
+
+ this.onCompositionStart = function(compositionState) {
+ this.renderer.showComposition(compositionState);
+ };
+
+ this.onCompositionUpdate = function(text) {
+ this.renderer.setCompositionText(text);
+ };
+
+ this.onCompositionEnd = function() {
+ this.renderer.hideComposition();
+ };
+ this.getFirstVisibleRow = function() {
+ return this.renderer.getFirstVisibleRow();
+ };
+ this.getLastVisibleRow = function() {
+ return this.renderer.getLastVisibleRow();
+ };
+ this.isRowVisible = function(row) {
+ return (
+ row >= this.getFirstVisibleRow() && row <= this.getLastVisibleRow()
+ );
+ };
+ this.isRowFullyVisible = function(row) {
+ return (
+ row >= this.renderer.getFirstFullyVisibleRow() &&
+ row <= this.renderer.getLastFullyVisibleRow()
+ );
+ };
+ this.$getVisibleRowCount = function() {
+ return (
+ this.renderer.getScrollBottomRow() -
+ this.renderer.getScrollTopRow() +
+ 1
+ );
+ };
+
+ this.$moveByPage = function(dir, select) {
+ var renderer = this.renderer;
+ var config = this.renderer.layerConfig;
+ var rows = dir * Math.floor(config.height / config.lineHeight);
+
+ if (select === true) {
+ this.selection.$moveSelection(function() {
+ this.moveCursorBy(rows, 0);
+ });
+ } else if (select === false) {
+ this.selection.moveCursorBy(rows, 0);
+ this.selection.clearSelection();
+ }
+
+ var scrollTop = renderer.scrollTop;
+
+ renderer.scrollBy(0, rows * config.lineHeight);
+ if (select != null) renderer.scrollCursorIntoView(null, 0.5);
+
+ renderer.animateScrolling(scrollTop);
+ };
+ this.selectPageDown = function() {
+ this.$moveByPage(1, true);
+ };
+ this.selectPageUp = function() {
+ this.$moveByPage(-1, true);
+ };
+ this.gotoPageDown = function() {
+ this.$moveByPage(1, false);
+ };
+ this.gotoPageUp = function() {
+ this.$moveByPage(-1, false);
+ };
+ this.scrollPageDown = function() {
+ this.$moveByPage(1);
+ };
+ this.scrollPageUp = function() {
+ this.$moveByPage(-1);
+ };
+ this.scrollToRow = function(row) {
+ this.renderer.scrollToRow(row);
+ };
+ this.scrollToLine = function(line, center, animate, callback) {
+ this.renderer.scrollToLine(line, center, animate, callback);
+ };
+ this.centerSelection = function() {
+ var range = this.getSelectionRange();
+ var pos = {
+ row: Math.floor(
+ range.start.row + (range.end.row - range.start.row) / 2
+ ),
+ column: Math.floor(
+ range.start.column + (range.end.column - range.start.column) / 2
+ )
+ };
+ this.renderer.alignCursor(pos, 0.5);
+ };
+ this.getCursorPosition = function() {
+ return this.selection.getCursor();
+ };
+ this.getCursorPositionScreen = function() {
+ return this.session.documentToScreenPosition(this.getCursorPosition());
+ };
+ this.getSelectionRange = function() {
+ return this.selection.getRange();
+ };
+ this.selectAll = function() {
+ this.selection.selectAll();
+ };
+ this.clearSelection = function() {
+ this.selection.clearSelection();
+ };
+ this.moveCursorTo = function(row, column) {
+ this.selection.moveCursorTo(row, column);
+ };
+ this.moveCursorToPosition = function(pos) {
+ this.selection.moveCursorToPosition(pos);
+ };
+ this.jumpToMatching = function(select, expand) {
+ var cursor = this.getCursorPosition();
+ var iterator = new TokenIterator(
+ this.session,
+ cursor.row,
+ cursor.column
+ );
+ var prevToken = iterator.getCurrentToken();
+ var token = prevToken || iterator.stepForward();
+
+ if (!token) return;
+ var matchType;
+ var found = false;
+ var depth = {};
+ var i = cursor.column - token.start;
+ var bracketType;
+ var brackets = {
+ ")": "(",
+ "(": "(",
+ "]": "[",
+ "[": "[",
+ "{": "{",
+ "}": "{"
+ };
+
+ do {
+ if (token.value.match(/[{}()\[\]]/g)) {
+ for (; i < token.value.length && !found; i++) {
+ if (!brackets[token.value[i]]) {
+ continue;
+ }
+
+ bracketType =
+ brackets[token.value[i]] +
+ "." +
+ token.type.replace("rparen", "lparen");
+
+ if (isNaN(depth[bracketType])) {
+ depth[bracketType] = 0;
+ }
+
+ switch (token.value[i]) {
+ case "(":
+ case "[":
+ case "{":
+ depth[bracketType]++;
+ break;
+ case ")":
+ case "]":
+ case "}":
+ depth[bracketType]--;
+
+ if (depth[bracketType] === -1) {
+ matchType = "bracket";
+ found = true;
+ }
+ break;
+ }
+ }
+ } else if (token.type.indexOf("tag-name") !== -1) {
+ if (isNaN(depth[token.value])) {
+ depth[token.value] = 0;
+ }
+
+ if (prevToken.value === "<") {
+ depth[token.value]++;
+ } else if (prevToken.value === "") {
+ depth[token.value]--;
+ }
+
+ if (depth[token.value] === -1) {
+ matchType = "tag";
+ found = true;
+ }
+ }
+
+ if (!found) {
+ prevToken = token;
+ token = iterator.stepForward();
+ i = 0;
+ }
+ } while (token && !found);
+ if (!matchType) return;
+
+ var range, pos;
+ if (matchType === "bracket") {
+ range = this.session.getBracketRange(cursor);
+ if (!range) {
+ range = new Range(
+ iterator.getCurrentTokenRow(),
+ iterator.getCurrentTokenColumn() + i - 1,
+ iterator.getCurrentTokenRow(),
+ iterator.getCurrentTokenColumn() + i - 1
+ );
+ pos = range.start;
+ if (
+ expand ||
+ (pos.row === cursor.row &&
+ Math.abs(pos.column - cursor.column) < 2)
+ )
+ range = this.session.getBracketRange(pos);
+ }
+ } else if (matchType === "tag") {
+ if (token && token.type.indexOf("tag-name") !== -1)
+ var tag = token.value;
+ else return;
+
+ range = new Range(
+ iterator.getCurrentTokenRow(),
+ iterator.getCurrentTokenColumn() - 2,
+ iterator.getCurrentTokenRow(),
+ iterator.getCurrentTokenColumn() - 2
+ );
+ if (range.compare(cursor.row, cursor.column) === 0) {
+ found = false;
+ do {
+ token = prevToken;
+ prevToken = iterator.stepBackward();
+
+ if (prevToken) {
+ if (prevToken.type.indexOf("tag-close") !== -1) {
+ range.setEnd(
+ iterator.getCurrentTokenRow(),
+ iterator.getCurrentTokenColumn() + 1
+ );
+ }
+
+ if (
+ token.value === tag &&
+ token.type.indexOf("tag-name") !== -1
+ ) {
+ if (prevToken.value === "<") {
+ depth[tag]++;
+ } else if (prevToken.value === "") {
+ depth[tag]--;
+ }
+
+ if (depth[tag] === 0) found = true;
+ }
+ }
+ } while (prevToken && !found);
+ }
+ if (token && token.type.indexOf("tag-name")) {
+ pos = range.start;
+ if (
+ pos.row == cursor.row &&
+ Math.abs(pos.column - cursor.column) < 2
+ )
+ pos = range.end;
+ }
+ }
+
+ pos = (range && range.cursor) || pos;
+ if (pos) {
+ if (select) {
+ if (range && expand) {
+ this.selection.setRange(range);
+ } else if (range && range.isEqual(this.getSelectionRange())) {
+ this.clearSelection();
+ } else {
+ this.selection.selectTo(pos.row, pos.column);
+ }
+ } else {
+ this.selection.moveTo(pos.row, pos.column);
+ }
+ }
+ };
+ this.gotoLine = function(lineNumber, column, animate) {
+ this.selection.clearSelection();
+ this.session.unfold({ row: lineNumber - 1, column: column || 0 });
+ this.exitMultiSelectMode && this.exitMultiSelectMode();
+ this.moveCursorTo(lineNumber - 1, column || 0);
+
+ if (!this.isRowFullyVisible(lineNumber - 1))
+ this.scrollToLine(lineNumber - 1, true, animate);
+ };
+ this.navigateTo = function(row, column) {
+ this.selection.moveTo(row, column);
+ };
+ this.navigateUp = function(times) {
+ if (this.selection.isMultiLine() && !this.selection.isBackwards()) {
+ var selectionStart = this.selection.anchor.getPosition();
+ return this.moveCursorToPosition(selectionStart);
+ }
+ this.selection.clearSelection();
+ this.selection.moveCursorBy(-times || -1, 0);
+ };
+ this.navigateDown = function(times) {
+ if (this.selection.isMultiLine() && this.selection.isBackwards()) {
+ var selectionEnd = this.selection.anchor.getPosition();
+ return this.moveCursorToPosition(selectionEnd);
+ }
+ this.selection.clearSelection();
+ this.selection.moveCursorBy(times || 1, 0);
+ };
+ this.navigateLeft = function(times) {
+ if (!this.selection.isEmpty()) {
+ var selectionStart = this.getSelectionRange().start;
+ this.moveCursorToPosition(selectionStart);
+ } else {
+ times = times || 1;
+ while (times--) {
+ this.selection.moveCursorLeft();
+ }
+ }
+ this.clearSelection();
+ };
+ this.navigateRight = function(times) {
+ if (!this.selection.isEmpty()) {
+ var selectionEnd = this.getSelectionRange().end;
+ this.moveCursorToPosition(selectionEnd);
+ } else {
+ times = times || 1;
+ while (times--) {
+ this.selection.moveCursorRight();
+ }
+ }
+ this.clearSelection();
+ };
+ this.navigateLineStart = function() {
+ this.selection.moveCursorLineStart();
+ this.clearSelection();
+ };
+ this.navigateLineEnd = function() {
+ this.selection.moveCursorLineEnd();
+ this.clearSelection();
+ };
+ this.navigateFileEnd = function() {
+ this.selection.moveCursorFileEnd();
+ this.clearSelection();
+ };
+ this.navigateFileStart = function() {
+ this.selection.moveCursorFileStart();
+ this.clearSelection();
+ };
+ this.navigateWordRight = function() {
+ this.selection.moveCursorWordRight();
+ this.clearSelection();
+ };
+ this.navigateWordLeft = function() {
+ this.selection.moveCursorWordLeft();
+ this.clearSelection();
+ };
+ this.replace = function(replacement, options) {
+ if (options) this.$search.set(options);
+
+ var range = this.$search.find(this.session);
+ var replaced = 0;
+ if (!range) return replaced;
+
+ if (this.$tryReplace(range, replacement)) {
+ replaced = 1;
+ }
+
+ this.selection.setSelectionRange(range);
+ this.renderer.scrollSelectionIntoView(range.start, range.end);
+
+ return replaced;
+ };
+ this.replaceAll = function(replacement, options) {
+ if (options) {
+ this.$search.set(options);
+ }
+
+ var ranges = this.$search.findAll(this.session);
+ var replaced = 0;
+ if (!ranges.length) return replaced;
+
+ var selection = this.getSelectionRange();
+ this.selection.moveTo(0, 0);
+
+ for (var i = ranges.length - 1; i >= 0; --i) {
+ if (this.$tryReplace(ranges[i], replacement)) {
+ replaced++;
+ }
+ }
+
+ this.selection.setSelectionRange(selection);
+
+ return replaced;
+ };
+
+ this.$tryReplace = function(range, replacement) {
+ var input = this.session.getTextRange(range);
+ replacement = this.$search.replace(input, replacement);
+ if (replacement !== null) {
+ range.end = this.session.replace(range, replacement);
+ return range;
+ } else {
+ return null;
+ }
+ };
+ this.getLastSearchOptions = function() {
+ return this.$search.getOptions();
+ };
+ this.find = function(needle, options, animate) {
+ if (!options) options = {};
+
+ if (typeof needle == "string" || needle instanceof RegExp)
+ options.needle = needle;
+ else if (typeof needle == "object") oop.mixin(options, needle);
+
+ var range = this.selection.getRange();
+ if (options.needle == null) {
+ needle =
+ this.session.getTextRange(range) || this.$search.$options.needle;
+ if (!needle) {
+ range = this.session.getWordRange(
+ range.start.row,
+ range.start.column
+ );
+ needle = this.session.getTextRange(range);
+ }
+ this.$search.set({ needle: needle });
+ }
+
+ this.$search.set(options);
+ if (!options.start) this.$search.set({ start: range });
+
+ var newRange = this.$search.find(this.session);
+ if (options.preventScroll) return newRange;
+ if (newRange) {
+ this.revealRange(newRange, animate);
+ return newRange;
+ }
+ if (options.backwards) range.start = range.end;
+ else range.end = range.start;
+ this.selection.setRange(range);
+ };
+ this.findNext = function(options, animate) {
+ this.find({ skipCurrent: true, backwards: false }, options, animate);
+ };
+ this.findPrevious = function(options, animate) {
+ this.find(options, { skipCurrent: true, backwards: true }, animate);
+ };
+
+ this.revealRange = function(range, animate) {
+ this.session.unfold(range);
+ this.selection.setSelectionRange(range);
+
+ var scrollTop = this.renderer.scrollTop;
+ this.renderer.scrollSelectionIntoView(range.start, range.end, 0.5);
+ if (animate !== false) this.renderer.animateScrolling(scrollTop);
+ };
+ this.undo = function() {
+ this.session.getUndoManager().undo(this.session);
+ this.renderer.scrollCursorIntoView(null, 0.5);
+ };
+ this.redo = function() {
+ this.session.getUndoManager().redo(this.session);
+ this.renderer.scrollCursorIntoView(null, 0.5);
+ };
+ this.destroy = function() {
+ if (this.$toDestroy) {
+ this.$toDestroy.forEach(function(el) {
+ el.destroy();
+ });
+ this.$toDestroy = null;
+ }
+ this.renderer.destroy();
+ this._signal("destroy", this);
+ if (this.session) this.session.destroy();
+ if (this._$emitInputEvent) this._$emitInputEvent.cancel();
+ this.removeAllListeners();
+ };
+ this.setAutoScrollEditorIntoView = function(enable) {
+ if (!enable) return;
+ var rect;
+ var self = this;
+ var shouldScroll = false;
+ if (!this.$scrollAnchor)
+ this.$scrollAnchor = document.createElement("div");
+ var scrollAnchor = this.$scrollAnchor;
+ scrollAnchor.style.cssText = "position:absolute";
+ this.container.insertBefore(scrollAnchor, this.container.firstChild);
+ var onChangeSelection = this.on("changeSelection", function() {
+ shouldScroll = true;
+ });
+ var onBeforeRender = this.renderer.on("beforeRender", function() {
+ if (shouldScroll)
+ rect = self.renderer.container.getBoundingClientRect();
+ });
+ var onAfterRender = this.renderer.on("afterRender", function() {
+ if (
+ shouldScroll &&
+ rect &&
+ (self.isFocused() || (self.searchBox && self.searchBox.isFocused()))
+ ) {
+ var renderer = self.renderer;
+ var pos = renderer.$cursorLayer.$pixelPos;
+ var config = renderer.layerConfig;
+ var top = pos.top - config.offset;
+ if (pos.top >= 0 && top + rect.top < 0) {
+ shouldScroll = true;
+ } else if (
+ pos.top < config.height &&
+ pos.top + rect.top + config.lineHeight > window.innerHeight
+ ) {
+ shouldScroll = false;
+ } else {
+ shouldScroll = null;
+ }
+ if (shouldScroll != null) {
+ scrollAnchor.style.top = top + "px";
+ scrollAnchor.style.left = pos.left + "px";
+ scrollAnchor.style.height = config.lineHeight + "px";
+ scrollAnchor.scrollIntoView(shouldScroll);
+ }
+ shouldScroll = rect = null;
+ }
+ });
+ this.setAutoScrollEditorIntoView = function(enable) {
+ if (enable) return;
+ delete this.setAutoScrollEditorIntoView;
+ this.off("changeSelection", onChangeSelection);
+ this.renderer.off("afterRender", onAfterRender);
+ this.renderer.off("beforeRender", onBeforeRender);
+ };
+ };
+
+ this.$resetCursorStyle = function() {
+ var style = this.$cursorStyle || "ace";
+ var cursorLayer = this.renderer.$cursorLayer;
+ if (!cursorLayer) return;
+ cursorLayer.setSmoothBlinking(/smooth/.test(style));
+ cursorLayer.isBlinking = !this.$readOnly && style != "wide";
+ dom.setCssClass(
+ cursorLayer.element,
+ "ace_slim-cursors",
+ /slim/.test(style)
+ );
+ };
+ this.prompt = function(message, options, callback) {
+ var editor = this;
+ config.loadModule("./ext/prompt", function(module) {
+ module.prompt(editor, message, options, callback);
+ });
+ };
+ }.call(Editor.prototype));
+
+ config.defineOptions(Editor.prototype, "editor", {
+ selectionStyle: {
+ set: function(style) {
+ this.onSelectionChange();
+ this._signal("changeSelectionStyle", { data: style });
+ },
+ initialValue: "line"
+ },
+ highlightActiveLine: {
+ set: function() {
+ this.$updateHighlightActiveLine();
+ },
+ initialValue: true
+ },
+ highlightSelectedWord: {
+ set: function(shouldHighlight) {
+ this.$onSelectionChange();
+ },
+ initialValue: true
+ },
+ readOnly: {
+ set: function(readOnly) {
+ this.textInput.setReadOnly(readOnly);
+ this.$resetCursorStyle();
+ },
+ initialValue: false
+ },
+ copyWithEmptySelection: {
+ set: function(value) {
+ this.textInput.setCopyWithEmptySelection(value);
+ },
+ initialValue: false
+ },
+ cursorStyle: {
+ set: function(val) {
+ this.$resetCursorStyle();
+ },
+ values: ["ace", "slim", "smooth", "wide"],
+ initialValue: "ace"
+ },
+ mergeUndoDeltas: {
+ values: [false, true, "always"],
+ initialValue: true
+ },
+ behavioursEnabled: { initialValue: true },
+ wrapBehavioursEnabled: { initialValue: true },
+ enableAutoIndent: { initialValue: true },
+ autoScrollEditorIntoView: {
+ set: function(val) {
+ this.setAutoScrollEditorIntoView(val);
+ }
+ },
+ keyboardHandler: {
+ set: function(val) {
+ this.setKeyboardHandler(val);
+ },
+ get: function() {
+ return this.$keybindingId;
+ },
+ handlesSet: true
+ },
+ value: {
+ set: function(val) {
+ this.session.setValue(val);
+ },
+ get: function() {
+ return this.getValue();
+ },
+ handlesSet: true,
+ hidden: true
+ },
+ session: {
+ set: function(val) {
+ this.setSession(val);
+ },
+ get: function() {
+ return this.session;
+ },
+ handlesSet: true,
+ hidden: true
+ },
+
+ showLineNumbers: {
+ set: function(show) {
+ this.renderer.$gutterLayer.setShowLineNumbers(show);
+ this.renderer.$loop.schedule(this.renderer.CHANGE_GUTTER);
+ if (show && this.$relativeLineNumbers)
+ relativeNumberRenderer.attach(this);
+ else relativeNumberRenderer.detach(this);
+ },
+ initialValue: true
+ },
+ relativeLineNumbers: {
+ set: function(value) {
+ if (this.$showLineNumbers && value)
+ relativeNumberRenderer.attach(this);
+ else relativeNumberRenderer.detach(this);
+ }
+ },
+ placeholder: {
+ set: function(message) {
+ if (!this.$updatePlaceholder) {
+ this.$updatePlaceholder = function() {
+ var value =
+ this.session && (this.renderer.$composition || this.getValue());
+ if (value && this.renderer.placeholderNode) {
+ this.renderer.off("afterRender", this.$updatePlaceholder);
+ dom.removeCssClass(this.container, "ace_hasPlaceholder");
+ this.renderer.placeholderNode.remove();
+ this.renderer.placeholderNode = null;
+ } else if (!value && !this.renderer.placeholderNode) {
+ this.renderer.on("afterRender", this.$updatePlaceholder);
+ dom.addCssClass(this.container, "ace_hasPlaceholder");
+ var el = dom.createElement("div");
+ el.className = "ace_placeholder";
+ el.textContent = this.$placeholder || "";
+ this.renderer.placeholderNode = el;
+ this.renderer.content.appendChild(
+ this.renderer.placeholderNode
+ );
+ } else if (!value && this.renderer.placeholderNode) {
+ this.renderer.placeholderNode.textContent =
+ this.$placeholder || "";
+ }
+ }.bind(this);
+ this.on("input", this.$updatePlaceholder);
+ }
+ this.$updatePlaceholder();
+ }
+ },
+
+ hScrollBarAlwaysVisible: "renderer",
+ vScrollBarAlwaysVisible: "renderer",
+ highlightGutterLine: "renderer",
+ animatedScroll: "renderer",
+ showInvisibles: "renderer",
+ showPrintMargin: "renderer",
+ printMarginColumn: "renderer",
+ printMargin: "renderer",
+ fadeFoldWidgets: "renderer",
+ showFoldWidgets: "renderer",
+ displayIndentGuides: "renderer",
+ showGutter: "renderer",
+ fontSize: "renderer",
+ fontFamily: "renderer",
+ maxLines: "renderer",
+ minLines: "renderer",
+ scrollPastEnd: "renderer",
+ fixedWidthGutter: "renderer",
+ theme: "renderer",
+ hasCssTransforms: "renderer",
+ maxPixelHeight: "renderer",
+ useTextareaForIME: "renderer",
+
+ scrollSpeed: "$mouseHandler",
+ dragDelay: "$mouseHandler",
+ dragEnabled: "$mouseHandler",
+ focusTimeout: "$mouseHandler",
+ tooltipFollowsMouse: "$mouseHandler",
+
+ firstLineNumber: "session",
+ overwrite: "session",
+ newLineMode: "session",
+ useWorker: "session",
+ useSoftTabs: "session",
+ navigateWithinSoftTabs: "session",
+ tabSize: "session",
+ wrap: "session",
+ indentedSoftWrap: "session",
+ foldStyle: "session",
+ mode: "session"
+ });
+
+ var relativeNumberRenderer = {
+ getText: function(session, row) {
+ return (
+ (Math.abs(session.selection.lead.row - row) ||
+ row + 1 + (row < 9 ? "\xb7" : "")) + ""
+ );
+ },
+ getWidth: function(session, lastLineNumber, config) {
+ return (
+ Math.max(
+ lastLineNumber.toString().length,
+ (config.lastRow + 1).toString().length,
+ 2
+ ) * config.characterWidth
+ );
+ },
+ update: function(e, editor) {
+ editor.renderer.$loop.schedule(editor.renderer.CHANGE_GUTTER);
+ },
+ attach: function(editor) {
+ editor.renderer.$gutterLayer.$renderer = this;
+ editor.on("changeSelection", this.update);
+ this.update(null, editor);
+ },
+ detach: function(editor) {
+ if (editor.renderer.$gutterLayer.$renderer == this)
+ editor.renderer.$gutterLayer.$renderer = null;
+ editor.off("changeSelection", this.update);
+ this.update(null, editor);
+ }
+ };
+
+ exports.Editor = Editor;
+ }
+);
+
+ace.define(
+ "ace/undomanager",
+ ["require", "exports", "module", "ace/range"],
+ function(require, exports, module) {
+ "use strict";
+ var UndoManager = function() {
+ this.$maxRev = 0;
+ this.$fromUndo = false;
+ this.reset();
+ };
+
+ (function() {
+ this.addSession = function(session) {
+ this.$session = session;
+ };
+ this.add = function(delta, allowMerge, session) {
+ if (this.$fromUndo) return;
+ if (delta == this.$lastDelta) return;
+ if (!this.$keepRedoStack) this.$redoStack.length = 0;
+ if (allowMerge === false || !this.lastDeltas) {
+ this.lastDeltas = [];
+ this.$undoStack.push(this.lastDeltas);
+ delta.id = this.$rev = ++this.$maxRev;
+ }
+ if (delta.action == "remove" || delta.action == "insert")
+ this.$lastDelta = delta;
+ this.lastDeltas.push(delta);
+ };
+
+ this.addSelection = function(selection, rev) {
+ this.selections.push({
+ value: selection,
+ rev: rev || this.$rev
+ });
+ };
+
+ this.startNewGroup = function() {
+ this.lastDeltas = null;
+ return this.$rev;
+ };
+
+ this.markIgnored = function(from, to) {
+ if (to == null) to = this.$rev + 1;
+ var stack = this.$undoStack;
+ for (var i = stack.length; i--; ) {
+ var delta = stack[i][0];
+ if (delta.id <= from) break;
+ if (delta.id < to) delta.ignore = true;
+ }
+ this.lastDeltas = null;
+ };
+
+ this.getSelection = function(rev, after) {
+ var stack = this.selections;
+ for (var i = stack.length; i--; ) {
+ var selection = stack[i];
+ if (selection.rev < rev) {
+ if (after) selection = stack[i + 1];
+ return selection;
+ }
+ }
+ };
+
+ this.getRevision = function() {
+ return this.$rev;
+ };
+
+ this.getDeltas = function(from, to) {
+ if (to == null) to = this.$rev + 1;
+ var stack = this.$undoStack;
+ var end = null,
+ start = 0;
+ for (var i = stack.length; i--; ) {
+ var delta = stack[i][0];
+ if (delta.id < to && !end) end = i + 1;
+ if (delta.id <= from) {
+ start = i + 1;
+ break;
+ }
+ }
+ return stack.slice(start, end);
+ };
+
+ this.getChangedRanges = function(from, to) {
+ if (to == null) to = this.$rev + 1;
+ };
+
+ this.getChangedLines = function(from, to) {
+ if (to == null) to = this.$rev + 1;
+ };
+ this.undo = function(session, dontSelect) {
+ this.lastDeltas = null;
+ var stack = this.$undoStack;
+
+ if (!rearrangeUndoStack(stack, stack.length)) return;
+
+ if (!session) session = this.$session;
+
+ if (this.$redoStackBaseRev !== this.$rev && this.$redoStack.length)
+ this.$redoStack = [];
+
+ this.$fromUndo = true;
+
+ var deltaSet = stack.pop();
+ var undoSelectionRange = null;
+ if (deltaSet) {
+ undoSelectionRange = session.undoChanges(deltaSet, dontSelect);
+ this.$redoStack.push(deltaSet);
+ this.$syncRev();
+ }
+
+ this.$fromUndo = false;
+
+ return undoSelectionRange;
+ };
+ this.redo = function(session, dontSelect) {
+ this.lastDeltas = null;
+
+ if (!session) session = this.$session;
+
+ this.$fromUndo = true;
+ if (this.$redoStackBaseRev != this.$rev) {
+ var diff = this.getDeltas(this.$redoStackBaseRev, this.$rev + 1);
+ rebaseRedoStack(this.$redoStack, diff);
+ this.$redoStackBaseRev = this.$rev;
+ this.$redoStack.forEach(function(x) {
+ x[0].id = ++this.$maxRev;
+ }, this);
+ }
+ var deltaSet = this.$redoStack.pop();
+ var redoSelectionRange = null;
+
+ if (deltaSet) {
+ redoSelectionRange = session.redoChanges(deltaSet, dontSelect);
+ this.$undoStack.push(deltaSet);
+ this.$syncRev();
+ }
+ this.$fromUndo = false;
+
+ return redoSelectionRange;
+ };
+
+ this.$syncRev = function() {
+ var stack = this.$undoStack;
+ var nextDelta = stack[stack.length - 1];
+ var id = (nextDelta && nextDelta[0].id) || 0;
+ this.$redoStackBaseRev = id;
+ this.$rev = id;
+ };
+ this.reset = function() {
+ this.lastDeltas = null;
+ this.$lastDelta = null;
+ this.$undoStack = [];
+ this.$redoStack = [];
+ this.$rev = 0;
+ this.mark = 0;
+ this.$redoStackBaseRev = this.$rev;
+ this.selections = [];
+ };
+ this.canUndo = function() {
+ return this.$undoStack.length > 0;
+ };
+ this.canRedo = function() {
+ return this.$redoStack.length > 0;
+ };
+ this.bookmark = function(rev) {
+ if (rev == undefined) rev = this.$rev;
+ this.mark = rev;
+ };
+ this.isAtBookmark = function() {
+ return this.$rev === this.mark;
+ };
+
+ this.toJSON = function() {};
+
+ this.fromJSON = function() {};
+
+ this.hasUndo = this.canUndo;
+ this.hasRedo = this.canRedo;
+ this.isClean = this.isAtBookmark;
+ this.markClean = this.bookmark;
+
+ this.$prettyPrint = function(delta) {
+ if (delta) return stringifyDelta(delta);
+ return (
+ stringifyDelta(this.$undoStack) +
+ "\n---\n" +
+ stringifyDelta(this.$redoStack)
+ );
+ };
+ }.call(UndoManager.prototype));
+
+ function rearrangeUndoStack(stack, pos) {
+ for (var i = pos; i--; ) {
+ var deltaSet = stack[i];
+ if (deltaSet && !deltaSet[0].ignore) {
+ while (i < pos - 1) {
+ var swapped = swapGroups(stack[i], stack[i + 1]);
+ stack[i] = swapped[0];
+ stack[i + 1] = swapped[1];
+ i++;
+ }
+ return true;
+ }
+ }
+ }
+
+ var Range = require("./range").Range;
+ var cmp = Range.comparePoints;
+ var comparePoints = Range.comparePoints;
+
+ function $updateMarkers(delta) {
+ var isInsert = delta.action == "insert";
+ var start = delta.start;
+ var end = delta.end;
+ var rowShift = (end.row - start.row) * (isInsert ? 1 : -1);
+ var colShift = (end.column - start.column) * (isInsert ? 1 : -1);
+ if (isInsert) end = start;
+
+ for (var i in this.marks) {
+ var point = this.marks[i];
+ var cmp = comparePoints(point, start);
+ if (cmp < 0) {
+ continue; // delta starts after the range
+ }
+ if (cmp === 0) {
+ if (isInsert) {
+ if (point.bias == 1) {
+ cmp = 1;
+ } else {
+ point.bias == -1;
+ continue;
+ }
+ }
+ }
+ var cmp2 = isInsert ? cmp : comparePoints(point, end);
+ if (cmp2 > 0) {
+ point.row += rowShift;
+ point.column += point.row == end.row ? colShift : 0;
+ continue;
+ }
+ if (!isInsert && cmp2 <= 0) {
+ point.row = start.row;
+ point.column = start.column;
+ if (cmp2 === 0) point.bias = 1;
+ }
+ }
+ }
+
+ function clonePos(pos) {
+ return { row: pos.row, column: pos.column };
+ }
+ function cloneDelta(d) {
+ return {
+ start: clonePos(d.start),
+ end: clonePos(d.end),
+ action: d.action,
+ lines: d.lines.slice()
+ };
+ }
+ function stringifyDelta(d) {
+ d = d || this;
+ if (Array.isArray(d)) {
+ return d.map(stringifyDelta).join("\n");
+ }
+ var type = "";
+ if (d.action) {
+ type = d.action == "insert" ? "+" : "-";
+ type += "[" + d.lines + "]";
+ } else if (d.value) {
+ if (Array.isArray(d.value)) {
+ type = d.value.map(stringifyRange).join("\n");
+ } else {
+ type = stringifyRange(d.value);
+ }
+ }
+ if (d.start) {
+ type += stringifyRange(d);
+ }
+ if (d.id || d.rev) {
+ type += "\t(" + (d.id || d.rev) + ")";
+ }
+ return type;
+ }
+ function stringifyRange(r) {
+ return (
+ r.start.row +
+ ":" +
+ r.start.column +
+ "=>" +
+ r.end.row +
+ ":" +
+ r.end.column
+ );
+ }
+
+ function swap(d1, d2) {
+ var i1 = d1.action == "insert";
+ var i2 = d2.action == "insert";
+
+ if (i1 && i2) {
+ if (cmp(d2.start, d1.end) >= 0) {
+ shift(d2, d1, -1);
+ } else if (cmp(d2.start, d1.start) <= 0) {
+ shift(d1, d2, +1);
+ } else {
+ return null;
+ }
+ } else if (i1 && !i2) {
+ if (cmp(d2.start, d1.end) >= 0) {
+ shift(d2, d1, -1);
+ } else if (cmp(d2.end, d1.start) <= 0) {
+ shift(d1, d2, -1);
+ } else {
+ return null;
+ }
+ } else if (!i1 && i2) {
+ if (cmp(d2.start, d1.start) >= 0) {
+ shift(d2, d1, +1);
+ } else if (cmp(d2.start, d1.start) <= 0) {
+ shift(d1, d2, +1);
+ } else {
+ return null;
+ }
+ } else if (!i1 && !i2) {
+ if (cmp(d2.start, d1.start) >= 0) {
+ shift(d2, d1, +1);
+ } else if (cmp(d2.end, d1.start) <= 0) {
+ shift(d1, d2, -1);
+ } else {
+ return null;
+ }
+ }
+ return [d2, d1];
+ }
+ function swapGroups(ds1, ds2) {
+ for (var i = ds1.length; i--; ) {
+ for (var j = 0; j < ds2.length; j++) {
+ if (!swap(ds1[i], ds2[j])) {
+ while (i < ds1.length) {
+ while (j--) {
+ swap(ds2[j], ds1[i]);
+ }
+ j = ds2.length;
+ i++;
+ }
+ return [ds1, ds2];
+ }
+ }
+ }
+ ds1.selectionBefore = ds2.selectionBefore = ds1.selectionAfter = ds2.selectionAfter = null;
+ return [ds2, ds1];
+ }
+ function xform(d1, c1) {
+ var i1 = d1.action == "insert";
+ var i2 = c1.action == "insert";
+
+ if (i1 && i2) {
+ if (cmp(d1.start, c1.start) < 0) {
+ shift(c1, d1, 1);
+ } else {
+ shift(d1, c1, 1);
+ }
+ } else if (i1 && !i2) {
+ if (cmp(d1.start, c1.end) >= 0) {
+ shift(d1, c1, -1);
+ } else if (cmp(d1.start, c1.start) <= 0) {
+ shift(c1, d1, +1);
+ } else {
+ shift(d1, Range.fromPoints(c1.start, d1.start), -1);
+ shift(c1, d1, +1);
+ }
+ } else if (!i1 && i2) {
+ if (cmp(c1.start, d1.end) >= 0) {
+ shift(c1, d1, -1);
+ } else if (cmp(c1.start, d1.start) <= 0) {
+ shift(d1, c1, +1);
+ } else {
+ shift(c1, Range.fromPoints(d1.start, c1.start), -1);
+ shift(d1, c1, +1);
+ }
+ } else if (!i1 && !i2) {
+ if (cmp(c1.start, d1.end) >= 0) {
+ shift(c1, d1, -1);
+ } else if (cmp(c1.end, d1.start) <= 0) {
+ shift(d1, c1, -1);
+ } else {
+ var before, after;
+ if (cmp(d1.start, c1.start) < 0) {
+ before = d1;
+ d1 = splitDelta(d1, c1.start);
+ }
+ if (cmp(d1.end, c1.end) > 0) {
+ after = splitDelta(d1, c1.end);
+ }
+
+ shiftPos(c1.end, d1.start, d1.end, -1);
+ if (after && !before) {
+ d1.lines = after.lines;
+ d1.start = after.start;
+ d1.end = after.end;
+ after = d1;
+ }
+
+ return [c1, before, after].filter(Boolean);
+ }
+ }
+ return [c1, d1];
+ }
+
+ function shift(d1, d2, dir) {
+ shiftPos(d1.start, d2.start, d2.end, dir);
+ shiftPos(d1.end, d2.start, d2.end, dir);
+ }
+ function shiftPos(pos, start, end, dir) {
+ if (pos.row == (dir == 1 ? start : end).row) {
+ pos.column += dir * (end.column - start.column);
+ }
+ pos.row += dir * (end.row - start.row);
+ }
+ function splitDelta(c, pos) {
+ var lines = c.lines;
+ var end = c.end;
+ c.end = clonePos(pos);
+ var rowsBefore = c.end.row - c.start.row;
+ var otherLines = lines.splice(rowsBefore, lines.length);
+
+ var col = rowsBefore ? pos.column : pos.column - c.start.column;
+ lines.push(otherLines[0].substring(0, col));
+ otherLines[0] = otherLines[0].substr(col);
+ var rest = {
+ start: clonePos(pos),
+ end: end,
+ lines: otherLines,
+ action: c.action
+ };
+ return rest;
+ }
+
+ function moveDeltasByOne(redoStack, d) {
+ d = cloneDelta(d);
+ for (var j = redoStack.length; j--; ) {
+ var deltaSet = redoStack[j];
+ for (var i = 0; i < deltaSet.length; i++) {
+ var x = deltaSet[i];
+ var xformed = xform(x, d);
+ d = xformed[0];
+ if (xformed.length != 2) {
+ if (xformed[2]) {
+ deltaSet.splice(i + 1, 1, xformed[1], xformed[2]);
+ i++;
+ } else if (!xformed[1]) {
+ deltaSet.splice(i, 1);
+ i--;
+ }
+ }
+ }
+ if (!deltaSet.length) {
+ redoStack.splice(j, 1);
+ }
+ }
+ return redoStack;
+ }
+ function rebaseRedoStack(redoStack, deltaSets) {
+ for (var i = 0; i < deltaSets.length; i++) {
+ var deltas = deltaSets[i];
+ for (var j = 0; j < deltas.length; j++) {
+ moveDeltasByOne(redoStack, deltas[j]);
+ }
+ }
+ }
+
+ exports.UndoManager = UndoManager;
+ }
+);
+
+ace.define(
+ "ace/layer/lines",
+ ["require", "exports", "module", "ace/lib/dom"],
+ function(require, exports, module) {
+ "use strict";
+
+ var dom = require("../lib/dom");
+
+ var Lines = function(element, canvasHeight) {
+ this.element = element;
+ this.canvasHeight = canvasHeight || 500000;
+ this.element.style.height = this.canvasHeight * 2 + "px";
+
+ this.cells = [];
+ this.cellCache = [];
+ this.$offsetCoefficient = 0;
+ };
+
+ (function() {
+ this.moveContainer = function(config) {
+ dom.translate(
+ this.element,
+ 0,
+ -((config.firstRowScreen * config.lineHeight) % this.canvasHeight) -
+ config.offset * this.$offsetCoefficient
+ );
+ };
+
+ this.pageChanged = function(oldConfig, newConfig) {
+ return (
+ Math.floor(
+ (oldConfig.firstRowScreen * oldConfig.lineHeight) /
+ this.canvasHeight
+ ) !==
+ Math.floor(
+ (newConfig.firstRowScreen * newConfig.lineHeight) /
+ this.canvasHeight
+ )
+ );
+ };
+
+ this.computeLineTop = function(row, config, session) {
+ var screenTop = config.firstRowScreen * config.lineHeight;
+ var screenPage = Math.floor(screenTop / this.canvasHeight);
+ var lineTop = session.documentToScreenRow(row, 0) * config.lineHeight;
+ return lineTop - screenPage * this.canvasHeight;
+ };
+
+ this.computeLineHeight = function(row, config, session) {
+ return config.lineHeight * session.getRowLineCount(row);
+ };
+
+ this.getLength = function() {
+ return this.cells.length;
+ };
+
+ this.get = function(index) {
+ return this.cells[index];
+ };
+
+ this.shift = function() {
+ this.$cacheCell(this.cells.shift());
+ };
+
+ this.pop = function() {
+ this.$cacheCell(this.cells.pop());
+ };
+
+ this.push = function(cell) {
+ if (Array.isArray(cell)) {
+ this.cells.push.apply(this.cells, cell);
+ var fragment = dom.createFragment(this.element);
+ for (var i = 0; i < cell.length; i++) {
+ fragment.appendChild(cell[i].element);
+ }
+ this.element.appendChild(fragment);
+ } else {
+ this.cells.push(cell);
+ this.element.appendChild(cell.element);
+ }
+ };
+
+ this.unshift = function(cell) {
+ if (Array.isArray(cell)) {
+ this.cells.unshift.apply(this.cells, cell);
+ var fragment = dom.createFragment(this.element);
+ for (var i = 0; i < cell.length; i++) {
+ fragment.appendChild(cell[i].element);
+ }
+ if (this.element.firstChild)
+ this.element.insertBefore(fragment, this.element.firstChild);
+ else this.element.appendChild(fragment);
+ } else {
+ this.cells.unshift(cell);
+ this.element.insertAdjacentElement("afterbegin", cell.element);
+ }
+ };
+
+ this.last = function() {
+ if (this.cells.length) return this.cells[this.cells.length - 1];
+ else return null;
+ };
+
+ this.$cacheCell = function(cell) {
+ if (!cell) return;
+
+ cell.element.remove();
+ this.cellCache.push(cell);
+ };
+
+ this.createCell = function(row, config, session, initElement) {
+ var cell = this.cellCache.pop();
+ if (!cell) {
+ var element = dom.createElement("div");
+ if (initElement) initElement(element);
+
+ this.element.appendChild(element);
+
+ cell = {
+ element: element,
+ text: "",
+ row: row
+ };
+ }
+ cell.row = row;
+
+ return cell;
+ };
+ }.call(Lines.prototype));
+
+ exports.Lines = Lines;
+ }
+);
+
+ace.define(
+ "ace/layer/gutter",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/lib/dom",
+ "ace/lib/oop",
+ "ace/lib/lang",
+ "ace/lib/event_emitter",
+ "ace/layer/lines"
+ ],
+ function(require, exports, module) {
+ "use strict";
+
+ var dom = require("../lib/dom");
+ var oop = require("../lib/oop");
+ var lang = require("../lib/lang");
+ var EventEmitter = require("../lib/event_emitter").EventEmitter;
+ var Lines = require("./lines").Lines;
+
+ var Gutter = function(parentEl) {
+ this.element = dom.createElement("div");
+ this.element.className = "ace_layer ace_gutter-layer";
+ parentEl.appendChild(this.element);
+ this.setShowFoldWidgets(this.$showFoldWidgets);
+
+ this.gutterWidth = 0;
+
+ this.$annotations = [];
+ this.$updateAnnotations = this.$updateAnnotations.bind(this);
+
+ this.$lines = new Lines(this.element);
+ this.$lines.$offsetCoefficient = 1;
+ };
+
+ (function() {
+ oop.implement(this, EventEmitter);
+
+ this.setSession = function(session) {
+ if (this.session) this.session.off("change", this.$updateAnnotations);
+ this.session = session;
+ if (session) session.on("change", this.$updateAnnotations);
+ };
+
+ this.addGutterDecoration = function(row, className) {
+ if (window.console)
+ console.warn &&
+ console.warn("deprecated use session.addGutterDecoration");
+ this.session.addGutterDecoration(row, className);
+ };
+
+ this.removeGutterDecoration = function(row, className) {
+ if (window.console)
+ console.warn &&
+ console.warn("deprecated use session.removeGutterDecoration");
+ this.session.removeGutterDecoration(row, className);
+ };
+
+ this.setAnnotations = function(annotations) {
+ this.$annotations = [];
+ for (var i = 0; i < annotations.length; i++) {
+ var annotation = annotations[i];
+ var row = annotation.row;
+ var rowInfo = this.$annotations[row];
+ if (!rowInfo) rowInfo = this.$annotations[row] = { text: [] };
+
+ var annoText = annotation.text;
+ annoText = annoText
+ ? lang.escapeHTML(annoText)
+ : annotation.html || "";
+
+ if (rowInfo.text.indexOf(annoText) === -1)
+ rowInfo.text.push(annoText);
+
+ var type = annotation.type;
+ if (type == "error") rowInfo.className = " ace_error";
+ else if (type == "warning" && rowInfo.className != " ace_error")
+ rowInfo.className = " ace_warning";
+ else if (type == "info" && !rowInfo.className)
+ rowInfo.className = " ace_info";
+ }
+ };
+
+ this.$updateAnnotations = function(delta) {
+ if (!this.$annotations.length) return;
+ var firstRow = delta.start.row;
+ var len = delta.end.row - firstRow;
+ if (len === 0) {
+ } else if (delta.action == "remove") {
+ this.$annotations.splice(firstRow, len + 1, null);
+ } else {
+ var args = new Array(len + 1);
+ args.unshift(firstRow, 1);
+ this.$annotations.splice.apply(this.$annotations, args);
+ }
+ };
+
+ this.update = function(config) {
+ this.config = config;
+
+ var session = this.session;
+ var firstRow = config.firstRow;
+ var lastRow = Math.min(
+ config.lastRow + config.gutterOffset, // needed to compensate for hor scollbar
+ session.getLength() - 1
+ );
+
+ this.oldLastRow = lastRow;
+ this.config = config;
+
+ this.$lines.moveContainer(config);
+ this.$updateCursorRow();
+
+ var fold = session.getNextFoldLine(firstRow);
+ var foldStart = fold ? fold.start.row : Infinity;
+
+ var cell = null;
+ var index = -1;
+ var row = firstRow;
+
+ while (true) {
+ if (row > foldStart) {
+ row = fold.end.row + 1;
+ fold = session.getNextFoldLine(row, fold);
+ foldStart = fold ? fold.start.row : Infinity;
+ }
+ if (row > lastRow) {
+ while (this.$lines.getLength() > index + 1) this.$lines.pop();
+
+ break;
+ }
+
+ cell = this.$lines.get(++index);
+ if (cell) {
+ cell.row = row;
+ } else {
+ cell = this.$lines.createCell(
+ row,
+ config,
+ this.session,
+ onCreateCell
+ );
+ this.$lines.push(cell);
+ }
+
+ this.$renderCell(cell, config, fold, row);
+ row++;
+ }
+
+ this._signal("afterRender");
+ this.$updateGutterWidth(config);
+ };
+
+ this.$updateGutterWidth = function(config) {
+ var session = this.session;
+
+ var gutterRenderer = session.gutterRenderer || this.$renderer;
+
+ var firstLineNumber = session.$firstLineNumber;
+ var lastLineText = this.$lines.last() ? this.$lines.last().text : "";
+
+ if (this.$fixedWidth || session.$useWrapMode)
+ lastLineText = session.getLength() + firstLineNumber - 1;
+
+ var gutterWidth = gutterRenderer
+ ? gutterRenderer.getWidth(session, lastLineText, config)
+ : lastLineText.toString().length * config.characterWidth;
+
+ var padding = this.$padding || this.$computePadding();
+ gutterWidth += padding.left + padding.right;
+ if (gutterWidth !== this.gutterWidth && !isNaN(gutterWidth)) {
+ this.gutterWidth = gutterWidth;
+ this.element.parentNode.style.width = this.element.style.width =
+ Math.ceil(this.gutterWidth) + "px";
+ this._signal("changeGutterWidth", gutterWidth);
+ }
+ };
+
+ this.$updateCursorRow = function() {
+ if (!this.$highlightGutterLine) return;
+
+ var position = this.session.selection.getCursor();
+ if (this.$cursorRow === position.row) return;
+
+ this.$cursorRow = position.row;
+ };
+
+ this.updateLineHighlight = function() {
+ if (!this.$highlightGutterLine) return;
+ var row = this.session.selection.cursor.row;
+ this.$cursorRow = row;
+
+ if (this.$cursorCell && this.$cursorCell.row == row) return;
+ if (this.$cursorCell)
+ this.$cursorCell.element.className = this.$cursorCell.element.className.replace(
+ "ace_gutter-active-line ",
+ ""
+ );
+ var cells = this.$lines.cells;
+ this.$cursorCell = null;
+ for (var i = 0; i < cells.length; i++) {
+ var cell = cells[i];
+ if (cell.row >= this.$cursorRow) {
+ if (cell.row > this.$cursorRow) {
+ var fold = this.session.getFoldLine(this.$cursorRow);
+ if (i > 0 && fold && fold.start.row == cells[i - 1].row)
+ cell = cells[i - 1];
+ else break;
+ }
+ cell.element.className =
+ "ace_gutter-active-line " + cell.element.className;
+ this.$cursorCell = cell;
+ break;
+ }
+ }
+ };
+
+ this.scrollLines = function(config) {
+ var oldConfig = this.config;
+ this.config = config;
+
+ this.$updateCursorRow();
+ if (this.$lines.pageChanged(oldConfig, config))
+ return this.update(config);
+
+ this.$lines.moveContainer(config);
+
+ var lastRow = Math.min(
+ config.lastRow + config.gutterOffset, // needed to compensate for hor scollbar
+ this.session.getLength() - 1
+ );
+ var oldLastRow = this.oldLastRow;
+ this.oldLastRow = lastRow;
+
+ if (!oldConfig || oldLastRow < config.firstRow)
+ return this.update(config);
+
+ if (lastRow < oldConfig.firstRow) return this.update(config);
+
+ if (oldConfig.firstRow < config.firstRow)
+ for (
+ var row = this.session.getFoldedRowCount(
+ oldConfig.firstRow,
+ config.firstRow - 1
+ );
+ row > 0;
+ row--
+ )
+ this.$lines.shift();
+
+ if (oldLastRow > lastRow)
+ for (
+ var row = this.session.getFoldedRowCount(lastRow + 1, oldLastRow);
+ row > 0;
+ row--
+ )
+ this.$lines.pop();
+
+ if (config.firstRow < oldConfig.firstRow) {
+ this.$lines.unshift(
+ this.$renderLines(config, config.firstRow, oldConfig.firstRow - 1)
+ );
+ }
+
+ if (lastRow > oldLastRow) {
+ this.$lines.push(this.$renderLines(config, oldLastRow + 1, lastRow));
+ }
+
+ this.updateLineHighlight();
+
+ this._signal("afterRender");
+ this.$updateGutterWidth(config);
+ };
+
+ this.$renderLines = function(config, firstRow, lastRow) {
+ var fragment = [];
+ var row = firstRow;
+ var foldLine = this.session.getNextFoldLine(row);
+ var foldStart = foldLine ? foldLine.start.row : Infinity;
+
+ while (true) {
+ if (row > foldStart) {
+ row = foldLine.end.row + 1;
+ foldLine = this.session.getNextFoldLine(row, foldLine);
+ foldStart = foldLine ? foldLine.start.row : Infinity;
+ }
+ if (row > lastRow) break;
+
+ var cell = this.$lines.createCell(
+ row,
+ config,
+ this.session,
+ onCreateCell
+ );
+ this.$renderCell(cell, config, foldLine, row);
+ fragment.push(cell);
+
+ row++;
+ }
+ return fragment;
+ };
+
+ this.$renderCell = function(cell, config, fold, row) {
+ var element = cell.element;
+
+ var session = this.session;
+
+ var textNode = element.childNodes[0];
+ var foldWidget = element.childNodes[1];
+
+ var firstLineNumber = session.$firstLineNumber;
+
+ var breakpoints = session.$breakpoints;
+ var decorations = session.$decorations;
+ var gutterRenderer = session.gutterRenderer || this.$renderer;
+ var foldWidgets = this.$showFoldWidgets && session.foldWidgets;
+ var foldStart = fold ? fold.start.row : Number.MAX_VALUE;
+
+ var className = "ace_gutter-cell ";
+ if (this.$highlightGutterLine) {
+ if (
+ row == this.$cursorRow ||
+ (fold &&
+ row < this.$cursorRow &&
+ row >= foldStart &&
+ this.$cursorRow <= fold.end.row)
+ ) {
+ className += "ace_gutter-active-line ";
+ if (this.$cursorCell != cell) {
+ if (this.$cursorCell)
+ this.$cursorCell.element.className = this.$cursorCell.element.className.replace(
+ "ace_gutter-active-line ",
+ ""
+ );
+ this.$cursorCell = cell;
+ }
+ }
+ }
+
+ if (breakpoints[row]) className += breakpoints[row];
+ if (decorations[row]) className += decorations[row];
+ if (this.$annotations[row])
+ className += this.$annotations[row].className;
+ if (element.className != className) element.className = className;
+
+ if (foldWidgets) {
+ var c = foldWidgets[row];
+ if (c == null) c = foldWidgets[row] = session.getFoldWidget(row);
+ }
+
+ if (c) {
+ var className = "ace_fold-widget ace_" + c;
+ if (c == "start" && row == foldStart && row < fold.end.row)
+ className += " ace_closed";
+ else className += " ace_open";
+ if (foldWidget.className != className)
+ foldWidget.className = className;
+
+ var foldHeight = config.lineHeight + "px";
+ dom.setStyle(foldWidget.style, "height", foldHeight);
+ dom.setStyle(foldWidget.style, "display", "inline-block");
+ } else {
+ if (foldWidget) {
+ dom.setStyle(foldWidget.style, "display", "none");
+ }
+ }
+
+ var text = (gutterRenderer
+ ? gutterRenderer.getText(session, row)
+ : row + firstLineNumber
+ ).toString();
+
+ if (text !== textNode.data) {
+ textNode.data = text;
+ }
+
+ dom.setStyle(
+ cell.element.style,
+ "height",
+ this.$lines.computeLineHeight(row, config, session) + "px"
+ );
+ dom.setStyle(
+ cell.element.style,
+ "top",
+ this.$lines.computeLineTop(row, config, session) + "px"
+ );
+
+ cell.text = text;
+ return cell;
+ };
+
+ this.$fixedWidth = false;
+
+ this.$highlightGutterLine = true;
+ this.$renderer = "";
+ this.setHighlightGutterLine = function(highlightGutterLine) {
+ this.$highlightGutterLine = highlightGutterLine;
+ };
+
+ this.$showLineNumbers = true;
+ this.$renderer = "";
+ this.setShowLineNumbers = function(show) {
+ this.$renderer = !show && {
+ getWidth: function() {
+ return 0;
+ },
+ getText: function() {
+ return "";
+ }
+ };
+ };
+
+ this.getShowLineNumbers = function() {
+ return this.$showLineNumbers;
+ };
+
+ this.$showFoldWidgets = true;
+ this.setShowFoldWidgets = function(show) {
+ if (show) dom.addCssClass(this.element, "ace_folding-enabled");
+ else dom.removeCssClass(this.element, "ace_folding-enabled");
+
+ this.$showFoldWidgets = show;
+ this.$padding = null;
+ };
+
+ this.getShowFoldWidgets = function() {
+ return this.$showFoldWidgets;
+ };
+
+ this.$computePadding = function() {
+ if (!this.element.firstChild) return { left: 0, right: 0 };
+ var style = dom.computedStyle(this.element.firstChild);
+ this.$padding = {};
+ this.$padding.left =
+ (parseInt(style.borderLeftWidth) || 0) +
+ (parseInt(style.paddingLeft) || 0) +
+ 1;
+ this.$padding.right =
+ (parseInt(style.borderRightWidth) || 0) +
+ (parseInt(style.paddingRight) || 0);
+ return this.$padding;
+ };
+
+ this.getRegion = function(point) {
+ var padding = this.$padding || this.$computePadding();
+ var rect = this.element.getBoundingClientRect();
+ if (point.x < padding.left + rect.left) return "markers";
+ if (this.$showFoldWidgets && point.x > rect.right - padding.right)
+ return "foldWidgets";
+ };
+ }.call(Gutter.prototype));
+
+ function onCreateCell(element) {
+ var textNode = document.createTextNode("");
+ element.appendChild(textNode);
+
+ var foldWidget = dom.createElement("span");
+ element.appendChild(foldWidget);
+
+ return element;
+ }
+
+ exports.Gutter = Gutter;
+ }
+);
+
+ace.define(
+ "ace/layer/marker",
+ ["require", "exports", "module", "ace/range", "ace/lib/dom"],
+ function(require, exports, module) {
+ "use strict";
+
+ var Range = require("../range").Range;
+ var dom = require("../lib/dom");
+
+ var Marker = function(parentEl) {
+ this.element = dom.createElement("div");
+ this.element.className = "ace_layer ace_marker-layer";
+ parentEl.appendChild(this.element);
+ };
+
+ (function() {
+ this.$padding = 0;
+
+ this.setPadding = function(padding) {
+ this.$padding = padding;
+ };
+ this.setSession = function(session) {
+ this.session = session;
+ };
+
+ this.setMarkers = function(markers) {
+ this.markers = markers;
+ };
+
+ this.elt = function(className, css) {
+ var x = this.i != -1 && this.element.childNodes[this.i];
+ if (!x) {
+ x = document.createElement("div");
+ this.element.appendChild(x);
+ this.i = -1;
+ } else {
+ this.i++;
+ }
+ x.style.cssText = css;
+ x.className = className;
+ };
+
+ this.update = function(config) {
+ if (!config) return;
+
+ this.config = config;
+
+ this.i = 0;
+ var html;
+ for (var key in this.markers) {
+ var marker = this.markers[key];
+
+ if (!marker.range) {
+ marker.update(html, this, this.session, config);
+ continue;
+ }
+
+ var range = marker.range.clipRows(config.firstRow, config.lastRow);
+ if (range.isEmpty()) continue;
+
+ range = range.toScreenRange(this.session);
+ if (marker.renderer) {
+ var top = this.$getTop(range.start.row, config);
+ var left =
+ this.$padding + range.start.column * config.characterWidth;
+ marker.renderer(html, range, left, top, config);
+ } else if (marker.type == "fullLine") {
+ this.drawFullLineMarker(html, range, marker.clazz, config);
+ } else if (marker.type == "screenLine") {
+ this.drawScreenLineMarker(html, range, marker.clazz, config);
+ } else if (range.isMultiLine()) {
+ if (marker.type == "text")
+ this.drawTextMarker(html, range, marker.clazz, config);
+ else this.drawMultiLineMarker(html, range, marker.clazz, config);
+ } else {
+ this.drawSingleLineMarker(
+ html,
+ range,
+ marker.clazz + " ace_start" + " ace_br15",
+ config
+ );
+ }
+ }
+ if (this.i != -1) {
+ while (this.i < this.element.childElementCount)
+ this.element.removeChild(this.element.lastChild);
+ }
+ };
+
+ this.$getTop = function(row, layerConfig) {
+ return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight;
+ };
+
+ function getBorderClass(tl, tr, br, bl) {
+ return (tl ? 1 : 0) | (tr ? 2 : 0) | (br ? 4 : 0) | (bl ? 8 : 0);
+ }
+ this.drawTextMarker = function(
+ stringBuilder,
+ range,
+ clazz,
+ layerConfig,
+ extraStyle
+ ) {
+ var session = this.session;
+ var start = range.start.row;
+ var end = range.end.row;
+ var row = start;
+ var prev = 0;
+ var curr = 0;
+ var next = session.getScreenLastRowColumn(row);
+ var lineRange = new Range(row, range.start.column, row, curr);
+ for (; row <= end; row++) {
+ lineRange.start.row = lineRange.end.row = row;
+ lineRange.start.column =
+ row == start ? range.start.column : session.getRowWrapIndent(row);
+ lineRange.end.column = next;
+ prev = curr;
+ curr = next;
+ next =
+ row + 1 < end
+ ? session.getScreenLastRowColumn(row + 1)
+ : row == end
+ ? 0
+ : range.end.column;
+ this.drawSingleLineMarker(
+ stringBuilder,
+ lineRange,
+ clazz +
+ (row == start ? " ace_start" : "") +
+ " ace_br" +
+ getBorderClass(
+ row == start || (row == start + 1 && range.start.column),
+ prev < curr,
+ curr > next,
+ row == end
+ ),
+ layerConfig,
+ row == end ? 0 : 1,
+ extraStyle
+ );
+ }
+ };
+ this.drawMultiLineMarker = function(
+ stringBuilder,
+ range,
+ clazz,
+ config,
+ extraStyle
+ ) {
+ var padding = this.$padding;
+ var height = config.lineHeight;
+ var top = this.$getTop(range.start.row, config);
+ var left = padding + range.start.column * config.characterWidth;
+ extraStyle = extraStyle || "";
+
+ if (this.session.$bidiHandler.isBidiRow(range.start.row)) {
+ var range1 = range.clone();
+ range1.end.row = range1.start.row;
+ range1.end.column = this.session.getLine(range1.start.row).length;
+ this.drawBidiSingleLineMarker(
+ stringBuilder,
+ range1,
+ clazz + " ace_br1 ace_start",
+ config,
+ null,
+ extraStyle
+ );
+ } else {
+ this.elt(
+ clazz + " ace_br1 ace_start",
+ "height:" +
+ height +
+ "px;" +
+ "right:0;" +
+ "top:" +
+ top +
+ "px;left:" +
+ left +
+ "px;" +
+ (extraStyle || "")
+ );
+ }
+ if (this.session.$bidiHandler.isBidiRow(range.end.row)) {
+ var range1 = range.clone();
+ range1.start.row = range1.end.row;
+ range1.start.column = 0;
+ this.drawBidiSingleLineMarker(
+ stringBuilder,
+ range1,
+ clazz + " ace_br12",
+ config,
+ null,
+ extraStyle
+ );
+ } else {
+ top = this.$getTop(range.end.row, config);
+ var width = range.end.column * config.characterWidth;
+
+ this.elt(
+ clazz + " ace_br12",
+ "height:" +
+ height +
+ "px;" +
+ "width:" +
+ width +
+ "px;" +
+ "top:" +
+ top +
+ "px;" +
+ "left:" +
+ padding +
+ "px;" +
+ (extraStyle || "")
+ );
+ }
+ height = (range.end.row - range.start.row - 1) * config.lineHeight;
+ if (height <= 0) return;
+ top = this.$getTop(range.start.row + 1, config);
+
+ var radiusClass =
+ (range.start.column ? 1 : 0) | (range.end.column ? 0 : 8);
+
+ this.elt(
+ clazz + (radiusClass ? " ace_br" + radiusClass : ""),
+ "height:" +
+ height +
+ "px;" +
+ "right:0;" +
+ "top:" +
+ top +
+ "px;" +
+ "left:" +
+ padding +
+ "px;" +
+ (extraStyle || "")
+ );
+ };
+ this.drawSingleLineMarker = function(
+ stringBuilder,
+ range,
+ clazz,
+ config,
+ extraLength,
+ extraStyle
+ ) {
+ if (this.session.$bidiHandler.isBidiRow(range.start.row))
+ return this.drawBidiSingleLineMarker(
+ stringBuilder,
+ range,
+ clazz,
+ config,
+ extraLength,
+ extraStyle
+ );
+ var height = config.lineHeight;
+ var width =
+ (range.end.column + (extraLength || 0) - range.start.column) *
+ config.characterWidth;
+
+ var top = this.$getTop(range.start.row, config);
+ var left = this.$padding + range.start.column * config.characterWidth;
+
+ this.elt(
+ clazz,
+ "height:" +
+ height +
+ "px;" +
+ "width:" +
+ width +
+ "px;" +
+ "top:" +
+ top +
+ "px;" +
+ "left:" +
+ left +
+ "px;" +
+ (extraStyle || "")
+ );
+ };
+ this.drawBidiSingleLineMarker = function(
+ stringBuilder,
+ range,
+ clazz,
+ config,
+ extraLength,
+ extraStyle
+ ) {
+ var height = config.lineHeight,
+ top = this.$getTop(range.start.row, config),
+ padding = this.$padding;
+ var selections = this.session.$bidiHandler.getSelections(
+ range.start.column,
+ range.end.column
+ );
+
+ selections.forEach(function(selection) {
+ this.elt(
+ clazz,
+ "height:" +
+ height +
+ "px;" +
+ "width:" +
+ selection.width +
+ (extraLength || 0) +
+ "px;" +
+ "top:" +
+ top +
+ "px;" +
+ "left:" +
+ (padding + selection.left) +
+ "px;" +
+ (extraStyle || "")
+ );
+ }, this);
+ };
+
+ this.drawFullLineMarker = function(
+ stringBuilder,
+ range,
+ clazz,
+ config,
+ extraStyle
+ ) {
+ var top = this.$getTop(range.start.row, config);
+ var height = config.lineHeight;
+ if (range.start.row != range.end.row)
+ height += this.$getTop(range.end.row, config) - top;
+
+ this.elt(
+ clazz,
+ "height:" +
+ height +
+ "px;" +
+ "top:" +
+ top +
+ "px;" +
+ "left:0;right:0;" +
+ (extraStyle || "")
+ );
+ };
+
+ this.drawScreenLineMarker = function(
+ stringBuilder,
+ range,
+ clazz,
+ config,
+ extraStyle
+ ) {
+ var top = this.$getTop(range.start.row, config);
+ var height = config.lineHeight;
+
+ this.elt(
+ clazz,
+ "height:" +
+ height +
+ "px;" +
+ "top:" +
+ top +
+ "px;" +
+ "left:0;right:0;" +
+ (extraStyle || "")
+ );
+ };
+ }.call(Marker.prototype));
+
+ exports.Marker = Marker;
+ }
+);
+
+ace.define(
+ "ace/layer/text",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/lib/oop",
+ "ace/lib/dom",
+ "ace/lib/lang",
+ "ace/layer/lines",
+ "ace/lib/event_emitter"
+ ],
+ function(require, exports, module) {
+ "use strict";
+
+ var oop = require("../lib/oop");
+ var dom = require("../lib/dom");
+ var lang = require("../lib/lang");
+ var Lines = require("./lines").Lines;
+ var EventEmitter = require("../lib/event_emitter").EventEmitter;
+
+ var Text = function(parentEl) {
+ this.dom = dom;
+ this.element = this.dom.createElement("div");
+ this.element.className = "ace_layer ace_text-layer";
+ parentEl.appendChild(this.element);
+ this.$updateEolChar = this.$updateEolChar.bind(this);
+ this.$lines = new Lines(this.element);
+ };
+
+ (function() {
+ oop.implement(this, EventEmitter);
+
+ this.EOF_CHAR = "\xB6";
+ this.EOL_CHAR_LF = "\xAC";
+ this.EOL_CHAR_CRLF = "\xa4";
+ this.EOL_CHAR = this.EOL_CHAR_LF;
+ this.TAB_CHAR = "\u2014"; //"\u21E5";
+ this.SPACE_CHAR = "\xB7";
+ this.$padding = 0;
+ this.MAX_LINE_LENGTH = 10000;
+
+ this.$updateEolChar = function() {
+ var doc = this.session.doc;
+ var unixMode =
+ doc.getNewLineCharacter() == "\n" &&
+ doc.getNewLineMode() != "windows";
+ var EOL_CHAR = unixMode ? this.EOL_CHAR_LF : this.EOL_CHAR_CRLF;
+ if (this.EOL_CHAR != EOL_CHAR) {
+ this.EOL_CHAR = EOL_CHAR;
+ return true;
+ }
+ };
+
+ this.setPadding = function(padding) {
+ this.$padding = padding;
+ this.element.style.margin = "0 " + padding + "px";
+ };
+
+ this.getLineHeight = function() {
+ return this.$fontMetrics.$characterSize.height || 0;
+ };
+
+ this.getCharacterWidth = function() {
+ return this.$fontMetrics.$characterSize.width || 0;
+ };
+
+ this.$setFontMetrics = function(measure) {
+ this.$fontMetrics = measure;
+ this.$fontMetrics.on(
+ "changeCharacterSize",
+ function(e) {
+ this._signal("changeCharacterSize", e);
+ }.bind(this)
+ );
+ this.$pollSizeChanges();
+ };
+
+ this.checkForSizeChanges = function() {
+ this.$fontMetrics.checkForSizeChanges();
+ };
+ this.$pollSizeChanges = function() {
+ return (this.$pollSizeChangesTimer = this.$fontMetrics.$pollSizeChanges());
+ };
+ this.setSession = function(session) {
+ this.session = session;
+ if (session) this.$computeTabString();
+ };
+
+ this.showInvisibles = false;
+ this.showSpaces = false;
+ this.showTabs = false;
+ this.showEOL = false;
+ this.setShowInvisibles = function(showInvisibles) {
+ if (this.showInvisibles == showInvisibles) return false;
+
+ this.showInvisibles = showInvisibles;
+ if (typeof showInvisibles == "string") {
+ this.showSpaces = /tab/i.test(showInvisibles);
+ this.showTabs = /space/i.test(showInvisibles);
+ this.showEOL = /eol/i.test(showInvisibles);
+ } else {
+ this.showSpaces = this.showTabs = this.showEOL = showInvisibles;
+ }
+ this.$computeTabString();
+ return true;
+ };
+
+ this.displayIndentGuides = true;
+ this.setDisplayIndentGuides = function(display) {
+ if (this.displayIndentGuides == display) return false;
+
+ this.displayIndentGuides = display;
+ this.$computeTabString();
+ return true;
+ };
+
+ this.$tabStrings = [];
+ this.onChangeTabSize = this.$computeTabString = function() {
+ var tabSize = this.session.getTabSize();
+ this.tabSize = tabSize;
+ var tabStr = (this.$tabStrings = [0]);
+ for (var i = 1; i < tabSize + 1; i++) {
+ if (this.showTabs) {
+ var span = this.dom.createElement("span");
+ span.className = "ace_invisible ace_invisible_tab";
+ span.textContent = lang.stringRepeat(this.TAB_CHAR, i);
+ tabStr.push(span);
+ } else {
+ tabStr.push(
+ this.dom.createTextNode(lang.stringRepeat(" ", i), this.element)
+ );
+ }
+ }
+ if (this.displayIndentGuides) {
+ this.$indentGuideRe = /\s\S| \t|\t |\s$/;
+ var className = "ace_indent-guide";
+ var spaceClass = this.showSpaces
+ ? " ace_invisible ace_invisible_space"
+ : "";
+ var spaceContent = this.showSpaces
+ ? lang.stringRepeat(this.SPACE_CHAR, this.tabSize)
+ : lang.stringRepeat(" ", this.tabSize);
+
+ var tabClass = this.showTabs
+ ? " ace_invisible ace_invisible_tab"
+ : "";
+ var tabContent = this.showTabs
+ ? lang.stringRepeat(this.TAB_CHAR, this.tabSize)
+ : spaceContent;
+
+ var span = this.dom.createElement("span");
+ span.className = className + spaceClass;
+ span.textContent = spaceContent;
+ this.$tabStrings[" "] = span;
+
+ var span = this.dom.createElement("span");
+ span.className = className + tabClass;
+ span.textContent = tabContent;
+ this.$tabStrings["\t"] = span;
+ }
+ };
+
+ this.updateLines = function(config, firstRow, lastRow) {
+ if (
+ this.config.lastRow != config.lastRow ||
+ this.config.firstRow != config.firstRow
+ ) {
+ return this.update(config);
+ }
+
+ this.config = config;
+
+ var first = Math.max(firstRow, config.firstRow);
+ var last = Math.min(lastRow, config.lastRow);
+
+ var lineElements = this.element.childNodes;
+ var lineElementsIdx = 0;
+
+ for (var row = config.firstRow; row < first; row++) {
+ var foldLine = this.session.getFoldLine(row);
+ if (foldLine) {
+ if (foldLine.containsRow(first)) {
+ first = foldLine.start.row;
+ break;
+ } else {
+ row = foldLine.end.row;
+ }
+ }
+ lineElementsIdx++;
+ }
+
+ var heightChanged = false;
+ var row = first;
+ var foldLine = this.session.getNextFoldLine(row);
+ var foldStart = foldLine ? foldLine.start.row : Infinity;
+
+ while (true) {
+ if (row > foldStart) {
+ row = foldLine.end.row + 1;
+ foldLine = this.session.getNextFoldLine(row, foldLine);
+ foldStart = foldLine ? foldLine.start.row : Infinity;
+ }
+ if (row > last) break;
+
+ var lineElement = lineElements[lineElementsIdx++];
+ if (lineElement) {
+ this.dom.removeChildren(lineElement);
+ this.$renderLine(
+ lineElement,
+ row,
+ row == foldStart ? foldLine : false
+ );
+
+ if (heightChanged)
+ lineElement.style.top =
+ this.$lines.computeLineTop(row, config, this.session) + "px";
+
+ var height =
+ config.lineHeight * this.session.getRowLength(row) + "px";
+ if (lineElement.style.height != height) {
+ heightChanged = true;
+ lineElement.style.height = height;
+ }
+ }
+ row++;
+ }
+ if (heightChanged) {
+ while (lineElementsIdx < this.$lines.cells.length) {
+ var cell = this.$lines.cells[lineElementsIdx++];
+ cell.element.style.top =
+ this.$lines.computeLineTop(cell.row, config, this.session) + "px";
+ }
+ }
+ };
+
+ this.scrollLines = function(config) {
+ var oldConfig = this.config;
+ this.config = config;
+
+ if (this.$lines.pageChanged(oldConfig, config))
+ return this.update(config);
+
+ this.$lines.moveContainer(config);
+
+ var lastRow = config.lastRow;
+ var oldLastRow = oldConfig ? oldConfig.lastRow : -1;
+
+ if (!oldConfig || oldLastRow < config.firstRow)
+ return this.update(config);
+
+ if (lastRow < oldConfig.firstRow) return this.update(config);
+
+ if (!oldConfig || oldConfig.lastRow < config.firstRow)
+ return this.update(config);
+
+ if (config.lastRow < oldConfig.firstRow) return this.update(config);
+
+ if (oldConfig.firstRow < config.firstRow)
+ for (
+ var row = this.session.getFoldedRowCount(
+ oldConfig.firstRow,
+ config.firstRow - 1
+ );
+ row > 0;
+ row--
+ )
+ this.$lines.shift();
+
+ if (oldConfig.lastRow > config.lastRow)
+ for (
+ var row = this.session.getFoldedRowCount(
+ config.lastRow + 1,
+ oldConfig.lastRow
+ );
+ row > 0;
+ row--
+ )
+ this.$lines.pop();
+
+ if (config.firstRow < oldConfig.firstRow) {
+ this.$lines.unshift(
+ this.$renderLinesFragment(
+ config,
+ config.firstRow,
+ oldConfig.firstRow - 1
+ )
+ );
+ }
+
+ if (config.lastRow > oldConfig.lastRow) {
+ this.$lines.push(
+ this.$renderLinesFragment(
+ config,
+ oldConfig.lastRow + 1,
+ config.lastRow
+ )
+ );
+ }
+ };
+
+ this.$renderLinesFragment = function(config, firstRow, lastRow) {
+ var fragment = [];
+ var row = firstRow;
+ var foldLine = this.session.getNextFoldLine(row);
+ var foldStart = foldLine ? foldLine.start.row : Infinity;
+
+ while (true) {
+ if (row > foldStart) {
+ row = foldLine.end.row + 1;
+ foldLine = this.session.getNextFoldLine(row, foldLine);
+ foldStart = foldLine ? foldLine.start.row : Infinity;
+ }
+ if (row > lastRow) break;
+
+ var line = this.$lines.createCell(row, config, this.session);
+
+ var lineEl = line.element;
+ this.dom.removeChildren(lineEl);
+ dom.setStyle(
+ lineEl.style,
+ "height",
+ this.$lines.computeLineHeight(row, config, this.session) + "px"
+ );
+ dom.setStyle(
+ lineEl.style,
+ "top",
+ this.$lines.computeLineTop(row, config, this.session) + "px"
+ );
+ this.$renderLine(lineEl, row, row == foldStart ? foldLine : false);
+
+ if (this.$useLineGroups()) {
+ lineEl.className = "ace_line_group";
+ } else {
+ lineEl.className = "ace_line";
+ }
+ fragment.push(line);
+
+ row++;
+ }
+ return fragment;
+ };
+
+ this.update = function(config) {
+ this.$lines.moveContainer(config);
+
+ this.config = config;
+
+ var firstRow = config.firstRow;
+ var lastRow = config.lastRow;
+
+ var lines = this.$lines;
+ while (lines.getLength()) lines.pop();
+
+ lines.push(this.$renderLinesFragment(config, firstRow, lastRow));
+ };
+
+ this.$textToken = {
+ text: true,
+ rparen: true,
+ lparen: true
+ };
+
+ this.$renderToken = function(parent, screenColumn, token, value) {
+ var self = this;
+ var re = /(\t)|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\uFEFF\uFFF9-\uFFFC]+)|(\u3000)|([\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3001-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]|[\uD800-\uDBFF][\uDC00-\uDFFF])/g;
+
+ var valueFragment = this.dom.createFragment(this.element);
+
+ var m;
+ var i = 0;
+ while ((m = re.exec(value))) {
+ var tab = m[1];
+ var simpleSpace = m[2];
+ var controlCharacter = m[3];
+ var cjkSpace = m[4];
+ var cjk = m[5];
+
+ if (!self.showSpaces && simpleSpace) continue;
+
+ var before = i != m.index ? value.slice(i, m.index) : "";
+
+ i = m.index + m[0].length;
+
+ if (before) {
+ valueFragment.appendChild(
+ this.dom.createTextNode(before, this.element)
+ );
+ }
+
+ if (tab) {
+ var tabSize = self.session.getScreenTabSize(screenColumn + m.index);
+ valueFragment.appendChild(
+ self.$tabStrings[tabSize].cloneNode(true)
+ );
+ screenColumn += tabSize - 1;
+ } else if (simpleSpace) {
+ if (self.showSpaces) {
+ var span = this.dom.createElement("span");
+ span.className = "ace_invisible ace_invisible_space";
+ span.textContent = lang.stringRepeat(
+ self.SPACE_CHAR,
+ simpleSpace.length
+ );
+ valueFragment.appendChild(span);
+ } else {
+ valueFragment.appendChild(
+ this.com.createTextNode(simpleSpace, this.element)
+ );
+ }
+ } else if (controlCharacter) {
+ var span = this.dom.createElement("span");
+ span.className = "ace_invisible ace_invisible_space ace_invalid";
+ span.textContent = lang.stringRepeat(
+ self.SPACE_CHAR,
+ controlCharacter.length
+ );
+ valueFragment.appendChild(span);
+ } else if (cjkSpace) {
+ screenColumn += 1;
+
+ var span = this.dom.createElement("span");
+ span.style.width = self.config.characterWidth * 2 + "px";
+ span.className = self.showSpaces
+ ? "ace_cjk ace_invisible ace_invisible_space"
+ : "ace_cjk";
+ span.textContent = self.showSpaces ? self.SPACE_CHAR : cjkSpace;
+ valueFragment.appendChild(span);
+ } else if (cjk) {
+ screenColumn += 1;
+ var span = this.dom.createElement("span");
+ span.style.width = self.config.characterWidth * 2 + "px";
+ span.className = "ace_cjk";
+ span.textContent = cjk;
+ valueFragment.appendChild(span);
+ }
+ }
+
+ valueFragment.appendChild(
+ this.dom.createTextNode(i ? value.slice(i) : value, this.element)
+ );
+
+ if (!this.$textToken[token.type]) {
+ var classes = "ace_" + token.type.replace(/\./g, " ace_");
+ var span = this.dom.createElement("span");
+ if (token.type == "fold")
+ span.style.width =
+ token.value.length * this.config.characterWidth + "px";
+
+ span.className = classes;
+ span.appendChild(valueFragment);
+
+ parent.appendChild(span);
+ } else {
+ parent.appendChild(valueFragment);
+ }
+
+ return screenColumn + value.length;
+ };
+
+ this.renderIndentGuide = function(parent, value, max) {
+ var cols = value.search(this.$indentGuideRe);
+ if (cols <= 0 || cols >= max) return value;
+ if (value[0] == " ") {
+ cols -= cols % this.tabSize;
+ var count = cols / this.tabSize;
+ for (var i = 0; i < count; i++) {
+ parent.appendChild(this.$tabStrings[" "].cloneNode(true));
+ }
+ return value.substr(cols);
+ } else if (value[0] == "\t") {
+ for (var i = 0; i < cols; i++) {
+ parent.appendChild(this.$tabStrings["\t"].cloneNode(true));
+ }
+ return value.substr(cols);
+ }
+ return value;
+ };
+
+ this.$createLineElement = function(parent) {
+ var lineEl = this.dom.createElement("div");
+ lineEl.className = "ace_line";
+ lineEl.style.height = this.config.lineHeight + "px";
+
+ return lineEl;
+ };
+
+ this.$renderWrappedLine = function(parent, tokens, splits) {
+ var chars = 0;
+ var split = 0;
+ var splitChars = splits[0];
+ var screenColumn = 0;
+
+ var lineEl = this.$createLineElement();
+ parent.appendChild(lineEl);
+
+ for (var i = 0; i < tokens.length; i++) {
+ var token = tokens[i];
+ var value = token.value;
+ if (i == 0 && this.displayIndentGuides) {
+ chars = value.length;
+ value = this.renderIndentGuide(lineEl, value, splitChars);
+ if (!value) continue;
+ chars -= value.length;
+ }
+
+ if (chars + value.length < splitChars) {
+ screenColumn = this.$renderToken(
+ lineEl,
+ screenColumn,
+ token,
+ value
+ );
+ chars += value.length;
+ } else {
+ while (chars + value.length >= splitChars) {
+ screenColumn = this.$renderToken(
+ lineEl,
+ screenColumn,
+ token,
+ value.substring(0, splitChars - chars)
+ );
+ value = value.substring(splitChars - chars);
+ chars = splitChars;
+
+ lineEl = this.$createLineElement();
+ parent.appendChild(lineEl);
+
+ lineEl.appendChild(
+ this.dom.createTextNode(
+ lang.stringRepeat("\xa0", splits.indent),
+ this.element
+ )
+ );
+
+ split++;
+ screenColumn = 0;
+ splitChars = splits[split] || Number.MAX_VALUE;
+ }
+ if (value.length != 0) {
+ chars += value.length;
+ screenColumn = this.$renderToken(
+ lineEl,
+ screenColumn,
+ token,
+ value
+ );
+ }
+ }
+ }
+
+ if (splits[splits.length - 1] > this.MAX_LINE_LENGTH)
+ this.$renderOverflowMessage(lineEl, screenColumn, null, "", true);
+ };
+
+ this.$renderSimpleLine = function(parent, tokens) {
+ var screenColumn = 0;
+ var token = tokens[0];
+ var value = token.value;
+ if (this.displayIndentGuides)
+ value = this.renderIndentGuide(parent, value);
+ if (value)
+ screenColumn = this.$renderToken(parent, screenColumn, token, value);
+ for (var i = 1; i < tokens.length; i++) {
+ token = tokens[i];
+ value = token.value;
+ if (screenColumn + value.length > this.MAX_LINE_LENGTH)
+ return this.$renderOverflowMessage(
+ parent,
+ screenColumn,
+ token,
+ value
+ );
+ screenColumn = this.$renderToken(parent, screenColumn, token, value);
+ }
+ };
+
+ this.$renderOverflowMessage = function(
+ parent,
+ screenColumn,
+ token,
+ value,
+ hide
+ ) {
+ token &&
+ this.$renderToken(
+ parent,
+ screenColumn,
+ token,
+ value.slice(0, this.MAX_LINE_LENGTH - screenColumn)
+ );
+
+ var overflowEl = this.dom.createElement("span");
+ overflowEl.className = "ace_inline_button ace_keyword ace_toggle_wrap";
+ overflowEl.textContent = hide ? "" : "";
+
+ parent.appendChild(overflowEl);
+ };
+ this.$renderLine = function(parent, row, foldLine) {
+ if (!foldLine && foldLine != false)
+ foldLine = this.session.getFoldLine(row);
+
+ if (foldLine) var tokens = this.$getFoldLineTokens(row, foldLine);
+ else var tokens = this.session.getTokens(row);
+
+ var lastLineEl = parent;
+ if (tokens.length) {
+ var splits = this.session.getRowSplitData(row);
+ if (splits && splits.length) {
+ this.$renderWrappedLine(parent, tokens, splits);
+ var lastLineEl = parent.lastChild;
+ } else {
+ var lastLineEl = parent;
+ if (this.$useLineGroups()) {
+ lastLineEl = this.$createLineElement();
+ parent.appendChild(lastLineEl);
+ }
+ this.$renderSimpleLine(lastLineEl, tokens);
+ }
+ } else if (this.$useLineGroups()) {
+ lastLineEl = this.$createLineElement();
+ parent.appendChild(lastLineEl);
+ }
+
+ if (this.showEOL && lastLineEl) {
+ if (foldLine) row = foldLine.end.row;
+
+ var invisibleEl = this.dom.createElement("span");
+ invisibleEl.className = "ace_invisible ace_invisible_eol";
+ invisibleEl.textContent =
+ row == this.session.getLength() - 1 ? this.EOF_CHAR : this.EOL_CHAR;
+
+ lastLineEl.appendChild(invisibleEl);
+ }
+ };
+
+ this.$getFoldLineTokens = function(row, foldLine) {
+ var session = this.session;
+ var renderTokens = [];
+
+ function addTokens(tokens, from, to) {
+ var idx = 0,
+ col = 0;
+ while (col + tokens[idx].value.length < from) {
+ col += tokens[idx].value.length;
+ idx++;
+
+ if (idx == tokens.length) return;
+ }
+ if (col != from) {
+ var value = tokens[idx].value.substring(from - col);
+ if (value.length > to - from) value = value.substring(0, to - from);
+
+ renderTokens.push({
+ type: tokens[idx].type,
+ value: value
+ });
+
+ col = from + value.length;
+ idx += 1;
+ }
+
+ while (col < to && idx < tokens.length) {
+ var value = tokens[idx].value;
+ if (value.length + col > to) {
+ renderTokens.push({
+ type: tokens[idx].type,
+ value: value.substring(0, to - col)
+ });
+ } else renderTokens.push(tokens[idx]);
+ col += value.length;
+ idx += 1;
+ }
+ }
+
+ var tokens = session.getTokens(row);
+ foldLine.walk(
+ function(placeholder, row, column, lastColumn, isNewRow) {
+ if (placeholder != null) {
+ renderTokens.push({
+ type: "fold",
+ value: placeholder
+ });
+ } else {
+ if (isNewRow) tokens = session.getTokens(row);
+
+ if (tokens.length) addTokens(tokens, lastColumn, column);
+ }
+ },
+ foldLine.end.row,
+ this.session.getLine(foldLine.end.row).length
+ );
+
+ return renderTokens;
+ };
+
+ this.$useLineGroups = function() {
+ return this.session.getUseWrapMode();
+ };
+
+ this.destroy = function() {};
+ }.call(Text.prototype));
+
+ exports.Text = Text;
+ }
+);
+
+ace.define(
+ "ace/layer/cursor",
+ ["require", "exports", "module", "ace/lib/dom"],
+ function(require, exports, module) {
+ "use strict";
+
+ var dom = require("../lib/dom");
+
+ var Cursor = function(parentEl) {
+ this.element = dom.createElement("div");
+ this.element.className = "ace_layer ace_cursor-layer";
+ parentEl.appendChild(this.element);
+
+ this.isVisible = false;
+ this.isBlinking = true;
+ this.blinkInterval = 1000;
+ this.smoothBlinking = false;
+
+ this.cursors = [];
+ this.cursor = this.addCursor();
+ dom.addCssClass(this.element, "ace_hidden-cursors");
+ this.$updateCursors = this.$updateOpacity.bind(this);
+ };
+
+ (function() {
+ this.$updateOpacity = function(val) {
+ var cursors = this.cursors;
+ for (var i = cursors.length; i--; )
+ dom.setStyle(cursors[i].style, "opacity", val ? "" : "0");
+ };
+
+ this.$startCssAnimation = function() {
+ var cursors = this.cursors;
+ for (var i = cursors.length; i--; )
+ cursors[i].style.animationDuration = this.blinkInterval + "ms";
+
+ setTimeout(
+ function() {
+ dom.addCssClass(this.element, "ace_animate-blinking");
+ }.bind(this)
+ );
+ };
+
+ this.$stopCssAnimation = function() {
+ dom.removeCssClass(this.element, "ace_animate-blinking");
+ };
+
+ this.$padding = 0;
+ this.setPadding = function(padding) {
+ this.$padding = padding;
+ };
+
+ this.setSession = function(session) {
+ this.session = session;
+ };
+
+ this.setBlinking = function(blinking) {
+ if (blinking != this.isBlinking) {
+ this.isBlinking = blinking;
+ this.restartTimer();
+ }
+ };
+
+ this.setBlinkInterval = function(blinkInterval) {
+ if (blinkInterval != this.blinkInterval) {
+ this.blinkInterval = blinkInterval;
+ this.restartTimer();
+ }
+ };
+
+ this.setSmoothBlinking = function(smoothBlinking) {
+ if (smoothBlinking != this.smoothBlinking) {
+ this.smoothBlinking = smoothBlinking;
+ dom.setCssClass(this.element, "ace_smooth-blinking", smoothBlinking);
+ this.$updateCursors(true);
+ this.restartTimer();
+ }
+ };
+
+ this.addCursor = function() {
+ var el = dom.createElement("div");
+ el.className = "ace_cursor";
+ this.element.appendChild(el);
+ this.cursors.push(el);
+ return el;
+ };
+
+ this.removeCursor = function() {
+ if (this.cursors.length > 1) {
+ var el = this.cursors.pop();
+ el.parentNode.removeChild(el);
+ return el;
+ }
+ };
+
+ this.hideCursor = function() {
+ this.isVisible = false;
+ dom.addCssClass(this.element, "ace_hidden-cursors");
+ this.restartTimer();
+ };
+
+ this.showCursor = function() {
+ this.isVisible = true;
+ dom.removeCssClass(this.element, "ace_hidden-cursors");
+ this.restartTimer();
+ };
+
+ this.restartTimer = function() {
+ var update = this.$updateCursors;
+ clearInterval(this.intervalId);
+ clearTimeout(this.timeoutId);
+ this.$stopCssAnimation();
+
+ if (this.smoothBlinking) {
+ dom.removeCssClass(this.element, "ace_smooth-blinking");
+ }
+
+ update(true);
+
+ if (!this.isBlinking || !this.blinkInterval || !this.isVisible) {
+ this.$stopCssAnimation();
+ return;
+ }
+
+ if (this.smoothBlinking) {
+ setTimeout(
+ function() {
+ dom.addCssClass(this.element, "ace_smooth-blinking");
+ }.bind(this)
+ );
+ }
+
+ if (dom.HAS_CSS_ANIMATION) {
+ this.$startCssAnimation();
+ } else {
+ var blink = function() {
+ this.timeoutId = setTimeout(function() {
+ update(false);
+ }, 0.6 * this.blinkInterval);
+ }.bind(this);
+
+ this.intervalId = setInterval(function() {
+ update(true);
+ blink();
+ }, this.blinkInterval);
+ blink();
+ }
+ };
+
+ this.getPixelPosition = function(position, onScreen) {
+ if (!this.config || !this.session) return { left: 0, top: 0 };
+
+ if (!position) position = this.session.selection.getCursor();
+ var pos = this.session.documentToScreenPosition(position);
+ var cursorLeft =
+ this.$padding +
+ (this.session.$bidiHandler.isBidiRow(pos.row, position.row)
+ ? this.session.$bidiHandler.getPosLeft(pos.column)
+ : pos.column * this.config.characterWidth);
+
+ var cursorTop =
+ (pos.row - (onScreen ? this.config.firstRowScreen : 0)) *
+ this.config.lineHeight;
+
+ return { left: cursorLeft, top: cursorTop };
+ };
+
+ this.isCursorInView = function(pixelPos, config) {
+ return pixelPos.top >= 0 && pixelPos.top < config.maxHeight;
+ };
+
+ this.update = function(config) {
+ this.config = config;
+
+ var selections = this.session.$selectionMarkers;
+ var i = 0,
+ cursorIndex = 0;
+
+ if (selections === undefined || selections.length === 0) {
+ selections = [{ cursor: null }];
+ }
+
+ for (var i = 0, n = selections.length; i < n; i++) {
+ var pixelPos = this.getPixelPosition(selections[i].cursor, true);
+ if (
+ (pixelPos.top > config.height + config.offset ||
+ pixelPos.top < 0) &&
+ i > 1
+ ) {
+ continue;
+ }
+
+ var element = this.cursors[cursorIndex++] || this.addCursor();
+ var style = element.style;
+
+ if (!this.drawCursor) {
+ if (!this.isCursorInView(pixelPos, config)) {
+ dom.setStyle(style, "display", "none");
+ } else {
+ dom.setStyle(style, "display", "block");
+ dom.translate(element, pixelPos.left, pixelPos.top);
+ dom.setStyle(
+ style,
+ "width",
+ Math.round(config.characterWidth) + "px"
+ );
+ dom.setStyle(style, "height", config.lineHeight + "px");
+ }
+ } else {
+ this.drawCursor(
+ element,
+ pixelPos,
+ config,
+ selections[i],
+ this.session
+ );
+ }
+ }
+ while (this.cursors.length > cursorIndex) this.removeCursor();
+
+ var overwrite = this.session.getOverwrite();
+ this.$setOverwrite(overwrite);
+ this.$pixelPos = pixelPos;
+ this.restartTimer();
+ };
+
+ this.drawCursor = null;
+
+ this.$setOverwrite = function(overwrite) {
+ if (overwrite != this.overwrite) {
+ this.overwrite = overwrite;
+ if (overwrite) dom.addCssClass(this.element, "ace_overwrite-cursors");
+ else dom.removeCssClass(this.element, "ace_overwrite-cursors");
+ }
+ };
+
+ this.destroy = function() {
+ clearInterval(this.intervalId);
+ clearTimeout(this.timeoutId);
+ };
+ }.call(Cursor.prototype));
+
+ exports.Cursor = Cursor;
+ }
+);
+
+ace.define(
+ "ace/scrollbar",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/lib/oop",
+ "ace/lib/dom",
+ "ace/lib/event",
+ "ace/lib/event_emitter"
+ ],
+ function(require, exports, module) {
+ "use strict";
+
+ var oop = require("./lib/oop");
+ var dom = require("./lib/dom");
+ var event = require("./lib/event");
+ var EventEmitter = require("./lib/event_emitter").EventEmitter;
+ var MAX_SCROLL_H = 0x8000;
+ var ScrollBar = function(parent) {
+ this.element = dom.createElement("div");
+ this.element.className = "ace_scrollbar ace_scrollbar" + this.classSuffix;
+
+ this.inner = dom.createElement("div");
+ this.inner.className = "ace_scrollbar-inner";
+ this.inner.textContent = "\xa0";
+ this.element.appendChild(this.inner);
+
+ parent.appendChild(this.element);
+
+ this.setVisible(false);
+ this.skipEvent = false;
+
+ event.addListener(this.element, "scroll", this.onScroll.bind(this));
+ event.addListener(this.element, "mousedown", event.preventDefault);
+ };
+
+ (function() {
+ oop.implement(this, EventEmitter);
+
+ this.setVisible = function(isVisible) {
+ this.element.style.display = isVisible ? "" : "none";
+ this.isVisible = isVisible;
+ this.coeff = 1;
+ };
+ }.call(ScrollBar.prototype));
+ var VScrollBar = function(parent, renderer) {
+ ScrollBar.call(this, parent);
+ this.scrollTop = 0;
+ this.scrollHeight = 0;
+ renderer.$scrollbarWidth = this.width = dom.scrollbarWidth(
+ parent.ownerDocument
+ );
+ this.inner.style.width = this.element.style.width =
+ (this.width || 15) + 5 + "px";
+ this.$minWidth = 0;
+ };
+
+ oop.inherits(VScrollBar, ScrollBar);
+
+ (function() {
+ this.classSuffix = "-v";
+ this.onScroll = function() {
+ if (!this.skipEvent) {
+ this.scrollTop = this.element.scrollTop;
+ if (this.coeff != 1) {
+ var h = this.element.clientHeight / this.scrollHeight;
+ this.scrollTop = (this.scrollTop * (1 - h)) / (this.coeff - h);
+ }
+ this._emit("scroll", { data: this.scrollTop });
+ }
+ this.skipEvent = false;
+ };
+ this.getWidth = function() {
+ return Math.max(this.isVisible ? this.width : 0, this.$minWidth || 0);
+ };
+ this.setHeight = function(height) {
+ this.element.style.height = height + "px";
+ };
+ this.setInnerHeight = this.setScrollHeight = function(height) {
+ this.scrollHeight = height;
+ if (height > MAX_SCROLL_H) {
+ this.coeff = MAX_SCROLL_H / height;
+ height = MAX_SCROLL_H;
+ } else if (this.coeff != 1) {
+ this.coeff = 1;
+ }
+ this.inner.style.height = height + "px";
+ };
+ this.setScrollTop = function(scrollTop) {
+ if (this.scrollTop != scrollTop) {
+ this.skipEvent = true;
+ this.scrollTop = scrollTop;
+ this.element.scrollTop = scrollTop * this.coeff;
+ }
+ };
+ }.call(VScrollBar.prototype));
+ var HScrollBar = function(parent, renderer) {
+ ScrollBar.call(this, parent);
+ this.scrollLeft = 0;
+ this.height = renderer.$scrollbarWidth;
+ this.inner.style.height = this.element.style.height =
+ (this.height || 15) + 5 + "px";
+ };
+
+ oop.inherits(HScrollBar, ScrollBar);
+
+ (function() {
+ this.classSuffix = "-h";
+ this.onScroll = function() {
+ if (!this.skipEvent) {
+ this.scrollLeft = this.element.scrollLeft;
+ this._emit("scroll", { data: this.scrollLeft });
+ }
+ this.skipEvent = false;
+ };
+ this.getHeight = function() {
+ return this.isVisible ? this.height : 0;
+ };
+ this.setWidth = function(width) {
+ this.element.style.width = width + "px";
+ };
+ this.setInnerWidth = function(width) {
+ this.inner.style.width = width + "px";
+ };
+ this.setScrollWidth = function(width) {
+ this.inner.style.width = width + "px";
+ };
+ this.setScrollLeft = function(scrollLeft) {
+ if (this.scrollLeft != scrollLeft) {
+ this.skipEvent = true;
+ this.scrollLeft = this.element.scrollLeft = scrollLeft;
+ }
+ };
+ }.call(HScrollBar.prototype));
+
+ exports.ScrollBar = VScrollBar; // backward compatibility
+ exports.ScrollBarV = VScrollBar; // backward compatibility
+ exports.ScrollBarH = HScrollBar; // backward compatibility
+
+ exports.VScrollBar = VScrollBar;
+ exports.HScrollBar = HScrollBar;
+ }
+);
+
+ace.define(
+ "ace/renderloop",
+ ["require", "exports", "module", "ace/lib/event"],
+ function(require, exports, module) {
+ "use strict";
+
+ var event = require("./lib/event");
+
+ var RenderLoop = function(onRender, win) {
+ this.onRender = onRender;
+ this.pending = false;
+ this.changes = 0;
+ this.$recursionLimit = 2;
+ this.window = win || window;
+ var _self = this;
+ this._flush = function(ts) {
+ _self.pending = false;
+ var changes = _self.changes;
+
+ if (changes) {
+ event.blockIdle(100);
+ _self.changes = 0;
+ _self.onRender(changes);
+ }
+
+ if (_self.changes) {
+ if (_self.$recursionLimit-- < 0) return;
+ _self.schedule();
+ } else {
+ _self.$recursionLimit = 2;
+ }
+ };
+ };
+
+ (function() {
+ this.schedule = function(change) {
+ this.changes = this.changes | change;
+ if (this.changes && !this.pending) {
+ event.nextFrame(this._flush);
+ this.pending = true;
+ }
+ };
+
+ this.clear = function(change) {
+ var changes = this.changes;
+ this.changes = 0;
+ return changes;
+ };
+ }.call(RenderLoop.prototype));
+
+ exports.RenderLoop = RenderLoop;
+ }
+);
+
+ace.define(
+ "ace/layer/font_metrics",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/lib/oop",
+ "ace/lib/dom",
+ "ace/lib/lang",
+ "ace/lib/event",
+ "ace/lib/useragent",
+ "ace/lib/event_emitter"
+ ],
+ function(require, exports, module) {
+ var oop = require("../lib/oop");
+ var dom = require("../lib/dom");
+ var lang = require("../lib/lang");
+ var event = require("../lib/event");
+ var useragent = require("../lib/useragent");
+ var EventEmitter = require("../lib/event_emitter").EventEmitter;
+
+ var CHAR_COUNT = 256;
+ var USE_OBSERVER = typeof ResizeObserver == "function";
+ var L = 200;
+
+ var FontMetrics = (exports.FontMetrics = function(parentEl) {
+ this.el = dom.createElement("div");
+ this.$setMeasureNodeStyles(this.el.style, true);
+
+ this.$main = dom.createElement("div");
+ this.$setMeasureNodeStyles(this.$main.style);
+
+ this.$measureNode = dom.createElement("div");
+ this.$setMeasureNodeStyles(this.$measureNode.style);
+
+ this.el.appendChild(this.$main);
+ this.el.appendChild(this.$measureNode);
+ parentEl.appendChild(this.el);
+
+ this.$measureNode.textContent = lang.stringRepeat("X", CHAR_COUNT);
+
+ this.$characterSize = { width: 0, height: 0 };
+
+ if (USE_OBSERVER) this.$addObserver();
+ else this.checkForSizeChanges();
+ });
+
+ (function() {
+ oop.implement(this, EventEmitter);
+
+ this.$characterSize = { width: 0, height: 0 };
+
+ this.$setMeasureNodeStyles = function(style, isRoot) {
+ style.width = style.height = "auto";
+ style.left = style.top = "0px";
+ style.visibility = "hidden";
+ style.position = "absolute";
+ style.whiteSpace = "pre";
+
+ if (useragent.isIE < 8) {
+ style["font-family"] = "inherit";
+ } else {
+ style.font = "inherit";
+ }
+ style.overflow = isRoot ? "hidden" : "visible";
+ };
+
+ this.checkForSizeChanges = function(size) {
+ if (size === undefined) size = this.$measureSizes();
+ if (
+ size &&
+ (this.$characterSize.width !== size.width ||
+ this.$characterSize.height !== size.height)
+ ) {
+ this.$measureNode.style.fontWeight = "bold";
+ var boldSize = this.$measureSizes();
+ this.$measureNode.style.fontWeight = "";
+ this.$characterSize = size;
+ this.charSizes = Object.create(null);
+ this.allowBoldFonts =
+ boldSize &&
+ boldSize.width === size.width &&
+ boldSize.height === size.height;
+ this._emit("changeCharacterSize", { data: size });
+ }
+ };
+
+ this.$addObserver = function() {
+ var self = this;
+ this.$observer = new window.ResizeObserver(function(e) {
+ self.checkForSizeChanges();
+ });
+ this.$observer.observe(this.$measureNode);
+ };
+
+ this.$pollSizeChanges = function() {
+ if (this.$pollSizeChangesTimer || this.$observer)
+ return this.$pollSizeChangesTimer;
+ var self = this;
+
+ return (this.$pollSizeChangesTimer = event.onIdle(function cb() {
+ self.checkForSizeChanges();
+ event.onIdle(cb, 500);
+ }, 500));
+ };
+
+ this.setPolling = function(val) {
+ if (val) {
+ this.$pollSizeChanges();
+ } else if (this.$pollSizeChangesTimer) {
+ clearInterval(this.$pollSizeChangesTimer);
+ this.$pollSizeChangesTimer = 0;
+ }
+ };
+
+ this.$measureSizes = function(node) {
+ var size = {
+ height: (node || this.$measureNode).clientHeight,
+ width: (node || this.$measureNode).clientWidth / CHAR_COUNT
+ };
+ if (size.width === 0 || size.height === 0) return null;
+ return size;
+ };
+
+ this.$measureCharWidth = function(ch) {
+ this.$main.textContent = lang.stringRepeat(ch, CHAR_COUNT);
+ var rect = this.$main.getBoundingClientRect();
+ return rect.width / CHAR_COUNT;
+ };
+
+ this.getCharacterWidth = function(ch) {
+ var w = this.charSizes[ch];
+ if (w === undefined) {
+ w = this.charSizes[ch] =
+ this.$measureCharWidth(ch) / this.$characterSize.width;
+ }
+ return w;
+ };
+
+ this.destroy = function() {
+ clearInterval(this.$pollSizeChangesTimer);
+ if (this.$observer) this.$observer.disconnect();
+ if (this.el && this.el.parentNode)
+ this.el.parentNode.removeChild(this.el);
+ };
+
+ this.$getZoom = function getZoom(element) {
+ if (!element) return 1;
+ return (
+ (window.getComputedStyle(element).zoom || 1) *
+ getZoom(element.parentElement)
+ );
+ };
+ this.$initTransformMeasureNodes = function() {
+ var t = function(t, l) {
+ return [
+ "div",
+ {
+ style: "position: absolute;top:" + t + "px;left:" + l + "px;"
+ }
+ ];
+ };
+ this.els = dom.buildDom([t(0, 0), t(L, 0), t(0, L), t(L, L)], this.el);
+ };
+ this.transformCoordinates = function(clientPos, elPos) {
+ if (clientPos) {
+ var zoom = this.$getZoom(this.el);
+ clientPos = mul(1 / zoom, clientPos);
+ }
+ function solve(l1, l2, r) {
+ var det = l1[1] * l2[0] - l1[0] * l2[1];
+ return [
+ (-l2[1] * r[0] + l2[0] * r[1]) / det,
+ (+l1[1] * r[0] - l1[0] * r[1]) / det
+ ];
+ }
+ function sub(a, b) {
+ return [a[0] - b[0], a[1] - b[1]];
+ }
+ function add(a, b) {
+ return [a[0] + b[0], a[1] + b[1]];
+ }
+ function mul(a, b) {
+ return [a * b[0], a * b[1]];
+ }
+
+ if (!this.els) this.$initTransformMeasureNodes();
+
+ function p(el) {
+ var r = el.getBoundingClientRect();
+ return [r.left, r.top];
+ }
+
+ var a = p(this.els[0]);
+ var b = p(this.els[1]);
+ var c = p(this.els[2]);
+ var d = p(this.els[3]);
+
+ var h = solve(sub(d, b), sub(d, c), sub(add(b, c), add(d, a)));
+
+ var m1 = mul(1 + h[0], sub(b, a));
+ var m2 = mul(1 + h[1], sub(c, a));
+
+ if (elPos) {
+ var x = elPos;
+ var k = (h[0] * x[0]) / L + (h[1] * x[1]) / L + 1;
+ var ut = add(mul(x[0], m1), mul(x[1], m2));
+ return add(mul(1 / k / L, ut), a);
+ }
+ var u = sub(clientPos, a);
+ var f = solve(sub(m1, mul(h[0], u)), sub(m2, mul(h[1], u)), u);
+ return mul(L, f);
+ };
+ }.call(FontMetrics.prototype));
+ }
+);
+
+ace.define(
+ "ace/virtual_renderer",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/lib/oop",
+ "ace/lib/dom",
+ "ace/config",
+ "ace/layer/gutter",
+ "ace/layer/marker",
+ "ace/layer/text",
+ "ace/layer/cursor",
+ "ace/scrollbar",
+ "ace/scrollbar",
+ "ace/renderloop",
+ "ace/layer/font_metrics",
+ "ace/lib/event_emitter",
+ "ace/lib/useragent"
+ ],
+ function(require, exports, module) {
+ "use strict";
+
+ var oop = require("./lib/oop");
+ var dom = require("./lib/dom");
+ var config = require("./config");
+ var GutterLayer = require("./layer/gutter").Gutter;
+ var MarkerLayer = require("./layer/marker").Marker;
+ var TextLayer = require("./layer/text").Text;
+ var CursorLayer = require("./layer/cursor").Cursor;
+ var HScrollBar = require("./scrollbar").HScrollBar;
+ var VScrollBar = require("./scrollbar").VScrollBar;
+ var RenderLoop = require("./renderloop").RenderLoop;
+ var FontMetrics = require("./layer/font_metrics").FontMetrics;
+ var EventEmitter = require("./lib/event_emitter").EventEmitter;
+ var editorCss =
+ '\
+ .ace_br1 {border-top-left-radius : 3px;}\
+ .ace_br2 {border-top-right-radius : 3px;}\
+ .ace_br3 {border-top-left-radius : 3px; border-top-right-radius: 3px;}\
+ .ace_br4 {border-bottom-right-radius: 3px;}\
+ .ace_br5 {border-top-left-radius : 3px; border-bottom-right-radius: 3px;}\
+ .ace_br6 {border-top-right-radius : 3px; border-bottom-right-radius: 3px;}\
+ .ace_br7 {border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px;}\
+ .ace_br8 {border-bottom-left-radius : 3px;}\
+ .ace_br9 {border-top-left-radius : 3px; border-bottom-left-radius: 3px;}\
+ .ace_br10{border-top-right-radius : 3px; border-bottom-left-radius: 3px;}\
+ .ace_br11{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-left-radius: 3px;}\
+ .ace_br12{border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\
+ .ace_br13{border-top-left-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\
+ .ace_br14{border-top-right-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\
+ .ace_br15{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\
+ .ace_editor {\
+ position: relative;\
+ overflow: hidden;\
+ padding: 0;\
+ direction: ltr;\
+ text-align: left;\
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\
+ }\
+ .ace_editor div {\
+ font-family: monospace !important;\
+ }\
+ .ace_scroller {\
+ position: absolute;\
+ overflow: hidden;\
+ top: 0;\
+ bottom: 0;\
+ background-color: inherit;\
+ -ms-user-select: none;\
+ -moz-user-select: none;\
+ -webkit-user-select: none;\
+ user-select: none;\
+ cursor: text;\
+ }\
+ .ace_content {\
+ position: absolute;\
+ box-sizing: border-box;\
+ min-width: 100%;\
+ contain: style size layout;\
+ font-variant-ligatures: no-common-ligatures;\
+ }\
+ .ace_dragging .ace_scroller:before{\
+ position: absolute;\
+ top: 0;\
+ left: 0;\
+ right: 0;\
+ bottom: 0;\
+ content: \'\';\
+ background: rgba(250, 250, 250, 0.01);\
+ z-index: 1000;\
+ }\
+ .ace_dragging.ace_dark .ace_scroller:before{\
+ background: rgba(0, 0, 0, 0.01);\
+ }\
+ .ace_selecting, .ace_selecting * {\
+ cursor: text !important;\
+ }\
+ .ace_gutter {\
+ position: absolute;\
+ overflow : hidden;\
+ width: auto;\
+ top: 0;\
+ bottom: 0;\
+ left: 0;\
+ cursor: default;\
+ z-index: 4;\
+ -ms-user-select: none;\
+ -moz-user-select: none;\
+ -webkit-user-select: none;\
+ user-select: none;\
+ contain: style size layout;\
+ }\
+ .ace_gutter-active-line {\
+ position: absolute;\
+ left: 0;\
+ right: 0;\
+ }\
+ .ace_scroller.ace_scroll-left {\
+ box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset;\
+ }\
+ .ace_gutter-cell {\
+ position: absolute;\
+ top: 0;\
+ left: 0;\
+ right: 0;\
+ padding-left: 19px;\
+ padding-right: 6px;\
+ background-repeat: no-repeat;\
+ }\
+ .ace_gutter-cell.ace_error {\
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitmk2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg==");\
+ background-repeat: no-repeat;\
+ background-position: 2px center;\
+ }\
+ .ace_gutter-cell.ace_warning {\
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg==");\
+ background-position: 2px center;\
+ }\
+ .ace_gutter-cell.ace_info {\
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAJ0Uk5TAAB2k804AAAAPklEQVQY02NgIB68QuO3tiLznjAwpKTgNyDbMegwisCHZUETUZV0ZqOquBpXj2rtnpSJT1AEnnRmL2OgGgAAIKkRQap2htgAAAAASUVORK5CYII=");\
+ background-position: 2px center;\
+ }\
+ .ace_dark .ace_gutter-cell.ace_info {\
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAChoaGAgIAqKiq+vr6tra1ZWVmUlJSbm5s8PDxubm56enrdgzg3AAAAAXRSTlMAQObYZgAAAClJREFUeNpjYMAPdsMYHegyJZFQBlsUlMFVCWUYKkAZMxZAGdxlDMQBAG+TBP4B6RyJAAAAAElFTkSuQmCC");\
+ }\
+ .ace_scrollbar {\
+ contain: strict;\
+ position: absolute;\
+ right: 0;\
+ bottom: 0;\
+ z-index: 6;\
+ }\
+ .ace_scrollbar-inner {\
+ position: absolute;\
+ cursor: text;\
+ left: 0;\
+ top: 0;\
+ }\
+ .ace_scrollbar-v{\
+ overflow-x: hidden;\
+ overflow-y: scroll;\
+ top: 0;\
+ }\
+ .ace_scrollbar-h {\
+ overflow-x: scroll;\
+ overflow-y: hidden;\
+ left: 0;\
+ }\
+ .ace_print-margin {\
+ position: absolute;\
+ height: 100%;\
+ }\
+ .ace_text-input {\
+ position: absolute;\
+ z-index: 0;\
+ width: 0.5em;\
+ height: 1em;\
+ opacity: 0;\
+ background: transparent;\
+ -moz-appearance: none;\
+ appearance: none;\
+ border: none;\
+ resize: none;\
+ outline: none;\
+ overflow: hidden;\
+ padding: 0 1px;\
+ margin: 0 -1px;\
+ contain: strict;\
+ -ms-user-select: text;\
+ -moz-user-select: text;\
+ -webkit-user-select: text;\
+ user-select: text;\
+ white-space: pre!important;\
+ }\
+ .ace_text-input.ace_composition {\
+ background: transparent;\
+ color: inherit;\
+ z-index: 1000;\
+ opacity: 1;\
+ }\
+ .ace_composition_placeholder { color: transparent }\
+ .ace_composition_marker { \
+ border-bottom: 1px solid;\
+ position: absolute;\
+ border-radius: 0;\
+ margin-top: 1px;\
+ }\
+ [ace_nocontext=true] {\
+ transform: none!important;\
+ filter: none!important;\
+ clip-path: none!important;\
+ mask : none!important;\
+ contain: none!important;\
+ perspective: none!important;\
+ mix-blend-mode: initial!important;\
+ z-index: auto;\
+ }\
+ .ace_layer {\
+ z-index: 1;\
+ position: absolute;\
+ overflow: hidden;\
+ word-wrap: normal;\
+ white-space: pre;\
+ height: 100%;\
+ width: 100%;\
+ box-sizing: border-box;\
+ pointer-events: none;\
+ }\
+ .ace_gutter-layer {\
+ position: relative;\
+ width: auto;\
+ text-align: right;\
+ pointer-events: auto;\
+ height: 1000000px;\
+ contain: style size layout;\
+ }\
+ .ace_text-layer {\
+ font: inherit !important;\
+ position: absolute;\
+ height: 1000000px;\
+ width: 1000000px;\
+ contain: style size layout;\
+ }\
+ .ace_text-layer > .ace_line, .ace_text-layer > .ace_line_group {\
+ contain: style size layout;\
+ position: absolute;\
+ top: 0;\
+ left: 0;\
+ right: 0;\
+ }\
+ .ace_hidpi .ace_text-layer,\
+ .ace_hidpi .ace_gutter-layer,\
+ .ace_hidpi .ace_content,\
+ .ace_hidpi .ace_gutter {\
+ contain: strict;\
+ will-change: transform;\
+ }\
+ .ace_hidpi .ace_text-layer > .ace_line, \
+ .ace_hidpi .ace_text-layer > .ace_line_group {\
+ contain: strict;\
+ }\
+ .ace_cjk {\
+ display: inline-block;\
+ text-align: center;\
+ }\
+ .ace_cursor-layer {\
+ z-index: 4;\
+ }\
+ .ace_cursor {\
+ z-index: 4;\
+ position: absolute;\
+ box-sizing: border-box;\
+ border-left: 2px solid;\
+ transform: translatez(0);\
+ }\
+ .ace_multiselect .ace_cursor {\
+ border-left-width: 1px;\
+ }\
+ .ace_slim-cursors .ace_cursor {\
+ border-left-width: 1px;\
+ }\
+ .ace_overwrite-cursors .ace_cursor {\
+ border-left-width: 0;\
+ border-bottom: 1px solid;\
+ }\
+ .ace_hidden-cursors .ace_cursor {\
+ opacity: 0.2;\
+ }\
+ .ace_hasPlaceholder .ace_hidden-cursors .ace_cursor {\
+ opacity: 0;\
+ }\
+ .ace_smooth-blinking .ace_cursor {\
+ transition: opacity 0.18s;\
+ }\
+ .ace_animate-blinking .ace_cursor {\
+ animation-duration: 1000ms;\
+ animation-timing-function: step-end;\
+ animation-name: blink-ace-animate;\
+ animation-iteration-count: infinite;\
+ }\
+ .ace_animate-blinking.ace_smooth-blinking .ace_cursor {\
+ animation-duration: 1000ms;\
+ animation-timing-function: ease-in-out;\
+ animation-name: blink-ace-animate-smooth;\
+ }\
+ @keyframes blink-ace-animate {\
+ from, to { opacity: 1; }\
+ 60% { opacity: 0; }\
+ }\
+ @keyframes blink-ace-animate-smooth {\
+ from, to { opacity: 1; }\
+ 45% { opacity: 1; }\
+ 60% { opacity: 0; }\
+ 85% { opacity: 0; }\
+ }\
+ .ace_marker-layer .ace_step, .ace_marker-layer .ace_stack {\
+ position: absolute;\
+ z-index: 3;\
+ }\
+ .ace_marker-layer .ace_selection {\
+ position: absolute;\
+ z-index: 5;\
+ }\
+ .ace_marker-layer .ace_bracket {\
+ position: absolute;\
+ z-index: 6;\
+ }\
+ .ace_marker-layer .ace_error_bracket {\
+ position: absolute;\
+ border-bottom: 1px solid #DE5555;\
+ border-radius: 0;\
+ }\
+ .ace_marker-layer .ace_active-line {\
+ position: absolute;\
+ z-index: 2;\
+ }\
+ .ace_marker-layer .ace_selected-word {\
+ position: absolute;\
+ z-index: 4;\
+ box-sizing: border-box;\
+ }\
+ .ace_line .ace_fold {\
+ box-sizing: border-box;\
+ display: inline-block;\
+ height: 11px;\
+ margin-top: -2px;\
+ vertical-align: middle;\
+ background-image:\
+ url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="),\
+ url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi+P//fxgTAwPDBxDxD078RSX+YeEyDFMCIMAAI3INmXiwf2YAAAAASUVORK5CYII=");\
+ background-repeat: no-repeat, repeat-x;\
+ background-position: center center, top left;\
+ color: transparent;\
+ border: 1px solid black;\
+ border-radius: 2px;\
+ cursor: pointer;\
+ pointer-events: auto;\
+ }\
+ .ace_dark .ace_fold {\
+ }\
+ .ace_fold:hover{\
+ background-image:\
+ url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="),\
+ url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi+P//fz4TAwPDZxDxD5X4i5fLMEwJgAADAEPVDbjNw87ZAAAAAElFTkSuQmCC");\
+ }\
+ .ace_tooltip {\
+ background-color: #FFF;\
+ background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1));\
+ border: 1px solid gray;\
+ border-radius: 1px;\
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);\
+ color: black;\
+ max-width: 100%;\
+ padding: 3px 4px;\
+ position: fixed;\
+ z-index: 999999;\
+ box-sizing: border-box;\
+ cursor: default;\
+ white-space: pre;\
+ word-wrap: break-word;\
+ line-height: normal;\
+ font-style: normal;\
+ font-weight: normal;\
+ letter-spacing: normal;\
+ pointer-events: none;\
+ }\
+ .ace_folding-enabled > .ace_gutter-cell {\
+ padding-right: 13px;\
+ }\
+ .ace_fold-widget {\
+ box-sizing: border-box;\
+ margin: 0 -12px 0 1px;\
+ display: none;\
+ width: 11px;\
+ vertical-align: top;\
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg==");\
+ background-repeat: no-repeat;\
+ background-position: center;\
+ border-radius: 3px;\
+ border: 1px solid transparent;\
+ cursor: pointer;\
+ }\
+ .ace_folding-enabled .ace_fold-widget {\
+ display: inline-block; \
+ }\
+ .ace_fold-widget.ace_end {\
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg==");\
+ }\
+ .ace_fold-widget.ace_closed {\
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA==");\
+ }\
+ .ace_fold-widget:hover {\
+ border: 1px solid rgba(0, 0, 0, 0.3);\
+ background-color: rgba(255, 255, 255, 0.2);\
+ box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\
+ }\
+ .ace_fold-widget:active {\
+ border: 1px solid rgba(0, 0, 0, 0.4);\
+ background-color: rgba(0, 0, 0, 0.05);\
+ box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\
+ }\
+ .ace_dark .ace_fold-widget {\
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC");\
+ }\
+ .ace_dark .ace_fold-widget.ace_end {\
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg==");\
+ }\
+ .ace_dark .ace_fold-widget.ace_closed {\
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg==");\
+ }\
+ .ace_dark .ace_fold-widget:hover {\
+ box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\
+ background-color: rgba(255, 255, 255, 0.1);\
+ }\
+ .ace_dark .ace_fold-widget:active {\
+ box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\
+ }\
+ .ace_inline_button {\
+ border: 1px solid lightgray;\
+ display: inline-block;\
+ margin: -1px 8px;\
+ padding: 0 5px;\
+ pointer-events: auto;\
+ cursor: pointer;\
+ }\
+ .ace_inline_button:hover {\
+ border-color: gray;\
+ background: rgba(200,200,200,0.2);\
+ display: inline-block;\
+ pointer-events: auto;\
+ }\
+ .ace_fold-widget.ace_invalid {\
+ background-color: #FFB4B4;\
+ border-color: #DE5555;\
+ }\
+ .ace_fade-fold-widgets .ace_fold-widget {\
+ transition: opacity 0.4s ease 0.05s;\
+ opacity: 0;\
+ }\
+ .ace_fade-fold-widgets:hover .ace_fold-widget {\
+ transition: opacity 0.05s ease 0.05s;\
+ opacity:1;\
+ }\
+ .ace_underline {\
+ text-decoration: underline;\
+ }\
+ .ace_bold {\
+ font-weight: bold;\
+ }\
+ .ace_nobold .ace_bold {\
+ font-weight: normal;\
+ }\
+ .ace_italic {\
+ font-style: italic;\
+ }\
+ .ace_error-marker {\
+ background-color: rgba(255, 0, 0,0.2);\
+ position: absolute;\
+ z-index: 9;\
+ }\
+ .ace_highlight-marker {\
+ background-color: rgba(255, 255, 0,0.2);\
+ position: absolute;\
+ z-index: 8;\
+ }\
+ .ace_mobile-menu {\
+ position: absolute;\
+ line-height: 1.5;\
+ border-radius: 4px;\
+ -ms-user-select: none;\
+ -moz-user-select: none;\
+ -webkit-user-select: none;\
+ user-select: none;\
+ background: white;\
+ box-shadow: 1px 3px 2px grey;\
+ border: 1px solid #dcdcdc;\
+ color: black;\
+ }\
+ .ace_dark > .ace_mobile-menu {\
+ background: #333;\
+ color: #ccc;\
+ box-shadow: 1px 3px 2px grey;\
+ border: 1px solid #444;\
+ }\
+ .ace_mobile-button {\
+ padding: 2px;\
+ cursor: pointer;\
+ overflow: hidden;\
+ }\
+ .ace_mobile-button:hover {\
+ background-color: #eee;\
+ opacity:1;\
+ }\
+ .ace_mobile-button:active {\
+ background-color: #ddd;\
+ }\
+ .ace_placeholder {\
+ transform: scale(0.9);\
+ transform-origin: left;\
+ white-space: pre;\
+ opacity: 0.7;\
+ margin: 0 10px;\
+ }';
+
+ var useragent = require("./lib/useragent");
+ var HIDE_TEXTAREA = useragent.isIE;
+
+ dom.importCssString(editorCss, "ace_editor.css");
+
+ var VirtualRenderer = function(container, theme) {
+ var _self = this;
+
+ this.container = container || dom.createElement("div");
+
+ dom.addCssClass(this.container, "ace_editor");
+ if (dom.HI_DPI) dom.addCssClass(this.container, "ace_hidpi");
+
+ this.setTheme(theme);
+
+ this.$gutter = dom.createElement("div");
+ this.$gutter.className = "ace_gutter";
+ this.container.appendChild(this.$gutter);
+ this.$gutter.setAttribute("aria-hidden", true);
+
+ this.scroller = dom.createElement("div");
+ this.scroller.className = "ace_scroller";
+
+ this.container.appendChild(this.scroller);
+
+ this.content = dom.createElement("div");
+ this.content.className = "ace_content";
+ this.scroller.appendChild(this.content);
+
+ this.$gutterLayer = new GutterLayer(this.$gutter);
+ this.$gutterLayer.on("changeGutterWidth", this.onGutterResize.bind(this));
+
+ this.$markerBack = new MarkerLayer(this.content);
+
+ var textLayer = (this.$textLayer = new TextLayer(this.content));
+ this.canvas = textLayer.element;
+
+ this.$markerFront = new MarkerLayer(this.content);
+
+ this.$cursorLayer = new CursorLayer(this.content);
+ this.$horizScroll = false;
+ this.$vScroll = false;
+
+ this.scrollBar = this.scrollBarV = new VScrollBar(this.container, this);
+ this.scrollBarH = new HScrollBar(this.container, this);
+ this.scrollBarV.on("scroll", function(e) {
+ if (!_self.$scrollAnimation)
+ _self.session.setScrollTop(e.data - _self.scrollMargin.top);
+ });
+ this.scrollBarH.on("scroll", function(e) {
+ if (!_self.$scrollAnimation)
+ _self.session.setScrollLeft(e.data - _self.scrollMargin.left);
+ });
+
+ this.scrollTop = 0;
+ this.scrollLeft = 0;
+
+ this.cursorPos = {
+ row: 0,
+ column: 0
+ };
+
+ this.$fontMetrics = new FontMetrics(this.container);
+ this.$textLayer.$setFontMetrics(this.$fontMetrics);
+ this.$textLayer.on("changeCharacterSize", function(e) {
+ _self.updateCharacterSize();
+ _self.onResize(
+ true,
+ _self.gutterWidth,
+ _self.$size.width,
+ _self.$size.height
+ );
+ _self._signal("changeCharacterSize", e);
+ });
+
+ this.$size = {
+ width: 0,
+ height: 0,
+ scrollerHeight: 0,
+ scrollerWidth: 0,
+ $dirty: true
+ };
+
+ this.layerConfig = {
+ width: 1,
+ padding: 0,
+ firstRow: 0,
+ firstRowScreen: 0,
+ lastRow: 0,
+ lineHeight: 0,
+ characterWidth: 0,
+ minHeight: 1,
+ maxHeight: 1,
+ offset: 0,
+ height: 1,
+ gutterOffset: 1
+ };
+
+ this.scrollMargin = {
+ left: 0,
+ right: 0,
+ top: 0,
+ bottom: 0,
+ v: 0,
+ h: 0
+ };
+
+ this.margin = {
+ left: 0,
+ right: 0,
+ top: 0,
+ bottom: 0,
+ v: 0,
+ h: 0
+ };
+
+ this.$keepTextAreaAtCursor = !useragent.isIOS;
+
+ this.$loop = new RenderLoop(
+ this.$renderChanges.bind(this),
+ this.container.ownerDocument.defaultView
+ );
+ this.$loop.schedule(this.CHANGE_FULL);
+
+ this.updateCharacterSize();
+ this.setPadding(4);
+ config.resetOptions(this);
+ config._signal("renderer", this);
+ };
+
+ (function() {
+ this.CHANGE_CURSOR = 1;
+ this.CHANGE_MARKER = 2;
+ this.CHANGE_GUTTER = 4;
+ this.CHANGE_SCROLL = 8;
+ this.CHANGE_LINES = 16;
+ this.CHANGE_TEXT = 32;
+ this.CHANGE_SIZE = 64;
+ this.CHANGE_MARKER_BACK = 128;
+ this.CHANGE_MARKER_FRONT = 256;
+ this.CHANGE_FULL = 512;
+ this.CHANGE_H_SCROLL = 1024;
+
+ oop.implement(this, EventEmitter);
+
+ this.updateCharacterSize = function() {
+ if (this.$textLayer.allowBoldFonts != this.$allowBoldFonts) {
+ this.$allowBoldFonts = this.$textLayer.allowBoldFonts;
+ this.setStyle("ace_nobold", !this.$allowBoldFonts);
+ }
+
+ this.layerConfig.characterWidth = this.characterWidth = this.$textLayer.getCharacterWidth();
+ this.layerConfig.lineHeight = this.lineHeight = this.$textLayer.getLineHeight();
+ this.$updatePrintMargin();
+ dom.setStyle(
+ this.scroller.style,
+ "line-height",
+ this.lineHeight + "px"
+ );
+ };
+ this.setSession = function(session) {
+ if (this.session)
+ this.session.doc.off("changeNewLineMode", this.onChangeNewLineMode);
+
+ this.session = session;
+ if (session && this.scrollMargin.top && session.getScrollTop() <= 0)
+ session.setScrollTop(-this.scrollMargin.top);
+
+ this.$cursorLayer.setSession(session);
+ this.$markerBack.setSession(session);
+ this.$markerFront.setSession(session);
+ this.$gutterLayer.setSession(session);
+ this.$textLayer.setSession(session);
+ if (!session) return;
+
+ this.$loop.schedule(this.CHANGE_FULL);
+ this.session.$setFontMetrics(this.$fontMetrics);
+ this.scrollBarH.scrollLeft = this.scrollBarV.scrollTop = null;
+
+ this.onChangeNewLineMode = this.onChangeNewLineMode.bind(this);
+ this.onChangeNewLineMode();
+ this.session.doc.on("changeNewLineMode", this.onChangeNewLineMode);
+ };
+ this.updateLines = function(firstRow, lastRow, force) {
+ if (lastRow === undefined) lastRow = Infinity;
+
+ if (!this.$changedLines) {
+ this.$changedLines = {
+ firstRow: firstRow,
+ lastRow: lastRow
+ };
+ } else {
+ if (this.$changedLines.firstRow > firstRow)
+ this.$changedLines.firstRow = firstRow;
+
+ if (this.$changedLines.lastRow < lastRow)
+ this.$changedLines.lastRow = lastRow;
+ }
+ if (this.$changedLines.lastRow < this.layerConfig.firstRow) {
+ if (force) this.$changedLines.lastRow = this.layerConfig.lastRow;
+ else return;
+ }
+ if (this.$changedLines.firstRow > this.layerConfig.lastRow) return;
+ this.$loop.schedule(this.CHANGE_LINES);
+ };
+
+ this.onChangeNewLineMode = function() {
+ this.$loop.schedule(this.CHANGE_TEXT);
+ this.$textLayer.$updateEolChar();
+ this.session.$bidiHandler.setEolChar(this.$textLayer.EOL_CHAR);
+ };
+
+ this.onChangeTabSize = function() {
+ this.$loop.schedule(this.CHANGE_TEXT | this.CHANGE_MARKER);
+ this.$textLayer.onChangeTabSize();
+ };
+ this.updateText = function() {
+ this.$loop.schedule(this.CHANGE_TEXT);
+ };
+ this.updateFull = function(force) {
+ if (force) this.$renderChanges(this.CHANGE_FULL, true);
+ else this.$loop.schedule(this.CHANGE_FULL);
+ };
+ this.updateFontSize = function() {
+ this.$textLayer.checkForSizeChanges();
+ };
+
+ this.$changes = 0;
+ this.$updateSizeAsync = function() {
+ if (this.$loop.pending) this.$size.$dirty = true;
+ else this.onResize();
+ };
+ this.onResize = function(force, gutterWidth, width, height) {
+ if (this.resizing > 2) return;
+ else if (this.resizing > 0) this.resizing++;
+ else this.resizing = force ? 1 : 0;
+ var el = this.container;
+ if (!height) height = el.clientHeight || el.scrollHeight;
+ if (!width) width = el.clientWidth || el.scrollWidth;
+ var changes = this.$updateCachedSize(force, gutterWidth, width, height);
+
+ if (!this.$size.scrollerHeight || (!width && !height))
+ return (this.resizing = 0);
+
+ if (force) this.$gutterLayer.$padding = null;
+
+ if (force) this.$renderChanges(changes | this.$changes, true);
+ else this.$loop.schedule(changes | this.$changes);
+
+ if (this.resizing) this.resizing = 0;
+ this.scrollBarV.scrollLeft = this.scrollBarV.scrollTop = null;
+ };
+
+ this.$updateCachedSize = function(force, gutterWidth, width, height) {
+ height -= this.$extraHeight || 0;
+ var changes = 0;
+ var size = this.$size;
+ var oldSize = {
+ width: size.width,
+ height: size.height,
+ scrollerHeight: size.scrollerHeight,
+ scrollerWidth: size.scrollerWidth
+ };
+ if (height && (force || size.height != height)) {
+ size.height = height;
+ changes |= this.CHANGE_SIZE;
+
+ size.scrollerHeight = size.height;
+ if (this.$horizScroll)
+ size.scrollerHeight -= this.scrollBarH.getHeight();
+ this.scrollBarV.element.style.bottom =
+ this.scrollBarH.getHeight() + "px";
+
+ changes = changes | this.CHANGE_SCROLL;
+ }
+
+ if (width && (force || size.width != width)) {
+ changes |= this.CHANGE_SIZE;
+ size.width = width;
+
+ if (gutterWidth == null)
+ gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0;
+
+ this.gutterWidth = gutterWidth;
+
+ dom.setStyle(
+ this.scrollBarH.element.style,
+ "left",
+ gutterWidth + "px"
+ );
+ dom.setStyle(
+ this.scroller.style,
+ "left",
+ gutterWidth + this.margin.left + "px"
+ );
+ size.scrollerWidth = Math.max(
+ 0,
+ width - gutterWidth - this.scrollBarV.getWidth() - this.margin.h
+ );
+ dom.setStyle(this.$gutter.style, "left", this.margin.left + "px");
+
+ var right = this.scrollBarV.getWidth() + "px";
+ dom.setStyle(this.scrollBarH.element.style, "right", right);
+ dom.setStyle(this.scroller.style, "right", right);
+ dom.setStyle(
+ this.scroller.style,
+ "bottom",
+ this.scrollBarH.getHeight()
+ );
+
+ if (
+ (this.session &&
+ this.session.getUseWrapMode() &&
+ this.adjustWrapLimit()) ||
+ force
+ ) {
+ changes |= this.CHANGE_FULL;
+ }
+ }
+
+ size.$dirty = !width || !height;
+
+ if (changes) this._signal("resize", oldSize);
+
+ return changes;
+ };
+
+ this.onGutterResize = function(width) {
+ var gutterWidth = this.$showGutter ? width : 0;
+ if (gutterWidth != this.gutterWidth)
+ this.$changes |= this.$updateCachedSize(
+ true,
+ gutterWidth,
+ this.$size.width,
+ this.$size.height
+ );
+
+ if (this.session.getUseWrapMode() && this.adjustWrapLimit()) {
+ this.$loop.schedule(this.CHANGE_FULL);
+ } else if (this.$size.$dirty) {
+ this.$loop.schedule(this.CHANGE_FULL);
+ } else {
+ this.$computeLayerConfig();
+ }
+ };
+ this.adjustWrapLimit = function() {
+ var availableWidth = this.$size.scrollerWidth - this.$padding * 2;
+ var limit = Math.floor(availableWidth / this.characterWidth);
+ return this.session.adjustWrapLimit(
+ limit,
+ this.$showPrintMargin && this.$printMarginColumn
+ );
+ };
+ this.setAnimatedScroll = function(shouldAnimate) {
+ this.setOption("animatedScroll", shouldAnimate);
+ };
+ this.getAnimatedScroll = function() {
+ return this.$animatedScroll;
+ };
+ this.setShowInvisibles = function(showInvisibles) {
+ this.setOption("showInvisibles", showInvisibles);
+ this.session.$bidiHandler.setShowInvisibles(showInvisibles);
+ };
+ this.getShowInvisibles = function() {
+ return this.getOption("showInvisibles");
+ };
+ this.getDisplayIndentGuides = function() {
+ return this.getOption("displayIndentGuides");
+ };
+
+ this.setDisplayIndentGuides = function(display) {
+ this.setOption("displayIndentGuides", display);
+ };
+ this.setShowPrintMargin = function(showPrintMargin) {
+ this.setOption("showPrintMargin", showPrintMargin);
+ };
+ this.getShowPrintMargin = function() {
+ return this.getOption("showPrintMargin");
+ };
+ this.setPrintMarginColumn = function(showPrintMargin) {
+ this.setOption("printMarginColumn", showPrintMargin);
+ };
+ this.getPrintMarginColumn = function() {
+ return this.getOption("printMarginColumn");
+ };
+ this.getShowGutter = function() {
+ return this.getOption("showGutter");
+ };
+ this.setShowGutter = function(show) {
+ return this.setOption("showGutter", show);
+ };
+
+ this.getFadeFoldWidgets = function() {
+ return this.getOption("fadeFoldWidgets");
+ };
+
+ this.setFadeFoldWidgets = function(show) {
+ this.setOption("fadeFoldWidgets", show);
+ };
+
+ this.setHighlightGutterLine = function(shouldHighlight) {
+ this.setOption("highlightGutterLine", shouldHighlight);
+ };
+
+ this.getHighlightGutterLine = function() {
+ return this.getOption("highlightGutterLine");
+ };
+
+ this.$updatePrintMargin = function() {
+ if (!this.$showPrintMargin && !this.$printMarginEl) return;
+
+ if (!this.$printMarginEl) {
+ var containerEl = dom.createElement("div");
+ containerEl.className = "ace_layer ace_print-margin-layer";
+ this.$printMarginEl = dom.createElement("div");
+ this.$printMarginEl.className = "ace_print-margin";
+ containerEl.appendChild(this.$printMarginEl);
+ this.content.insertBefore(containerEl, this.content.firstChild);
+ }
+
+ var style = this.$printMarginEl.style;
+ style.left =
+ Math.round(
+ this.characterWidth * this.$printMarginColumn + this.$padding
+ ) + "px";
+ style.visibility = this.$showPrintMargin ? "visible" : "hidden";
+
+ if (this.session && this.session.$wrap == -1) this.adjustWrapLimit();
+ };
+ this.getContainerElement = function() {
+ return this.container;
+ };
+ this.getMouseEventTarget = function() {
+ return this.scroller;
+ };
+ this.getTextAreaContainer = function() {
+ return this.container;
+ };
+ this.$moveTextAreaToCursor = function() {
+ if (this.$isMousePressed) return;
+ var style = this.textarea.style;
+ var composition = this.$composition;
+ if (!this.$keepTextAreaAtCursor && !composition) {
+ dom.translate(this.textarea, -100, 0);
+ return;
+ }
+ var pixelPos = this.$cursorLayer.$pixelPos;
+ if (!pixelPos) return;
+ if (composition && composition.markerRange)
+ pixelPos = this.$cursorLayer.getPixelPosition(
+ composition.markerRange.start,
+ true
+ );
+
+ var config = this.layerConfig;
+ var posTop = pixelPos.top;
+ var posLeft = pixelPos.left;
+ posTop -= config.offset;
+
+ var h =
+ composition && composition.useTextareaForIME
+ ? this.lineHeight
+ : HIDE_TEXTAREA
+ ? 0
+ : 1;
+ if (posTop < 0 || posTop > config.height - h) {
+ dom.translate(this.textarea, 0, 0);
+ return;
+ }
+
+ var w = 1;
+ var maxTop = this.$size.height - h;
+ if (!composition) {
+ posTop += this.lineHeight;
+ } else {
+ if (composition.useTextareaForIME) {
+ var val = this.textarea.value;
+ w =
+ this.characterWidth * this.session.$getStringScreenWidth(val)[0];
+ } else {
+ posTop += this.lineHeight + 2;
+ }
+ }
+
+ posLeft -= this.scrollLeft;
+ if (posLeft > this.$size.scrollerWidth - w)
+ posLeft = this.$size.scrollerWidth - w;
+
+ posLeft += this.gutterWidth + this.margin.left;
+
+ dom.setStyle(style, "height", h + "px");
+ dom.setStyle(style, "width", w + "px");
+ dom.translate(
+ this.textarea,
+ Math.min(posLeft, this.$size.scrollerWidth - w),
+ Math.min(posTop, maxTop)
+ );
+ };
+ this.getFirstVisibleRow = function() {
+ return this.layerConfig.firstRow;
+ };
+ this.getFirstFullyVisibleRow = function() {
+ return (
+ this.layerConfig.firstRow + (this.layerConfig.offset === 0 ? 0 : 1)
+ );
+ };
+ this.getLastFullyVisibleRow = function() {
+ var config = this.layerConfig;
+ var lastRow = config.lastRow;
+ var top =
+ this.session.documentToScreenRow(lastRow, 0) * config.lineHeight;
+ if (
+ top - this.session.getScrollTop() >
+ config.height - config.lineHeight
+ )
+ return lastRow - 1;
+ return lastRow;
+ };
+ this.getLastVisibleRow = function() {
+ return this.layerConfig.lastRow;
+ };
+
+ this.$padding = null;
+ this.setPadding = function(padding) {
+ this.$padding = padding;
+ this.$textLayer.setPadding(padding);
+ this.$cursorLayer.setPadding(padding);
+ this.$markerFront.setPadding(padding);
+ this.$markerBack.setPadding(padding);
+ this.$loop.schedule(this.CHANGE_FULL);
+ this.$updatePrintMargin();
+ };
+
+ this.setScrollMargin = function(top, bottom, left, right) {
+ var sm = this.scrollMargin;
+ sm.top = top | 0;
+ sm.bottom = bottom | 0;
+ sm.right = right | 0;
+ sm.left = left | 0;
+ sm.v = sm.top + sm.bottom;
+ sm.h = sm.left + sm.right;
+ if (sm.top && this.scrollTop <= 0 && this.session)
+ this.session.setScrollTop(-sm.top);
+ this.updateFull();
+ };
+
+ this.setMargin = function(top, bottom, left, right) {
+ var sm = this.margin;
+ sm.top = top | 0;
+ sm.bottom = bottom | 0;
+ sm.right = right | 0;
+ sm.left = left | 0;
+ sm.v = sm.top + sm.bottom;
+ sm.h = sm.left + sm.right;
+ this.$updateCachedSize(
+ true,
+ this.gutterWidth,
+ this.$size.width,
+ this.$size.height
+ );
+ this.updateFull();
+ };
+ this.getHScrollBarAlwaysVisible = function() {
+ return this.$hScrollBarAlwaysVisible;
+ };
+ this.setHScrollBarAlwaysVisible = function(alwaysVisible) {
+ this.setOption("hScrollBarAlwaysVisible", alwaysVisible);
+ };
+ this.getVScrollBarAlwaysVisible = function() {
+ return this.$vScrollBarAlwaysVisible;
+ };
+ this.setVScrollBarAlwaysVisible = function(alwaysVisible) {
+ this.setOption("vScrollBarAlwaysVisible", alwaysVisible);
+ };
+
+ this.$updateScrollBarV = function() {
+ var scrollHeight = this.layerConfig.maxHeight;
+ var scrollerHeight = this.$size.scrollerHeight;
+ if (!this.$maxLines && this.$scrollPastEnd) {
+ scrollHeight -=
+ (scrollerHeight - this.lineHeight) * this.$scrollPastEnd;
+ if (this.scrollTop > scrollHeight - scrollerHeight) {
+ scrollHeight = this.scrollTop + scrollerHeight;
+ this.scrollBarV.scrollTop = null;
+ }
+ }
+ this.scrollBarV.setScrollHeight(scrollHeight + this.scrollMargin.v);
+ this.scrollBarV.setScrollTop(this.scrollTop + this.scrollMargin.top);
+ };
+ this.$updateScrollBarH = function() {
+ this.scrollBarH.setScrollWidth(
+ this.layerConfig.width + 2 * this.$padding + this.scrollMargin.h
+ );
+ this.scrollBarH.setScrollLeft(this.scrollLeft + this.scrollMargin.left);
+ };
+
+ this.$frozen = false;
+ this.freeze = function() {
+ this.$frozen = true;
+ };
+
+ this.unfreeze = function() {
+ this.$frozen = false;
+ };
+
+ this.$renderChanges = function(changes, force) {
+ if (this.$changes) {
+ changes |= this.$changes;
+ this.$changes = 0;
+ }
+ if (
+ !this.session ||
+ !this.container.offsetWidth ||
+ this.$frozen ||
+ (!changes && !force)
+ ) {
+ this.$changes |= changes;
+ return;
+ }
+ if (this.$size.$dirty) {
+ this.$changes |= changes;
+ return this.onResize(true);
+ }
+ if (!this.lineHeight) {
+ this.$textLayer.checkForSizeChanges();
+ }
+
+ this._signal("beforeRender", changes);
+
+ if (this.session && this.session.$bidiHandler)
+ this.session.$bidiHandler.updateCharacterWidths(this.$fontMetrics);
+
+ var config = this.layerConfig;
+ if (
+ changes & this.CHANGE_FULL ||
+ changes & this.CHANGE_SIZE ||
+ changes & this.CHANGE_TEXT ||
+ changes & this.CHANGE_LINES ||
+ changes & this.CHANGE_SCROLL ||
+ changes & this.CHANGE_H_SCROLL
+ ) {
+ changes |= this.$computeLayerConfig() | this.$loop.clear();
+ if (
+ config.firstRow != this.layerConfig.firstRow &&
+ config.firstRowScreen == this.layerConfig.firstRowScreen
+ ) {
+ var st =
+ this.scrollTop +
+ (config.firstRow - this.layerConfig.firstRow) * this.lineHeight;
+ if (st > 0) {
+ this.scrollTop = st;
+ changes = changes | this.CHANGE_SCROLL;
+ changes |= this.$computeLayerConfig() | this.$loop.clear();
+ }
+ }
+ config = this.layerConfig;
+ this.$updateScrollBarV();
+ if (changes & this.CHANGE_H_SCROLL) this.$updateScrollBarH();
+
+ dom.translate(this.content, -this.scrollLeft, -config.offset);
+
+ var width = config.width + 2 * this.$padding + "px";
+ var height = config.minHeight + "px";
+
+ dom.setStyle(this.content.style, "width", width);
+ dom.setStyle(this.content.style, "height", height);
+ }
+ if (changes & this.CHANGE_H_SCROLL) {
+ dom.translate(this.content, -this.scrollLeft, -config.offset);
+ this.scroller.className =
+ this.scrollLeft <= 0
+ ? "ace_scroller"
+ : "ace_scroller ace_scroll-left";
+ }
+ if (changes & this.CHANGE_FULL) {
+ this.$changedLines = null;
+ this.$textLayer.update(config);
+ if (this.$showGutter) this.$gutterLayer.update(config);
+ this.$markerBack.update(config);
+ this.$markerFront.update(config);
+ this.$cursorLayer.update(config);
+ this.$moveTextAreaToCursor();
+ this._signal("afterRender", changes);
+ return;
+ }
+ if (changes & this.CHANGE_SCROLL) {
+ this.$changedLines = null;
+ if (changes & this.CHANGE_TEXT || changes & this.CHANGE_LINES)
+ this.$textLayer.update(config);
+ else this.$textLayer.scrollLines(config);
+
+ if (this.$showGutter) {
+ if (changes & this.CHANGE_GUTTER || changes & this.CHANGE_LINES)
+ this.$gutterLayer.update(config);
+ else this.$gutterLayer.scrollLines(config);
+ }
+ this.$markerBack.update(config);
+ this.$markerFront.update(config);
+ this.$cursorLayer.update(config);
+ this.$moveTextAreaToCursor();
+ this._signal("afterRender", changes);
+ return;
+ }
+
+ if (changes & this.CHANGE_TEXT) {
+ this.$changedLines = null;
+ this.$textLayer.update(config);
+ if (this.$showGutter) this.$gutterLayer.update(config);
+ } else if (changes & this.CHANGE_LINES) {
+ if (
+ this.$updateLines() ||
+ (changes & this.CHANGE_GUTTER && this.$showGutter)
+ )
+ this.$gutterLayer.update(config);
+ } else if (changes & this.CHANGE_TEXT || changes & this.CHANGE_GUTTER) {
+ if (this.$showGutter) this.$gutterLayer.update(config);
+ } else if (changes & this.CHANGE_CURSOR) {
+ if (this.$highlightGutterLine)
+ this.$gutterLayer.updateLineHighlight(config);
+ }
+
+ if (changes & this.CHANGE_CURSOR) {
+ this.$cursorLayer.update(config);
+ this.$moveTextAreaToCursor();
+ }
+
+ if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_FRONT)) {
+ this.$markerFront.update(config);
+ }
+
+ if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_BACK)) {
+ this.$markerBack.update(config);
+ }
+
+ this._signal("afterRender", changes);
+ };
+
+ this.$autosize = function() {
+ var height = this.session.getScreenLength() * this.lineHeight;
+ var maxHeight = this.$maxLines * this.lineHeight;
+ var desiredHeight =
+ Math.min(
+ maxHeight,
+ Math.max((this.$minLines || 1) * this.lineHeight, height)
+ ) +
+ this.scrollMargin.v +
+ (this.$extraHeight || 0);
+ if (this.$horizScroll) desiredHeight += this.scrollBarH.getHeight();
+ if (this.$maxPixelHeight && desiredHeight > this.$maxPixelHeight)
+ desiredHeight = this.$maxPixelHeight;
+
+ var hideScrollbars = desiredHeight <= 2 * this.lineHeight;
+ var vScroll = !hideScrollbars && height > maxHeight;
+
+ if (
+ desiredHeight != this.desiredHeight ||
+ this.$size.height != this.desiredHeight ||
+ vScroll != this.$vScroll
+ ) {
+ if (vScroll != this.$vScroll) {
+ this.$vScroll = vScroll;
+ this.scrollBarV.setVisible(vScroll);
+ }
+
+ var w = this.container.clientWidth;
+ this.container.style.height = desiredHeight + "px";
+ this.$updateCachedSize(true, this.$gutterWidth, w, desiredHeight);
+ this.desiredHeight = desiredHeight;
+
+ this._signal("autosize");
+ }
+ };
+
+ this.$computeLayerConfig = function() {
+ var session = this.session;
+ var size = this.$size;
+
+ var hideScrollbars = size.height <= 2 * this.lineHeight;
+ var screenLines = this.session.getScreenLength();
+ var maxHeight = screenLines * this.lineHeight;
+
+ var longestLine = this.$getLongestLine();
+
+ var horizScroll =
+ !hideScrollbars &&
+ (this.$hScrollBarAlwaysVisible ||
+ size.scrollerWidth - longestLine - 2 * this.$padding < 0);
+
+ var hScrollChanged = this.$horizScroll !== horizScroll;
+ if (hScrollChanged) {
+ this.$horizScroll = horizScroll;
+ this.scrollBarH.setVisible(horizScroll);
+ }
+ var vScrollBefore = this.$vScroll; // autosize can change vscroll value in which case we need to update longestLine
+ if (this.$maxLines && this.lineHeight > 1) this.$autosize();
+
+ var minHeight = size.scrollerHeight + this.lineHeight;
+
+ var scrollPastEnd =
+ !this.$maxLines && this.$scrollPastEnd
+ ? (size.scrollerHeight - this.lineHeight) * this.$scrollPastEnd
+ : 0;
+ maxHeight += scrollPastEnd;
+
+ var sm = this.scrollMargin;
+ this.session.setScrollTop(
+ Math.max(
+ -sm.top,
+ Math.min(
+ this.scrollTop,
+ maxHeight - size.scrollerHeight + sm.bottom
+ )
+ )
+ );
+
+ this.session.setScrollLeft(
+ Math.max(
+ -sm.left,
+ Math.min(
+ this.scrollLeft,
+ longestLine + 2 * this.$padding - size.scrollerWidth + sm.right
+ )
+ )
+ );
+
+ var vScroll =
+ !hideScrollbars &&
+ (this.$vScrollBarAlwaysVisible ||
+ size.scrollerHeight - maxHeight + scrollPastEnd < 0 ||
+ this.scrollTop > sm.top);
+ var vScrollChanged = vScrollBefore !== vScroll;
+ if (vScrollChanged) {
+ this.$vScroll = vScroll;
+ this.scrollBarV.setVisible(vScroll);
+ }
+
+ var offset = this.scrollTop % this.lineHeight;
+ var lineCount = Math.ceil(minHeight / this.lineHeight) - 1;
+ var firstRow = Math.max(
+ 0,
+ Math.round((this.scrollTop - offset) / this.lineHeight)
+ );
+ var lastRow = firstRow + lineCount;
+ var firstRowScreen, firstRowHeight;
+ var lineHeight = this.lineHeight;
+ firstRow = session.screenToDocumentRow(firstRow, 0);
+ var foldLine = session.getFoldLine(firstRow);
+ if (foldLine) {
+ firstRow = foldLine.start.row;
+ }
+
+ firstRowScreen = session.documentToScreenRow(firstRow, 0);
+ firstRowHeight = session.getRowLength(firstRow) * lineHeight;
+
+ lastRow = Math.min(
+ session.screenToDocumentRow(lastRow, 0),
+ session.getLength() - 1
+ );
+ minHeight =
+ size.scrollerHeight +
+ session.getRowLength(lastRow) * lineHeight +
+ firstRowHeight;
+
+ offset = this.scrollTop - firstRowScreen * lineHeight;
+
+ var changes = 0;
+ if (this.layerConfig.width != longestLine || hScrollChanged)
+ changes = this.CHANGE_H_SCROLL;
+ if (hScrollChanged || vScrollChanged) {
+ changes |= this.$updateCachedSize(
+ true,
+ this.gutterWidth,
+ size.width,
+ size.height
+ );
+ this._signal("scrollbarVisibilityChanged");
+ if (vScrollChanged) longestLine = this.$getLongestLine();
+ }
+
+ this.layerConfig = {
+ width: longestLine,
+ padding: this.$padding,
+ firstRow: firstRow,
+ firstRowScreen: firstRowScreen,
+ lastRow: lastRow,
+ lineHeight: lineHeight,
+ characterWidth: this.characterWidth,
+ minHeight: minHeight,
+ maxHeight: maxHeight,
+ offset: offset,
+ gutterOffset: lineHeight
+ ? Math.max(
+ 0,
+ Math.ceil(
+ (offset + size.height - size.scrollerHeight) / lineHeight
+ )
+ )
+ : 0,
+ height: this.$size.scrollerHeight
+ };
+
+ if (this.session.$bidiHandler)
+ this.session.$bidiHandler.setContentWidth(
+ longestLine - this.$padding
+ );
+
+ return changes;
+ };
+
+ this.$updateLines = function() {
+ if (!this.$changedLines) return;
+ var firstRow = this.$changedLines.firstRow;
+ var lastRow = this.$changedLines.lastRow;
+ this.$changedLines = null;
+
+ var layerConfig = this.layerConfig;
+
+ if (firstRow > layerConfig.lastRow + 1) {
+ return;
+ }
+ if (lastRow < layerConfig.firstRow) {
+ return;
+ }
+ if (lastRow === Infinity) {
+ if (this.$showGutter) this.$gutterLayer.update(layerConfig);
+ this.$textLayer.update(layerConfig);
+ return;
+ }
+ this.$textLayer.updateLines(layerConfig, firstRow, lastRow);
+ return true;
+ };
+
+ this.$getLongestLine = function() {
+ var charCount = this.session.getScreenWidth();
+ if (this.showInvisibles && !this.session.$useWrapMode) charCount += 1;
+
+ if (this.$textLayer && charCount > this.$textLayer.MAX_LINE_LENGTH)
+ charCount = this.$textLayer.MAX_LINE_LENGTH + 30;
+
+ return Math.max(
+ this.$size.scrollerWidth - 2 * this.$padding,
+ Math.round(charCount * this.characterWidth)
+ );
+ };
+ this.updateFrontMarkers = function() {
+ this.$markerFront.setMarkers(this.session.getMarkers(true));
+ this.$loop.schedule(this.CHANGE_MARKER_FRONT);
+ };
+ this.updateBackMarkers = function() {
+ this.$markerBack.setMarkers(this.session.getMarkers());
+ this.$loop.schedule(this.CHANGE_MARKER_BACK);
+ };
+ this.addGutterDecoration = function(row, className) {
+ this.$gutterLayer.addGutterDecoration(row, className);
+ };
+ this.removeGutterDecoration = function(row, className) {
+ this.$gutterLayer.removeGutterDecoration(row, className);
+ };
+ this.updateBreakpoints = function(rows) {
+ this.$loop.schedule(this.CHANGE_GUTTER);
+ };
+ this.setAnnotations = function(annotations) {
+ this.$gutterLayer.setAnnotations(annotations);
+ this.$loop.schedule(this.CHANGE_GUTTER);
+ };
+ this.updateCursor = function() {
+ this.$loop.schedule(this.CHANGE_CURSOR);
+ };
+ this.hideCursor = function() {
+ this.$cursorLayer.hideCursor();
+ };
+ this.showCursor = function() {
+ this.$cursorLayer.showCursor();
+ };
+
+ this.scrollSelectionIntoView = function(anchor, lead, offset) {
+ this.scrollCursorIntoView(anchor, offset);
+ this.scrollCursorIntoView(lead, offset);
+ };
+ this.scrollCursorIntoView = function(cursor, offset, $viewMargin) {
+ if (this.$size.scrollerHeight === 0) return;
+
+ var pos = this.$cursorLayer.getPixelPosition(cursor);
+
+ var left = pos.left;
+ var top = pos.top;
+
+ var topMargin = ($viewMargin && $viewMargin.top) || 0;
+ var bottomMargin = ($viewMargin && $viewMargin.bottom) || 0;
+
+ var scrollTop = this.$scrollAnimation
+ ? this.session.getScrollTop()
+ : this.scrollTop;
+
+ if (scrollTop + topMargin > top) {
+ if (offset && scrollTop + topMargin > top + this.lineHeight)
+ top -= offset * this.$size.scrollerHeight;
+ if (top === 0) top = -this.scrollMargin.top;
+ this.session.setScrollTop(top);
+ } else if (
+ scrollTop + this.$size.scrollerHeight - bottomMargin <
+ top + this.lineHeight
+ ) {
+ if (
+ offset &&
+ scrollTop + this.$size.scrollerHeight - bottomMargin <
+ top - this.lineHeight
+ )
+ top += offset * this.$size.scrollerHeight;
+ this.session.setScrollTop(
+ top + this.lineHeight + bottomMargin - this.$size.scrollerHeight
+ );
+ }
+
+ var scrollLeft = this.scrollLeft;
+
+ if (scrollLeft > left) {
+ if (left < this.$padding + 2 * this.layerConfig.characterWidth)
+ left = -this.scrollMargin.left;
+ this.session.setScrollLeft(left);
+ } else if (
+ scrollLeft + this.$size.scrollerWidth <
+ left + this.characterWidth
+ ) {
+ this.session.setScrollLeft(
+ Math.round(left + this.characterWidth - this.$size.scrollerWidth)
+ );
+ } else if (
+ scrollLeft <= this.$padding &&
+ left - scrollLeft < this.characterWidth
+ ) {
+ this.session.setScrollLeft(0);
+ }
+ };
+ this.getScrollTop = function() {
+ return this.session.getScrollTop();
+ };
+ this.getScrollLeft = function() {
+ return this.session.getScrollLeft();
+ };
+ this.getScrollTopRow = function() {
+ return this.scrollTop / this.lineHeight;
+ };
+ this.getScrollBottomRow = function() {
+ return Math.max(
+ 0,
+ Math.floor(
+ (this.scrollTop + this.$size.scrollerHeight) / this.lineHeight
+ ) - 1
+ );
+ };
+ this.scrollToRow = function(row) {
+ this.session.setScrollTop(row * this.lineHeight);
+ };
+
+ this.alignCursor = function(cursor, alignment) {
+ if (typeof cursor == "number") cursor = { row: cursor, column: 0 };
+
+ var pos = this.$cursorLayer.getPixelPosition(cursor);
+ var h = this.$size.scrollerHeight - this.lineHeight;
+ var offset = pos.top - h * (alignment || 0);
+
+ this.session.setScrollTop(offset);
+ return offset;
+ };
+
+ this.STEPS = 8;
+ this.$calcSteps = function(fromValue, toValue) {
+ var i = 0;
+ var l = this.STEPS;
+ var steps = [];
+
+ var func = function(t, x_min, dx) {
+ return dx * (Math.pow(t - 1, 3) + 1) + x_min;
+ };
+
+ for (i = 0; i < l; ++i)
+ steps.push(func(i / this.STEPS, fromValue, toValue - fromValue));
+
+ return steps;
+ };
+ this.scrollToLine = function(line, center, animate, callback) {
+ var pos = this.$cursorLayer.getPixelPosition({ row: line, column: 0 });
+ var offset = pos.top;
+ if (center) offset -= this.$size.scrollerHeight / 2;
+
+ var initialScroll = this.scrollTop;
+ this.session.setScrollTop(offset);
+ if (animate !== false) this.animateScrolling(initialScroll, callback);
+ };
+
+ this.animateScrolling = function(fromValue, callback) {
+ var toValue = this.scrollTop;
+ if (!this.$animatedScroll) return;
+ var _self = this;
+
+ if (fromValue == toValue) return;
+
+ if (this.$scrollAnimation) {
+ var oldSteps = this.$scrollAnimation.steps;
+ if (oldSteps.length) {
+ fromValue = oldSteps[0];
+ if (fromValue == toValue) return;
+ }
+ }
+
+ var steps = _self.$calcSteps(fromValue, toValue);
+ this.$scrollAnimation = { from: fromValue, to: toValue, steps: steps };
+
+ clearInterval(this.$timer);
+
+ _self.session.setScrollTop(steps.shift());
+ _self.session.$scrollTop = toValue;
+ this.$timer = setInterval(function() {
+ if (!_self.session) return clearInterval(_self.$timer);
+ if (steps.length) {
+ _self.session.setScrollTop(steps.shift());
+ _self.session.$scrollTop = toValue;
+ } else if (toValue != null) {
+ _self.session.$scrollTop = -1;
+ _self.session.setScrollTop(toValue);
+ toValue = null;
+ } else {
+ _self.$timer = clearInterval(_self.$timer);
+ _self.$scrollAnimation = null;
+ callback && callback();
+ }
+ }, 10);
+ };
+ this.scrollToY = function(scrollTop) {
+ if (this.scrollTop !== scrollTop) {
+ this.$loop.schedule(this.CHANGE_SCROLL);
+ this.scrollTop = scrollTop;
+ }
+ };
+ this.scrollToX = function(scrollLeft) {
+ if (this.scrollLeft !== scrollLeft) this.scrollLeft = scrollLeft;
+ this.$loop.schedule(this.CHANGE_H_SCROLL);
+ };
+ this.scrollTo = function(x, y) {
+ this.session.setScrollTop(y);
+ this.session.setScrollLeft(y);
+ };
+ this.scrollBy = function(deltaX, deltaY) {
+ deltaY &&
+ this.session.setScrollTop(this.session.getScrollTop() + deltaY);
+ deltaX &&
+ this.session.setScrollLeft(this.session.getScrollLeft() + deltaX);
+ };
+ this.isScrollableBy = function(deltaX, deltaY) {
+ if (
+ deltaY < 0 &&
+ this.session.getScrollTop() >= 1 - this.scrollMargin.top
+ )
+ return true;
+ if (
+ deltaY > 0 &&
+ this.session.getScrollTop() +
+ this.$size.scrollerHeight -
+ this.layerConfig.maxHeight <
+ -1 + this.scrollMargin.bottom
+ )
+ return true;
+ if (
+ deltaX < 0 &&
+ this.session.getScrollLeft() >= 1 - this.scrollMargin.left
+ )
+ return true;
+ if (
+ deltaX > 0 &&
+ this.session.getScrollLeft() +
+ this.$size.scrollerWidth -
+ this.layerConfig.width <
+ -1 + this.scrollMargin.right
+ )
+ return true;
+ };
+
+ this.pixelToScreenCoordinates = function(x, y) {
+ var canvasPos;
+ if (this.$hasCssTransforms) {
+ canvasPos = { top: 0, left: 0 };
+ var p = this.$fontMetrics.transformCoordinates([x, y]);
+ x = p[1] - this.gutterWidth - this.margin.left;
+ y = p[0];
+ } else {
+ canvasPos = this.scroller.getBoundingClientRect();
+ }
+
+ var offsetX = x + this.scrollLeft - canvasPos.left - this.$padding;
+ var offset = offsetX / this.characterWidth;
+ var row = Math.floor(
+ (y + this.scrollTop - canvasPos.top) / this.lineHeight
+ );
+ var col = this.$blockCursor ? Math.floor(offset) : Math.round(offset);
+
+ return {
+ row: row,
+ column: col,
+ side: offset - col > 0 ? 1 : -1,
+ offsetX: offsetX
+ };
+ };
+
+ this.screenToTextCoordinates = function(x, y) {
+ var canvasPos;
+ if (this.$hasCssTransforms) {
+ canvasPos = { top: 0, left: 0 };
+ var p = this.$fontMetrics.transformCoordinates([x, y]);
+ x = p[1] - this.gutterWidth - this.margin.left;
+ y = p[0];
+ } else {
+ canvasPos = this.scroller.getBoundingClientRect();
+ }
+
+ var offsetX = x + this.scrollLeft - canvasPos.left - this.$padding;
+ var offset = offsetX / this.characterWidth;
+ var col = this.$blockCursor ? Math.floor(offset) : Math.round(offset);
+
+ var row = Math.floor(
+ (y + this.scrollTop - canvasPos.top) / this.lineHeight
+ );
+
+ return this.session.screenToDocumentPosition(
+ row,
+ Math.max(col, 0),
+ offsetX
+ );
+ };
+ this.textToScreenCoordinates = function(row, column) {
+ var canvasPos = this.scroller.getBoundingClientRect();
+ var pos = this.session.documentToScreenPosition(row, column);
+
+ var x =
+ this.$padding +
+ (this.session.$bidiHandler.isBidiRow(pos.row, row)
+ ? this.session.$bidiHandler.getPosLeft(pos.column)
+ : Math.round(pos.column * this.characterWidth));
+
+ var y = pos.row * this.lineHeight;
+
+ return {
+ pageX: canvasPos.left + x - this.scrollLeft,
+ pageY: canvasPos.top + y - this.scrollTop
+ };
+ };
+ this.visualizeFocus = function() {
+ dom.addCssClass(this.container, "ace_focus");
+ };
+ this.visualizeBlur = function() {
+ dom.removeCssClass(this.container, "ace_focus");
+ };
+ this.showComposition = function(composition) {
+ this.$composition = composition;
+ if (!composition.cssText) {
+ composition.cssText = this.textarea.style.cssText;
+ }
+ if (composition.useTextareaForIME == undefined)
+ composition.useTextareaForIME = this.$useTextareaForIME;
+
+ if (this.$useTextareaForIME) {
+ dom.addCssClass(this.textarea, "ace_composition");
+ this.textarea.style.cssText = "";
+ this.$moveTextAreaToCursor();
+ this.$cursorLayer.element.style.display = "none";
+ } else {
+ composition.markerId = this.session.addMarker(
+ composition.markerRange,
+ "ace_composition_marker",
+ "text"
+ );
+ }
+ };
+ this.setCompositionText = function(text) {
+ var cursor = this.session.selection.cursor;
+ this.addToken(
+ text,
+ "composition_placeholder",
+ cursor.row,
+ cursor.column
+ );
+ this.$moveTextAreaToCursor();
+ };
+ this.hideComposition = function() {
+ if (!this.$composition) return;
+
+ if (this.$composition.markerId)
+ this.session.removeMarker(this.$composition.markerId);
+
+ dom.removeCssClass(this.textarea, "ace_composition");
+ this.textarea.style.cssText = this.$composition.cssText;
+ var cursor = this.session.selection.cursor;
+ this.removeExtraToken(cursor.row, cursor.column);
+ this.$composition = null;
+ this.$cursorLayer.element.style.display = "";
+ };
+
+ this.addToken = function(text, type, row, column) {
+ var session = this.session;
+ session.bgTokenizer.lines[row] = null;
+ var newToken = { type: type, value: text };
+ var tokens = session.getTokens(row);
+ if (column == null) {
+ tokens.push(newToken);
+ } else {
+ var l = 0;
+ for (var i = 0; i < tokens.length; i++) {
+ var token = tokens[i];
+ l += token.value.length;
+ if (column <= l) {
+ var diff = token.value.length - (l - column);
+ var before = token.value.slice(0, diff);
+ var after = token.value.slice(diff);
+
+ tokens.splice(
+ i,
+ 1,
+ { type: token.type, value: before },
+ newToken,
+ { type: token.type, value: after }
+ );
+ break;
+ }
+ }
+ }
+ this.updateLines(row, row);
+ };
+
+ this.removeExtraToken = function(row, column) {
+ this.updateLines(row, row);
+ };
+ this.setTheme = function(theme, cb) {
+ var _self = this;
+ this.$themeId = theme;
+ _self._dispatchEvent("themeChange", { theme: theme });
+
+ if (!theme || typeof theme == "string") {
+ var moduleName = theme || this.$options.theme.initialValue;
+ config.loadModule(["theme", moduleName], afterLoad);
+ } else {
+ afterLoad(theme);
+ }
+
+ function afterLoad(module) {
+ if (_self.$themeId != theme) return cb && cb();
+ if (!module || !module.cssClass)
+ throw new Error(
+ "couldn't load module " + theme + " or it didn't call define"
+ );
+ if (module.$id) _self.$themeId = module.$id;
+ dom.importCssString(module.cssText, module.cssClass, _self.container);
+
+ if (_self.theme)
+ dom.removeCssClass(_self.container, _self.theme.cssClass);
+
+ var padding =
+ "padding" in module
+ ? module.padding
+ : "padding" in (_self.theme || {})
+ ? 4
+ : _self.$padding;
+ if (_self.$padding && padding != _self.$padding)
+ _self.setPadding(padding);
+ _self.$theme = module.cssClass;
+
+ _self.theme = module;
+ dom.addCssClass(_self.container, module.cssClass);
+ dom.setCssClass(_self.container, "ace_dark", module.isDark);
+ if (_self.$size) {
+ _self.$size.width = 0;
+ _self.$updateSizeAsync();
+ }
+
+ _self._dispatchEvent("themeLoaded", { theme: module });
+ cb && cb();
+ }
+ };
+ this.getTheme = function() {
+ return this.$themeId;
+ };
+ this.setStyle = function(style, include) {
+ dom.setCssClass(this.container, style, include !== false);
+ };
+ this.unsetStyle = function(style) {
+ dom.removeCssClass(this.container, style);
+ };
+
+ this.setCursorStyle = function(style) {
+ dom.setStyle(this.scroller.style, "cursor", style);
+ };
+ this.setMouseCursor = function(cursorStyle) {
+ dom.setStyle(this.scroller.style, "cursor", cursorStyle);
+ };
+
+ this.attachToShadowRoot = function() {
+ dom.importCssString(editorCss, "ace_editor.css", this.container);
+ };
+ this.destroy = function() {
+ this.freeze();
+ this.$fontMetrics.destroy();
+ this.$cursorLayer.destroy();
+ this.removeAllListeners();
+ this.container.textContent = "";
+ };
+ }.call(VirtualRenderer.prototype));
+
+ config.defineOptions(VirtualRenderer.prototype, "renderer", {
+ animatedScroll: { initialValue: false },
+ showInvisibles: {
+ set: function(value) {
+ if (this.$textLayer.setShowInvisibles(value))
+ this.$loop.schedule(this.CHANGE_TEXT);
+ },
+ initialValue: false
+ },
+ showPrintMargin: {
+ set: function() {
+ this.$updatePrintMargin();
+ },
+ initialValue: true
+ },
+ printMarginColumn: {
+ set: function() {
+ this.$updatePrintMargin();
+ },
+ initialValue: 80
+ },
+ printMargin: {
+ set: function(val) {
+ if (typeof val == "number") this.$printMarginColumn = val;
+ this.$showPrintMargin = !!val;
+ this.$updatePrintMargin();
+ },
+ get: function() {
+ return this.$showPrintMargin && this.$printMarginColumn;
+ }
+ },
+ showGutter: {
+ set: function(show) {
+ this.$gutter.style.display = show ? "block" : "none";
+ this.$loop.schedule(this.CHANGE_FULL);
+ this.onGutterResize();
+ },
+ initialValue: true
+ },
+ fadeFoldWidgets: {
+ set: function(show) {
+ dom.setCssClass(this.$gutter, "ace_fade-fold-widgets", show);
+ },
+ initialValue: false
+ },
+ showFoldWidgets: {
+ set: function(show) {
+ this.$gutterLayer.setShowFoldWidgets(show);
+ this.$loop.schedule(this.CHANGE_GUTTER);
+ },
+ initialValue: true
+ },
+ displayIndentGuides: {
+ set: function(show) {
+ if (this.$textLayer.setDisplayIndentGuides(show))
+ this.$loop.schedule(this.CHANGE_TEXT);
+ },
+ initialValue: true
+ },
+ highlightGutterLine: {
+ set: function(shouldHighlight) {
+ this.$gutterLayer.setHighlightGutterLine(shouldHighlight);
+ this.$loop.schedule(this.CHANGE_GUTTER);
+ },
+ initialValue: true
+ },
+ hScrollBarAlwaysVisible: {
+ set: function(val) {
+ if (!this.$hScrollBarAlwaysVisible || !this.$horizScroll)
+ this.$loop.schedule(this.CHANGE_SCROLL);
+ },
+ initialValue: false
+ },
+ vScrollBarAlwaysVisible: {
+ set: function(val) {
+ if (!this.$vScrollBarAlwaysVisible || !this.$vScroll)
+ this.$loop.schedule(this.CHANGE_SCROLL);
+ },
+ initialValue: false
+ },
+ fontSize: {
+ set: function(size) {
+ if (typeof size == "number") size = size + "px";
+ this.container.style.fontSize = size;
+ this.updateFontSize();
+ },
+ initialValue: 12
+ },
+ fontFamily: {
+ set: function(name) {
+ this.container.style.fontFamily = name;
+ this.updateFontSize();
+ }
+ },
+ maxLines: {
+ set: function(val) {
+ this.updateFull();
+ }
+ },
+ minLines: {
+ set: function(val) {
+ if (!(this.$minLines < 0x1ffffffffffff)) this.$minLines = 0;
+ this.updateFull();
+ }
+ },
+ maxPixelHeight: {
+ set: function(val) {
+ this.updateFull();
+ },
+ initialValue: 0
+ },
+ scrollPastEnd: {
+ set: function(val) {
+ val = +val || 0;
+ if (this.$scrollPastEnd == val) return;
+ this.$scrollPastEnd = val;
+ this.$loop.schedule(this.CHANGE_SCROLL);
+ },
+ initialValue: 0,
+ handlesSet: true
+ },
+ fixedWidthGutter: {
+ set: function(val) {
+ this.$gutterLayer.$fixedWidth = !!val;
+ this.$loop.schedule(this.CHANGE_GUTTER);
+ }
+ },
+ theme: {
+ set: function(val) {
+ this.setTheme(val);
+ },
+ get: function() {
+ return this.$themeId || this.theme;
+ },
+ initialValue: "./theme/textmate",
+ handlesSet: true
+ },
+ hasCssTransforms: {},
+ useTextareaForIME: {
+ initialValue: !useragent.isMobile && !useragent.isIE
+ }
+ });
+
+ exports.VirtualRenderer = VirtualRenderer;
+ }
+);
+
+ace.define(
+ "ace/worker/worker_client",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/lib/oop",
+ "ace/lib/net",
+ "ace/lib/event_emitter",
+ "ace/config"
+ ],
+ function(require, exports, module) {
+ "use strict";
+
+ var oop = require("../lib/oop");
+ var net = require("../lib/net");
+ var EventEmitter = require("../lib/event_emitter").EventEmitter;
+ var config = require("../config");
+
+ function $workerBlob(workerUrl) {
+ var script = "importScripts('" + net.qualifyURL(workerUrl) + "');";
+ try {
+ return new Blob([script], { type: "application/javascript" });
+ } catch (e) {
+ // Backwards-compatibility
+ var BlobBuilder =
+ window.BlobBuilder ||
+ window.WebKitBlobBuilder ||
+ window.MozBlobBuilder;
+ var blobBuilder = new BlobBuilder();
+ blobBuilder.append(script);
+ return blobBuilder.getBlob("application/javascript");
+ }
+ }
+
+ function createWorker(workerUrl) {
+ if (typeof Worker == "undefined")
+ return { postMessage: function() {}, terminate: function() {} };
+ if (config.get("loadWorkerFromBlob")) {
+ var blob = $workerBlob(workerUrl);
+ var URL = window.URL || window.webkitURL;
+ var blobURL = URL.createObjectURL(blob);
+ return new Worker(blobURL);
+ }
+ return new Worker(workerUrl);
+ }
+
+ var WorkerClient = function(worker) {
+ if (!worker.postMessage)
+ worker = this.$createWorkerFromOldConfig.apply(this, arguments);
+
+ this.$worker = worker;
+ this.$sendDeltaQueue = this.$sendDeltaQueue.bind(this);
+ this.changeListener = this.changeListener.bind(this);
+ this.onMessage = this.onMessage.bind(this);
+
+ this.callbackId = 1;
+ this.callbacks = {};
+
+ this.$worker.onmessage = this.onMessage;
+ };
+
+ (function() {
+ oop.implement(this, EventEmitter);
+
+ this.$createWorkerFromOldConfig = function(
+ topLevelNamespaces,
+ mod,
+ classname,
+ workerUrl,
+ importScripts
+ ) {
+ if (require.nameToUrl && !require.toUrl)
+ require.toUrl = require.nameToUrl;
+
+ if (config.get("packaged") || !require.toUrl) {
+ workerUrl = workerUrl || config.moduleUrl(mod, "worker");
+ } else {
+ var normalizePath = this.$normalizePath;
+ workerUrl =
+ workerUrl ||
+ normalizePath(require.toUrl("ace/worker/worker.js", null, "_"));
+
+ var tlns = {};
+ topLevelNamespaces.forEach(function(ns) {
+ tlns[ns] = normalizePath(
+ require.toUrl(ns, null, "_").replace(/(\.js)?(\?.*)?$/, "")
+ );
+ });
+ }
+
+ this.$worker = createWorker(workerUrl);
+ if (importScripts) {
+ this.send("importScripts", importScripts);
+ }
+ this.$worker.postMessage({
+ init: true,
+ tlns: tlns,
+ module: mod,
+ classname: classname
+ });
+ return this.$worker;
+ };
+
+ this.onMessage = function(e) {
+ var msg = e.data;
+ switch (msg.type) {
+ case "event":
+ this._signal(msg.name, { data: msg.data });
+ break;
+ case "call":
+ var callback = this.callbacks[msg.id];
+ if (callback) {
+ callback(msg.data);
+ delete this.callbacks[msg.id];
+ }
+ break;
+ case "error":
+ this.reportError(msg.data);
+ break;
+ case "log":
+ window.console &&
+ console.log &&
+ console.log.apply(console, msg.data);
+ break;
+ }
+ };
+
+ this.reportError = function(err) {
+ window.console && console.error && console.error(err);
+ };
+
+ this.$normalizePath = function(path) {
+ return net.qualifyURL(path);
+ };
+
+ this.terminate = function() {
+ this._signal("terminate", {});
+ this.deltaQueue = null;
+ this.$worker.terminate();
+ this.$worker = null;
+ if (this.$doc) this.$doc.off("change", this.changeListener);
+ this.$doc = null;
+ };
+
+ this.send = function(cmd, args) {
+ this.$worker.postMessage({ command: cmd, args: args });
+ };
+
+ this.call = function(cmd, args, callback) {
+ if (callback) {
+ var id = this.callbackId++;
+ this.callbacks[id] = callback;
+ args.push(id);
+ }
+ this.send(cmd, args);
+ };
+
+ this.emit = function(event, data) {
+ try {
+ if (data.data && data.data.err)
+ data.data.err = {
+ message: data.data.err.message,
+ stack: data.data.err.stack,
+ code: data.data.err.code
+ };
+ this.$worker.postMessage({ event: event, data: { data: data.data } });
+ } catch (ex) {
+ console.error(ex.stack);
+ }
+ };
+
+ this.attachToDocument = function(doc) {
+ if (this.$doc) this.terminate();
+
+ this.$doc = doc;
+ this.call("setValue", [doc.getValue()]);
+ doc.on("change", this.changeListener);
+ };
+
+ this.changeListener = function(delta) {
+ if (!this.deltaQueue) {
+ this.deltaQueue = [];
+ setTimeout(this.$sendDeltaQueue, 0);
+ }
+ if (delta.action == "insert")
+ this.deltaQueue.push(delta.start, delta.lines);
+ else this.deltaQueue.push(delta.start, delta.end);
+ };
+
+ this.$sendDeltaQueue = function() {
+ var q = this.deltaQueue;
+ if (!q) return;
+ this.deltaQueue = null;
+ if (q.length > 50 && q.length > this.$doc.getLength() >> 1) {
+ this.call("setValue", [this.$doc.getValue()]);
+ } else this.emit("change", { data: q });
+ };
+ }.call(WorkerClient.prototype));
+
+ var UIWorkerClient = function(topLevelNamespaces, mod, classname) {
+ var main = null;
+ var emitSync = false;
+ var sender = Object.create(EventEmitter);
+
+ var messageBuffer = [];
+ var workerClient = new WorkerClient({
+ messageBuffer: messageBuffer,
+ terminate: function() {},
+ postMessage: function(e) {
+ messageBuffer.push(e);
+ if (!main) return;
+ if (emitSync) setTimeout(processNext);
+ else processNext();
+ }
+ });
+
+ workerClient.setEmitSync = function(val) {
+ emitSync = val;
+ };
+
+ var processNext = function() {
+ var msg = messageBuffer.shift();
+ if (msg.command) main[msg.command].apply(main, msg.args);
+ else if (msg.event) sender._signal(msg.event, msg.data);
+ };
+
+ sender.postMessage = function(msg) {
+ workerClient.onMessage({ data: msg });
+ };
+ sender.callback = function(data, callbackId) {
+ this.postMessage({ type: "call", id: callbackId, data: data });
+ };
+ sender.emit = function(name, data) {
+ this.postMessage({ type: "event", name: name, data: data });
+ };
+
+ config.loadModule(["worker", mod], function(Main) {
+ main = new Main[classname](sender);
+ while (messageBuffer.length) processNext();
+ });
+
+ return workerClient;
+ };
+
+ exports.UIWorkerClient = UIWorkerClient;
+ exports.WorkerClient = WorkerClient;
+ exports.createWorker = createWorker;
+ }
+);
+
+ace.define(
+ "ace/placeholder",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/range",
+ "ace/lib/event_emitter",
+ "ace/lib/oop"
+ ],
+ function(require, exports, module) {
+ "use strict";
+
+ var Range = require("./range").Range;
+ var EventEmitter = require("./lib/event_emitter").EventEmitter;
+ var oop = require("./lib/oop");
+
+ var PlaceHolder = function(
+ session,
+ length,
+ pos,
+ others,
+ mainClass,
+ othersClass
+ ) {
+ var _self = this;
+ this.length = length;
+ this.session = session;
+ this.doc = session.getDocument();
+ this.mainClass = mainClass;
+ this.othersClass = othersClass;
+ this.$onUpdate = this.onUpdate.bind(this);
+ this.doc.on("change", this.$onUpdate);
+ this.$others = others;
+
+ this.$onCursorChange = function() {
+ setTimeout(function() {
+ _self.onCursorChange();
+ });
+ };
+
+ this.$pos = pos;
+ var undoStack = session.getUndoManager().$undoStack ||
+ session.getUndoManager().$undostack || { length: -1 };
+ this.$undoStackDepth = undoStack.length;
+ this.setup();
+
+ session.selection.on("changeCursor", this.$onCursorChange);
+ };
+
+ (function() {
+ oop.implement(this, EventEmitter);
+ this.setup = function() {
+ var _self = this;
+ var doc = this.doc;
+ var session = this.session;
+
+ this.selectionBefore = session.selection.toJSON();
+ if (session.selection.inMultiSelectMode)
+ session.selection.toSingleRange();
+
+ this.pos = doc.createAnchor(this.$pos.row, this.$pos.column);
+ var pos = this.pos;
+ pos.$insertRight = true;
+ pos.detach();
+ pos.markerId = session.addMarker(
+ new Range(pos.row, pos.column, pos.row, pos.column + this.length),
+ this.mainClass,
+ null,
+ false
+ );
+ this.others = [];
+ this.$others.forEach(function(other) {
+ var anchor = doc.createAnchor(other.row, other.column);
+ anchor.$insertRight = true;
+ anchor.detach();
+ _self.others.push(anchor);
+ });
+ session.setUndoSelect(false);
+ };
+ this.showOtherMarkers = function() {
+ if (this.othersActive) return;
+ var session = this.session;
+ var _self = this;
+ this.othersActive = true;
+ this.others.forEach(function(anchor) {
+ anchor.markerId = session.addMarker(
+ new Range(
+ anchor.row,
+ anchor.column,
+ anchor.row,
+ anchor.column + _self.length
+ ),
+ _self.othersClass,
+ null,
+ false
+ );
+ });
+ };
+ this.hideOtherMarkers = function() {
+ if (!this.othersActive) return;
+ this.othersActive = false;
+ for (var i = 0; i < this.others.length; i++) {
+ this.session.removeMarker(this.others[i].markerId);
+ }
+ };
+ this.onUpdate = function(delta) {
+ if (this.$updating) return this.updateAnchors(delta);
+
+ var range = delta;
+ if (range.start.row !== range.end.row) return;
+ if (range.start.row !== this.pos.row) return;
+ this.$updating = true;
+ var lengthDiff =
+ delta.action === "insert"
+ ? range.end.column - range.start.column
+ : range.start.column - range.end.column;
+ var inMainRange =
+ range.start.column >= this.pos.column &&
+ range.start.column <= this.pos.column + this.length + 1;
+ var distanceFromStart = range.start.column - this.pos.column;
+
+ this.updateAnchors(delta);
+
+ if (inMainRange) this.length += lengthDiff;
+
+ if (inMainRange && !this.session.$fromUndo) {
+ if (delta.action === "insert") {
+ for (var i = this.others.length - 1; i >= 0; i--) {
+ var otherPos = this.others[i];
+ var newPos = {
+ row: otherPos.row,
+ column: otherPos.column + distanceFromStart
+ };
+ this.doc.insertMergedLines(newPos, delta.lines);
+ }
+ } else if (delta.action === "remove") {
+ for (var i = this.others.length - 1; i >= 0; i--) {
+ var otherPos = this.others[i];
+ var newPos = {
+ row: otherPos.row,
+ column: otherPos.column + distanceFromStart
+ };
+ this.doc.remove(
+ new Range(
+ newPos.row,
+ newPos.column,
+ newPos.row,
+ newPos.column - lengthDiff
+ )
+ );
+ }
+ }
+ }
+
+ this.$updating = false;
+ this.updateMarkers();
+ };
+
+ this.updateAnchors = function(delta) {
+ this.pos.onChange(delta);
+ for (var i = this.others.length; i--; ) this.others[i].onChange(delta);
+ this.updateMarkers();
+ };
+
+ this.updateMarkers = function() {
+ if (this.$updating) return;
+ var _self = this;
+ var session = this.session;
+ var updateMarker = function(pos, className) {
+ session.removeMarker(pos.markerId);
+ pos.markerId = session.addMarker(
+ new Range(pos.row, pos.column, pos.row, pos.column + _self.length),
+ className,
+ null,
+ false
+ );
+ };
+ updateMarker(this.pos, this.mainClass);
+ for (var i = this.others.length; i--; )
+ updateMarker(this.others[i], this.othersClass);
+ };
+
+ this.onCursorChange = function(event) {
+ if (this.$updating || !this.session) return;
+ var pos = this.session.selection.getCursor();
+ if (
+ pos.row === this.pos.row &&
+ pos.column >= this.pos.column &&
+ pos.column <= this.pos.column + this.length
+ ) {
+ this.showOtherMarkers();
+ this._emit("cursorEnter", event);
+ } else {
+ this.hideOtherMarkers();
+ this._emit("cursorLeave", event);
+ }
+ };
+ this.detach = function() {
+ this.session.removeMarker(this.pos && this.pos.markerId);
+ this.hideOtherMarkers();
+ this.doc.off("change", this.$onUpdate);
+ this.session.selection.off("changeCursor", this.$onCursorChange);
+ this.session.setUndoSelect(true);
+ this.session = null;
+ };
+ this.cancel = function() {
+ if (this.$undoStackDepth === -1) return;
+ var undoManager = this.session.getUndoManager();
+ var undosRequired =
+ (undoManager.$undoStack || undoManager.$undostack).length -
+ this.$undoStackDepth;
+ for (var i = 0; i < undosRequired; i++) {
+ undoManager.undo(this.session, true);
+ }
+ if (this.selectionBefore)
+ this.session.selection.fromJSON(this.selectionBefore);
+ };
+ }.call(PlaceHolder.prototype));
+
+ exports.PlaceHolder = PlaceHolder;
+ }
+);
+
+ace.define(
+ "ace/mouse/multi_select_handler",
+ ["require", "exports", "module", "ace/lib/event", "ace/lib/useragent"],
+ function(require, exports, module) {
+ var event = require("../lib/event");
+ var useragent = require("../lib/useragent");
+ function isSamePoint(p1, p2) {
+ return p1.row == p2.row && p1.column == p2.column;
+ }
+
+ function onMouseDown(e) {
+ var ev = e.domEvent;
+ var alt = ev.altKey;
+ var shift = ev.shiftKey;
+ var ctrl = ev.ctrlKey;
+ var accel = e.getAccelKey();
+ var button = e.getButton();
+
+ if (ctrl && useragent.isMac) button = ev.button;
+
+ if (e.editor.inMultiSelectMode && button == 2) {
+ e.editor.textInput.onContextMenu(e.domEvent);
+ return;
+ }
+
+ if (!ctrl && !alt && !accel) {
+ if (button === 0 && e.editor.inMultiSelectMode)
+ e.editor.exitMultiSelectMode();
+ return;
+ }
+
+ if (button !== 0) return;
+
+ var editor = e.editor;
+ var selection = editor.selection;
+ var isMultiSelect = editor.inMultiSelectMode;
+ var pos = e.getDocumentPosition();
+ var cursor = selection.getCursor();
+ var inSelection =
+ e.inSelection() || (selection.isEmpty() && isSamePoint(pos, cursor));
+
+ var mouseX = e.x,
+ mouseY = e.y;
+ var onMouseSelection = function(e) {
+ mouseX = e.clientX;
+ mouseY = e.clientY;
+ };
+
+ var session = editor.session;
+ var screenAnchor = editor.renderer.pixelToScreenCoordinates(
+ mouseX,
+ mouseY
+ );
+ var screenCursor = screenAnchor;
+
+ var selectionMode;
+ if (editor.$mouseHandler.$enableJumpToDef) {
+ if ((ctrl && alt) || (accel && alt))
+ selectionMode = shift ? "block" : "add";
+ else if (alt && editor.$blockSelectEnabled) selectionMode = "block";
+ } else {
+ if (accel && !alt) {
+ selectionMode = "add";
+ if (!isMultiSelect && shift) return;
+ } else if (alt && editor.$blockSelectEnabled) {
+ selectionMode = "block";
+ }
+ }
+
+ if (selectionMode && useragent.isMac && ev.ctrlKey) {
+ editor.$mouseHandler.cancelContextMenu();
+ }
+
+ if (selectionMode == "add") {
+ if (!isMultiSelect && inSelection) return; // dragging
+
+ if (!isMultiSelect) {
+ var range = selection.toOrientedRange();
+ editor.addSelectionMarker(range);
+ }
+
+ var oldRange = selection.rangeList.rangeAtPoint(pos);
+
+ editor.inVirtualSelectionMode = true;
+
+ if (shift) {
+ oldRange = null;
+ range = selection.ranges[0] || range;
+ editor.removeSelectionMarker(range);
+ }
+ editor.once("mouseup", function() {
+ var tmpSel = selection.toOrientedRange();
+
+ if (
+ oldRange &&
+ tmpSel.isEmpty() &&
+ isSamePoint(oldRange.cursor, tmpSel.cursor)
+ )
+ selection.substractPoint(tmpSel.cursor);
+ else {
+ if (shift) {
+ selection.substractPoint(range.cursor);
+ } else if (range) {
+ editor.removeSelectionMarker(range);
+ selection.addRange(range);
+ }
+ selection.addRange(tmpSel);
+ }
+ editor.inVirtualSelectionMode = false;
+ });
+ } else if (selectionMode == "block") {
+ e.stop();
+ editor.inVirtualSelectionMode = true;
+ var initialRange;
+ var rectSel = [];
+ var blockSelect = function() {
+ var newCursor = editor.renderer.pixelToScreenCoordinates(
+ mouseX,
+ mouseY
+ );
+ var cursor = session.screenToDocumentPosition(
+ newCursor.row,
+ newCursor.column,
+ newCursor.offsetX
+ );
+
+ if (
+ isSamePoint(screenCursor, newCursor) &&
+ isSamePoint(cursor, selection.lead)
+ )
+ return;
+ screenCursor = newCursor;
+
+ editor.selection.moveToPosition(cursor);
+ editor.renderer.scrollCursorIntoView();
+
+ editor.removeSelectionMarkers(rectSel);
+ rectSel = selection.rectangularRangeBlock(screenCursor, screenAnchor);
+ if (
+ editor.$mouseHandler.$clickSelection &&
+ rectSel.length == 1 &&
+ rectSel[0].isEmpty()
+ )
+ rectSel[0] = editor.$mouseHandler.$clickSelection.clone();
+ rectSel.forEach(editor.addSelectionMarker, editor);
+ editor.updateSelectionMarkers();
+ };
+ if (isMultiSelect && !accel) {
+ selection.toSingleRange();
+ } else if (!isMultiSelect && accel) {
+ initialRange = selection.toOrientedRange();
+ editor.addSelectionMarker(initialRange);
+ }
+
+ if (shift)
+ screenAnchor = session.documentToScreenPosition(selection.lead);
+ else selection.moveToPosition(pos);
+
+ screenCursor = { row: -1, column: -1 };
+
+ var onMouseSelectionEnd = function(e) {
+ blockSelect();
+ clearInterval(timerId);
+ editor.removeSelectionMarkers(rectSel);
+ if (!rectSel.length) rectSel = [selection.toOrientedRange()];
+ if (initialRange) {
+ editor.removeSelectionMarker(initialRange);
+ selection.toSingleRange(initialRange);
+ }
+ for (var i = 0; i < rectSel.length; i++)
+ selection.addRange(rectSel[i]);
+ editor.inVirtualSelectionMode = false;
+ editor.$mouseHandler.$clickSelection = null;
+ };
+
+ var onSelectionInterval = blockSelect;
+
+ event.capture(editor.container, onMouseSelection, onMouseSelectionEnd);
+ var timerId = setInterval(function() {
+ onSelectionInterval();
+ }, 20);
+
+ return e.preventDefault();
+ }
+ }
+
+ exports.onMouseDown = onMouseDown;
+ }
+);
+
+ace.define(
+ "ace/commands/multi_select_commands",
+ ["require", "exports", "module", "ace/keyboard/hash_handler"],
+ function(require, exports, module) {
+ exports.defaultCommands = [
+ {
+ name: "addCursorAbove",
+ description: "Add cursor above",
+ exec: function(editor) {
+ editor.selectMoreLines(-1);
+ },
+ bindKey: { win: "Ctrl-Alt-Up", mac: "Ctrl-Alt-Up" },
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "addCursorBelow",
+ description: "Add cursor below",
+ exec: function(editor) {
+ editor.selectMoreLines(1);
+ },
+ bindKey: { win: "Ctrl-Alt-Down", mac: "Ctrl-Alt-Down" },
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "addCursorAboveSkipCurrent",
+ description: "Add cursor above (skip current)",
+ exec: function(editor) {
+ editor.selectMoreLines(-1, true);
+ },
+ bindKey: { win: "Ctrl-Alt-Shift-Up", mac: "Ctrl-Alt-Shift-Up" },
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "addCursorBelowSkipCurrent",
+ description: "Add cursor below (skip current)",
+ exec: function(editor) {
+ editor.selectMoreLines(1, true);
+ },
+ bindKey: { win: "Ctrl-Alt-Shift-Down", mac: "Ctrl-Alt-Shift-Down" },
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "selectMoreBefore",
+ description: "Select more before",
+ exec: function(editor) {
+ editor.selectMore(-1);
+ },
+ bindKey: { win: "Ctrl-Alt-Left", mac: "Ctrl-Alt-Left" },
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "selectMoreAfter",
+ description: "Select more after",
+ exec: function(editor) {
+ editor.selectMore(1);
+ },
+ bindKey: { win: "Ctrl-Alt-Right", mac: "Ctrl-Alt-Right" },
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "selectNextBefore",
+ description: "Select next before",
+ exec: function(editor) {
+ editor.selectMore(-1, true);
+ },
+ bindKey: { win: "Ctrl-Alt-Shift-Left", mac: "Ctrl-Alt-Shift-Left" },
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "selectNextAfter",
+ description: "Select next after",
+ exec: function(editor) {
+ editor.selectMore(1, true);
+ },
+ bindKey: { win: "Ctrl-Alt-Shift-Right", mac: "Ctrl-Alt-Shift-Right" },
+ scrollIntoView: "cursor",
+ readOnly: true
+ },
+ {
+ name: "toggleSplitSelectionIntoLines",
+ description: "Split into lines",
+ exec: function(editor) {
+ if (editor.multiSelect.rangeCount > 1)
+ editor.multiSelect.joinSelections();
+ else editor.multiSelect.splitIntoLines();
+ },
+ bindKey: { win: "Ctrl-Alt-L", mac: "Ctrl-Alt-L" },
+ readOnly: true
+ },
+ {
+ name: "splitSelectionIntoLines",
+ description: "Split into lines",
+ exec: function(editor) {
+ editor.multiSelect.splitIntoLines();
+ },
+ readOnly: true
+ },
+ {
+ name: "alignCursors",
+ description: "Align cursors",
+ exec: function(editor) {
+ editor.alignCursors();
+ },
+ bindKey: { win: "Ctrl-Alt-A", mac: "Ctrl-Alt-A" },
+ scrollIntoView: "cursor"
+ },
+ {
+ name: "findAll",
+ description: "Find all",
+ exec: function(editor) {
+ editor.findAll();
+ },
+ bindKey: { win: "Ctrl-Alt-K", mac: "Ctrl-Alt-G" },
+ scrollIntoView: "cursor",
+ readOnly: true
+ }
+ ];
+ exports.multiSelectCommands = [
+ {
+ name: "singleSelection",
+ description: "Single selection",
+ bindKey: "esc",
+ exec: function(editor) {
+ editor.exitMultiSelectMode();
+ },
+ scrollIntoView: "cursor",
+ readOnly: true,
+ isAvailable: function(editor) {
+ return editor && editor.inMultiSelectMode;
+ }
+ }
+ ];
+
+ var HashHandler = require("../keyboard/hash_handler").HashHandler;
+ exports.keyboardHandler = new HashHandler(exports.multiSelectCommands);
+ }
+);
+
+ace.define(
+ "ace/multi_select",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/range_list",
+ "ace/range",
+ "ace/selection",
+ "ace/mouse/multi_select_handler",
+ "ace/lib/event",
+ "ace/lib/lang",
+ "ace/commands/multi_select_commands",
+ "ace/search",
+ "ace/edit_session",
+ "ace/editor",
+ "ace/config"
+ ],
+ function(require, exports, module) {
+ var RangeList = require("./range_list").RangeList;
+ var Range = require("./range").Range;
+ var Selection = require("./selection").Selection;
+ var onMouseDown = require("./mouse/multi_select_handler").onMouseDown;
+ var event = require("./lib/event");
+ var lang = require("./lib/lang");
+ var commands = require("./commands/multi_select_commands");
+ exports.commands = commands.defaultCommands.concat(
+ commands.multiSelectCommands
+ );
+ var Search = require("./search").Search;
+ var search = new Search();
+
+ function find(session, needle, dir) {
+ search.$options.wrap = true;
+ search.$options.needle = needle;
+ search.$options.backwards = dir == -1;
+ return search.find(session);
+ }
+ var EditSession = require("./edit_session").EditSession;
+ (function() {
+ this.getSelectionMarkers = function() {
+ return this.$selectionMarkers;
+ };
+ }.call(EditSession.prototype));
+ (function() {
+ this.ranges = null;
+ this.rangeList = null;
+ this.addRange = function(range, $blockChangeEvents) {
+ if (!range) return;
+
+ if (!this.inMultiSelectMode && this.rangeCount === 0) {
+ var oldRange = this.toOrientedRange();
+ this.rangeList.add(oldRange);
+ this.rangeList.add(range);
+ if (this.rangeList.ranges.length != 2) {
+ this.rangeList.removeAll();
+ return $blockChangeEvents || this.fromOrientedRange(range);
+ }
+ this.rangeList.removeAll();
+ this.rangeList.add(oldRange);
+ this.$onAddRange(oldRange);
+ }
+
+ if (!range.cursor) range.cursor = range.end;
+
+ var removed = this.rangeList.add(range);
+
+ this.$onAddRange(range);
+
+ if (removed.length) this.$onRemoveRange(removed);
+
+ if (this.rangeCount > 1 && !this.inMultiSelectMode) {
+ this._signal("multiSelect");
+ this.inMultiSelectMode = true;
+ this.session.$undoSelect = false;
+ this.rangeList.attach(this.session);
+ }
+
+ return $blockChangeEvents || this.fromOrientedRange(range);
+ };
+ this.toSingleRange = function(range) {
+ range = range || this.ranges[0];
+ var removed = this.rangeList.removeAll();
+ if (removed.length) this.$onRemoveRange(removed);
+
+ range && this.fromOrientedRange(range);
+ };
+ this.substractPoint = function(pos) {
+ var removed = this.rangeList.substractPoint(pos);
+ if (removed) {
+ this.$onRemoveRange(removed);
+ return removed[0];
+ }
+ };
+ this.mergeOverlappingRanges = function() {
+ var removed = this.rangeList.merge();
+ if (removed.length) this.$onRemoveRange(removed);
+ };
+
+ this.$onAddRange = function(range) {
+ this.rangeCount = this.rangeList.ranges.length;
+ this.ranges.unshift(range);
+ this._signal("addRange", { range: range });
+ };
+
+ this.$onRemoveRange = function(removed) {
+ this.rangeCount = this.rangeList.ranges.length;
+ if (this.rangeCount == 1 && this.inMultiSelectMode) {
+ var lastRange = this.rangeList.ranges.pop();
+ removed.push(lastRange);
+ this.rangeCount = 0;
+ }
+
+ for (var i = removed.length; i--; ) {
+ var index = this.ranges.indexOf(removed[i]);
+ this.ranges.splice(index, 1);
+ }
+
+ this._signal("removeRange", { ranges: removed });
+
+ if (this.rangeCount === 0 && this.inMultiSelectMode) {
+ this.inMultiSelectMode = false;
+ this._signal("singleSelect");
+ this.session.$undoSelect = true;
+ this.rangeList.detach(this.session);
+ }
+
+ lastRange = lastRange || this.ranges[0];
+ if (lastRange && !lastRange.isEqual(this.getRange()))
+ this.fromOrientedRange(lastRange);
+ };
+ this.$initRangeList = function() {
+ if (this.rangeList) return;
+
+ this.rangeList = new RangeList();
+ this.ranges = [];
+ this.rangeCount = 0;
+ };
+ this.getAllRanges = function() {
+ return this.rangeCount
+ ? this.rangeList.ranges.concat()
+ : [this.getRange()];
+ };
+ this.splitIntoLines = function() {
+ var ranges = this.ranges.length ? this.ranges : [this.getRange()];
+ var newRanges = [];
+ for (var i = 0; i < ranges.length; i++) {
+ var range = ranges[i];
+ var row = range.start.row;
+ var endRow = range.end.row;
+ if (row === endRow) {
+ newRanges.push(range.clone());
+ } else {
+ newRanges.push(
+ new Range(
+ row,
+ range.start.column,
+ row,
+ this.session.getLine(row).length
+ )
+ );
+ while (++row < endRow) newRanges.push(this.getLineRange(row, true));
+ newRanges.push(new Range(endRow, 0, endRow, range.end.column));
+ }
+ if (i == 0 && !this.isBackwards()) newRanges = newRanges.reverse();
+ }
+ this.toSingleRange();
+ for (var i = newRanges.length; i--; ) this.addRange(newRanges[i]);
+ };
+
+ this.joinSelections = function() {
+ var ranges = this.rangeList.ranges;
+ var lastRange = ranges[ranges.length - 1];
+ var range = Range.fromPoints(ranges[0].start, lastRange.end);
+
+ this.toSingleRange();
+ this.setSelectionRange(range, lastRange.cursor == lastRange.start);
+ };
+ this.toggleBlockSelection = function() {
+ if (this.rangeCount > 1) {
+ var ranges = this.rangeList.ranges;
+ var lastRange = ranges[ranges.length - 1];
+ var range = Range.fromPoints(ranges[0].start, lastRange.end);
+
+ this.toSingleRange();
+ this.setSelectionRange(range, lastRange.cursor == lastRange.start);
+ } else {
+ var cursor = this.session.documentToScreenPosition(this.cursor);
+ var anchor = this.session.documentToScreenPosition(this.anchor);
+
+ var rectSel = this.rectangularRangeBlock(cursor, anchor);
+ rectSel.forEach(this.addRange, this);
+ }
+ };
+ this.rectangularRangeBlock = function(
+ screenCursor,
+ screenAnchor,
+ includeEmptyLines
+ ) {
+ var rectSel = [];
+
+ var xBackwards = screenCursor.column < screenAnchor.column;
+ if (xBackwards) {
+ var startColumn = screenCursor.column;
+ var endColumn = screenAnchor.column;
+ var startOffsetX = screenCursor.offsetX;
+ var endOffsetX = screenAnchor.offsetX;
+ } else {
+ var startColumn = screenAnchor.column;
+ var endColumn = screenCursor.column;
+ var startOffsetX = screenAnchor.offsetX;
+ var endOffsetX = screenCursor.offsetX;
+ }
+
+ var yBackwards = screenCursor.row < screenAnchor.row;
+ if (yBackwards) {
+ var startRow = screenCursor.row;
+ var endRow = screenAnchor.row;
+ } else {
+ var startRow = screenAnchor.row;
+ var endRow = screenCursor.row;
+ }
+
+ if (startColumn < 0) startColumn = 0;
+ if (startRow < 0) startRow = 0;
+
+ if (startRow == endRow) includeEmptyLines = true;
+
+ var docEnd;
+ for (var row = startRow; row <= endRow; row++) {
+ var range = Range.fromPoints(
+ this.session.screenToDocumentPosition(
+ row,
+ startColumn,
+ startOffsetX
+ ),
+ this.session.screenToDocumentPosition(row, endColumn, endOffsetX)
+ );
+ if (range.isEmpty()) {
+ if (docEnd && isSamePoint(range.end, docEnd)) break;
+ docEnd = range.end;
+ }
+ range.cursor = xBackwards ? range.start : range.end;
+ rectSel.push(range);
+ }
+
+ if (yBackwards) rectSel.reverse();
+
+ if (!includeEmptyLines) {
+ var end = rectSel.length - 1;
+ while (rectSel[end].isEmpty() && end > 0) end--;
+ if (end > 0) {
+ var start = 0;
+ while (rectSel[start].isEmpty()) start++;
+ }
+ for (var i = end; i >= start; i--) {
+ if (rectSel[i].isEmpty()) rectSel.splice(i, 1);
+ }
+ }
+
+ return rectSel;
+ };
+ }.call(Selection.prototype));
+ var Editor = require("./editor").Editor;
+ (function() {
+ this.updateSelectionMarkers = function() {
+ this.renderer.updateCursor();
+ this.renderer.updateBackMarkers();
+ };
+ this.addSelectionMarker = function(orientedRange) {
+ if (!orientedRange.cursor) orientedRange.cursor = orientedRange.end;
+
+ var style = this.getSelectionStyle();
+ orientedRange.marker = this.session.addMarker(
+ orientedRange,
+ "ace_selection",
+ style
+ );
+
+ this.session.$selectionMarkers.push(orientedRange);
+ this.session.selectionMarkerCount = this.session.$selectionMarkers.length;
+ return orientedRange;
+ };
+ this.removeSelectionMarker = function(range) {
+ if (!range.marker) return;
+ this.session.removeMarker(range.marker);
+ var index = this.session.$selectionMarkers.indexOf(range);
+ if (index != -1) this.session.$selectionMarkers.splice(index, 1);
+ this.session.selectionMarkerCount = this.session.$selectionMarkers.length;
+ };
+
+ this.removeSelectionMarkers = function(ranges) {
+ var markerList = this.session.$selectionMarkers;
+ for (var i = ranges.length; i--; ) {
+ var range = ranges[i];
+ if (!range.marker) continue;
+ this.session.removeMarker(range.marker);
+ var index = markerList.indexOf(range);
+ if (index != -1) markerList.splice(index, 1);
+ }
+ this.session.selectionMarkerCount = markerList.length;
+ };
+
+ this.$onAddRange = function(e) {
+ this.addSelectionMarker(e.range);
+ this.renderer.updateCursor();
+ this.renderer.updateBackMarkers();
+ };
+
+ this.$onRemoveRange = function(e) {
+ this.removeSelectionMarkers(e.ranges);
+ this.renderer.updateCursor();
+ this.renderer.updateBackMarkers();
+ };
+
+ this.$onMultiSelect = function(e) {
+ if (this.inMultiSelectMode) return;
+ this.inMultiSelectMode = true;
+
+ this.setStyle("ace_multiselect");
+ this.keyBinding.addKeyboardHandler(commands.keyboardHandler);
+ this.commands.setDefaultHandler("exec", this.$onMultiSelectExec);
+
+ this.renderer.updateCursor();
+ this.renderer.updateBackMarkers();
+ };
+
+ this.$onSingleSelect = function(e) {
+ if (this.session.multiSelect.inVirtualMode) return;
+ this.inMultiSelectMode = false;
+
+ this.unsetStyle("ace_multiselect");
+ this.keyBinding.removeKeyboardHandler(commands.keyboardHandler);
+
+ this.commands.removeDefaultHandler("exec", this.$onMultiSelectExec);
+ this.renderer.updateCursor();
+ this.renderer.updateBackMarkers();
+ this._emit("changeSelection");
+ };
+
+ this.$onMultiSelectExec = function(e) {
+ var command = e.command;
+ var editor = e.editor;
+ if (!editor.multiSelect) return;
+ if (!command.multiSelectAction) {
+ var result = command.exec(editor, e.args || {});
+ editor.multiSelect.addRange(editor.multiSelect.toOrientedRange());
+ editor.multiSelect.mergeOverlappingRanges();
+ } else if (command.multiSelectAction == "forEach") {
+ result = editor.forEachSelection(command, e.args);
+ } else if (command.multiSelectAction == "forEachLine") {
+ result = editor.forEachSelection(command, e.args, true);
+ } else if (command.multiSelectAction == "single") {
+ editor.exitMultiSelectMode();
+ result = command.exec(editor, e.args || {});
+ } else {
+ result = command.multiSelectAction(editor, e.args || {});
+ }
+ return result;
+ };
+ this.forEachSelection = function(cmd, args, options) {
+ if (this.inVirtualSelectionMode) return;
+ var keepOrder = options && options.keepOrder;
+ var $byLines = options == true || (options && options.$byLines);
+ var session = this.session;
+ var selection = this.selection;
+ var rangeList = selection.rangeList;
+ var ranges = (keepOrder ? selection : rangeList).ranges;
+ var result;
+
+ if (!ranges.length)
+ return cmd.exec ? cmd.exec(this, args || {}) : cmd(this, args || {});
+
+ var reg = selection._eventRegistry;
+ selection._eventRegistry = {};
+
+ var tmpSel = new Selection(session);
+ this.inVirtualSelectionMode = true;
+ for (var i = ranges.length; i--; ) {
+ if ($byLines) {
+ while (i > 0 && ranges[i].start.row == ranges[i - 1].end.row) i--;
+ }
+ tmpSel.fromOrientedRange(ranges[i]);
+ tmpSel.index = i;
+ this.selection = session.selection = tmpSel;
+ var cmdResult = cmd.exec
+ ? cmd.exec(this, args || {})
+ : cmd(this, args || {});
+ if (!result && cmdResult !== undefined) result = cmdResult;
+ tmpSel.toOrientedRange(ranges[i]);
+ }
+ tmpSel.detach();
+
+ this.selection = session.selection = selection;
+ this.inVirtualSelectionMode = false;
+ selection._eventRegistry = reg;
+ selection.mergeOverlappingRanges();
+ if (selection.ranges[0])
+ selection.fromOrientedRange(selection.ranges[0]);
+
+ var anim = this.renderer.$scrollAnimation;
+ this.onCursorChange();
+ this.onSelectionChange();
+ if (anim && anim.from == anim.to)
+ this.renderer.animateScrolling(anim.from);
+
+ return result;
+ };
+ this.exitMultiSelectMode = function() {
+ if (!this.inMultiSelectMode || this.inVirtualSelectionMode) return;
+ this.multiSelect.toSingleRange();
+ };
+
+ this.getSelectedText = function() {
+ var text = "";
+ if (this.inMultiSelectMode && !this.inVirtualSelectionMode) {
+ var ranges = this.multiSelect.rangeList.ranges;
+ var buf = [];
+ for (var i = 0; i < ranges.length; i++) {
+ buf.push(this.session.getTextRange(ranges[i]));
+ }
+ var nl = this.session.getDocument().getNewLineCharacter();
+ text = buf.join(nl);
+ if (text.length == (buf.length - 1) * nl.length) text = "";
+ } else if (!this.selection.isEmpty()) {
+ text = this.session.getTextRange(this.getSelectionRange());
+ }
+ return text;
+ };
+
+ this.$checkMultiselectChange = function(e, anchor) {
+ if (this.inMultiSelectMode && !this.inVirtualSelectionMode) {
+ var range = this.multiSelect.ranges[0];
+ if (this.multiSelect.isEmpty() && anchor == this.multiSelect.anchor)
+ return;
+ var pos =
+ anchor == this.multiSelect.anchor
+ ? range.cursor == range.start
+ ? range.end
+ : range.start
+ : range.cursor;
+ if (
+ pos.row != anchor.row ||
+ this.session.$clipPositionToDocument(pos.row, pos.column).column !=
+ anchor.column
+ )
+ this.multiSelect.toSingleRange(this.multiSelect.toOrientedRange());
+ else this.multiSelect.mergeOverlappingRanges();
+ }
+ };
+ this.findAll = function(needle, options, additive) {
+ options = options || {};
+ options.needle = needle || options.needle;
+ if (options.needle == undefined) {
+ var range = this.selection.isEmpty()
+ ? this.selection.getWordRange()
+ : this.selection.getRange();
+ options.needle = this.session.getTextRange(range);
+ }
+ this.$search.set(options);
+
+ var ranges = this.$search.findAll(this.session);
+ if (!ranges.length) return 0;
+
+ var selection = this.multiSelect;
+
+ if (!additive) selection.toSingleRange(ranges[0]);
+
+ for (var i = ranges.length; i--; ) selection.addRange(ranges[i], true);
+ if (range && selection.rangeList.rangeAtPoint(range.start))
+ selection.addRange(range, true);
+
+ return ranges.length;
+ };
+ this.selectMoreLines = function(dir, skip) {
+ var range = this.selection.toOrientedRange();
+ var isBackwards = range.cursor == range.end;
+
+ var screenLead = this.session.documentToScreenPosition(range.cursor);
+ if (this.selection.$desiredColumn)
+ screenLead.column = this.selection.$desiredColumn;
+
+ var lead = this.session.screenToDocumentPosition(
+ screenLead.row + dir,
+ screenLead.column
+ );
+
+ if (!range.isEmpty()) {
+ var screenAnchor = this.session.documentToScreenPosition(
+ isBackwards ? range.end : range.start
+ );
+ var anchor = this.session.screenToDocumentPosition(
+ screenAnchor.row + dir,
+ screenAnchor.column
+ );
+ } else {
+ var anchor = lead;
+ }
+
+ if (isBackwards) {
+ var newRange = Range.fromPoints(lead, anchor);
+ newRange.cursor = newRange.start;
+ } else {
+ var newRange = Range.fromPoints(anchor, lead);
+ newRange.cursor = newRange.end;
+ }
+
+ newRange.desiredColumn = screenLead.column;
+ if (!this.selection.inMultiSelectMode) {
+ this.selection.addRange(range);
+ } else {
+ if (skip) var toRemove = range.cursor;
+ }
+
+ this.selection.addRange(newRange);
+ if (toRemove) this.selection.substractPoint(toRemove);
+ };
+ this.transposeSelections = function(dir) {
+ var session = this.session;
+ var sel = session.multiSelect;
+ var all = sel.ranges;
+
+ for (var i = all.length; i--; ) {
+ var range = all[i];
+ if (range.isEmpty()) {
+ var tmp = session.getWordRange(range.start.row, range.start.column);
+ range.start.row = tmp.start.row;
+ range.start.column = tmp.start.column;
+ range.end.row = tmp.end.row;
+ range.end.column = tmp.end.column;
+ }
+ }
+ sel.mergeOverlappingRanges();
+
+ var words = [];
+ for (var i = all.length; i--; ) {
+ var range = all[i];
+ words.unshift(session.getTextRange(range));
+ }
+
+ if (dir < 0) words.unshift(words.pop());
+ else words.push(words.shift());
+
+ for (var i = all.length; i--; ) {
+ var range = all[i];
+ var tmp = range.clone();
+ session.replace(range, words[i]);
+ range.start.row = tmp.start.row;
+ range.start.column = tmp.start.column;
+ }
+ sel.fromOrientedRange(sel.ranges[0]);
+ };
+ this.selectMore = function(dir, skip, stopAtFirst) {
+ var session = this.session;
+ var sel = session.multiSelect;
+
+ var range = sel.toOrientedRange();
+ if (range.isEmpty()) {
+ range = session.getWordRange(range.start.row, range.start.column);
+ range.cursor = dir == -1 ? range.start : range.end;
+ this.multiSelect.addRange(range);
+ if (stopAtFirst) return;
+ }
+ var needle = session.getTextRange(range);
+
+ var newRange = find(session, needle, dir);
+ if (newRange) {
+ newRange.cursor = dir == -1 ? newRange.start : newRange.end;
+ this.session.unfold(newRange);
+ this.multiSelect.addRange(newRange);
+ this.renderer.scrollCursorIntoView(null, 0.5);
+ }
+ if (skip) this.multiSelect.substractPoint(range.cursor);
+ };
+ this.alignCursors = function() {
+ var session = this.session;
+ var sel = session.multiSelect;
+ var ranges = sel.ranges;
+ var row = -1;
+ var sameRowRanges = ranges.filter(function(r) {
+ if (r.cursor.row == row) return true;
+ row = r.cursor.row;
+ });
+
+ if (!ranges.length || sameRowRanges.length == ranges.length - 1) {
+ var range = this.selection.getRange();
+ var fr = range.start.row,
+ lr = range.end.row;
+ var guessRange = fr == lr;
+ if (guessRange) {
+ var max = this.session.getLength();
+ var line;
+ do {
+ line = this.session.getLine(lr);
+ } while (/[=:]/.test(line) && ++lr < max);
+ do {
+ line = this.session.getLine(fr);
+ } while (/[=:]/.test(line) && --fr > 0);
+
+ if (fr < 0) fr = 0;
+ if (lr >= max) lr = max - 1;
+ }
+ var lines = this.session.removeFullLines(fr, lr);
+ lines = this.$reAlignText(lines, guessRange);
+ this.session.insert({ row: fr, column: 0 }, lines.join("\n") + "\n");
+ if (!guessRange) {
+ range.start.column = 0;
+ range.end.column = lines[lines.length - 1].length;
+ }
+ this.selection.setRange(range);
+ } else {
+ sameRowRanges.forEach(function(r) {
+ sel.substractPoint(r.cursor);
+ });
+
+ var maxCol = 0;
+ var minSpace = Infinity;
+ var spaceOffsets = ranges.map(function(r) {
+ var p = r.cursor;
+ var line = session.getLine(p.row);
+ var spaceOffset = line.substr(p.column).search(/\S/g);
+ if (spaceOffset == -1) spaceOffset = 0;
+
+ if (p.column > maxCol) maxCol = p.column;
+ if (spaceOffset < minSpace) minSpace = spaceOffset;
+ return spaceOffset;
+ });
+ ranges.forEach(function(r, i) {
+ var p = r.cursor;
+ var l = maxCol - p.column;
+ var d = spaceOffsets[i] - minSpace;
+ if (l > d) session.insert(p, lang.stringRepeat(" ", l - d));
+ else
+ session.remove(
+ new Range(p.row, p.column, p.row, p.column - l + d)
+ );
+
+ r.start.column = r.end.column = maxCol;
+ r.start.row = r.end.row = p.row;
+ r.cursor = r.end;
+ });
+ sel.fromOrientedRange(ranges[0]);
+ this.renderer.updateCursor();
+ this.renderer.updateBackMarkers();
+ }
+ };
+
+ this.$reAlignText = function(lines, forceLeft) {
+ var isLeftAligned = true,
+ isRightAligned = true;
+ var startW, textW, endW;
+
+ return lines
+ .map(function(line) {
+ var m = line.match(/(\s*)(.*?)(\s*)([=:].*)/);
+ if (!m) return [line];
+
+ if (startW == null) {
+ startW = m[1].length;
+ textW = m[2].length;
+ endW = m[3].length;
+ return m;
+ }
+
+ if (
+ startW + textW + endW !=
+ m[1].length + m[2].length + m[3].length
+ )
+ isRightAligned = false;
+ if (startW != m[1].length) isLeftAligned = false;
+
+ if (startW > m[1].length) startW = m[1].length;
+ if (textW < m[2].length) textW = m[2].length;
+ if (endW > m[3].length) endW = m[3].length;
+
+ return m;
+ })
+ .map(
+ forceLeft
+ ? alignLeft
+ : isLeftAligned
+ ? isRightAligned
+ ? alignRight
+ : alignLeft
+ : unAlign
+ );
+
+ function spaces(n) {
+ return lang.stringRepeat(" ", n);
+ }
+
+ function alignLeft(m) {
+ return !m[2]
+ ? m[0]
+ : spaces(startW) +
+ m[2] +
+ spaces(textW - m[2].length + endW) +
+ m[4].replace(/^([=:])\s+/, "$1 ");
+ }
+ function alignRight(m) {
+ return !m[2]
+ ? m[0]
+ : spaces(startW + textW - m[2].length) +
+ m[2] +
+ spaces(endW) +
+ m[4].replace(/^([=:])\s+/, "$1 ");
+ }
+ function unAlign(m) {
+ return !m[2]
+ ? m[0]
+ : spaces(startW) +
+ m[2] +
+ spaces(endW) +
+ m[4].replace(/^([=:])\s+/, "$1 ");
+ }
+ };
+ }.call(Editor.prototype));
+
+ function isSamePoint(p1, p2) {
+ return p1.row == p2.row && p1.column == p2.column;
+ }
+ exports.onSessionChange = function(e) {
+ var session = e.session;
+ if (session && !session.multiSelect) {
+ session.$selectionMarkers = [];
+ session.selection.$initRangeList();
+ session.multiSelect = session.selection;
+ }
+ this.multiSelect = session && session.multiSelect;
+
+ var oldSession = e.oldSession;
+ if (oldSession) {
+ oldSession.multiSelect.off("addRange", this.$onAddRange);
+ oldSession.multiSelect.off("removeRange", this.$onRemoveRange);
+ oldSession.multiSelect.off("multiSelect", this.$onMultiSelect);
+ oldSession.multiSelect.off("singleSelect", this.$onSingleSelect);
+ oldSession.multiSelect.lead.off("change", this.$checkMultiselectChange);
+ oldSession.multiSelect.anchor.off(
+ "change",
+ this.$checkMultiselectChange
+ );
+ }
+
+ if (session) {
+ session.multiSelect.on("addRange", this.$onAddRange);
+ session.multiSelect.on("removeRange", this.$onRemoveRange);
+ session.multiSelect.on("multiSelect", this.$onMultiSelect);
+ session.multiSelect.on("singleSelect", this.$onSingleSelect);
+ session.multiSelect.lead.on("change", this.$checkMultiselectChange);
+ session.multiSelect.anchor.on("change", this.$checkMultiselectChange);
+ }
+
+ if (
+ session &&
+ this.inMultiSelectMode != session.selection.inMultiSelectMode
+ ) {
+ if (session.selection.inMultiSelectMode) this.$onMultiSelect();
+ else this.$onSingleSelect();
+ }
+ };
+ function MultiSelect(editor) {
+ if (editor.$multiselectOnSessionChange) return;
+ editor.$onAddRange = editor.$onAddRange.bind(editor);
+ editor.$onRemoveRange = editor.$onRemoveRange.bind(editor);
+ editor.$onMultiSelect = editor.$onMultiSelect.bind(editor);
+ editor.$onSingleSelect = editor.$onSingleSelect.bind(editor);
+ editor.$multiselectOnSessionChange = exports.onSessionChange.bind(editor);
+ editor.$checkMultiselectChange = editor.$checkMultiselectChange.bind(
+ editor
+ );
+
+ editor.$multiselectOnSessionChange(editor);
+ editor.on("changeSession", editor.$multiselectOnSessionChange);
+
+ editor.on("mousedown", onMouseDown);
+ editor.commands.addCommands(commands.defaultCommands);
+
+ addAltCursorListeners(editor);
+ }
+
+ function addAltCursorListeners(editor) {
+ if (!editor.textInput) return;
+ var el = editor.textInput.getElement();
+ var altCursor = false;
+ event.addListener(
+ el,
+ "keydown",
+ function(e) {
+ var altDown =
+ e.keyCode == 18 && !(e.ctrlKey || e.shiftKey || e.metaKey);
+ if (editor.$blockSelectEnabled && altDown) {
+ if (!altCursor) {
+ editor.renderer.setMouseCursor("crosshair");
+ altCursor = true;
+ }
+ } else if (altCursor) {
+ reset();
+ }
+ },
+ editor
+ );
+
+ event.addListener(el, "keyup", reset, editor);
+ event.addListener(el, "blur", reset, editor);
+ function reset(e) {
+ if (altCursor) {
+ editor.renderer.setMouseCursor("");
+ altCursor = false;
+ }
+ }
+ }
+
+ exports.MultiSelect = MultiSelect;
+
+ require("./config").defineOptions(Editor.prototype, "editor", {
+ enableMultiselect: {
+ set: function(val) {
+ MultiSelect(this);
+ if (val) {
+ this.on("changeSession", this.$multiselectOnSessionChange);
+ this.on("mousedown", onMouseDown);
+ } else {
+ this.off("changeSession", this.$multiselectOnSessionChange);
+ this.off("mousedown", onMouseDown);
+ }
+ },
+ value: true
+ },
+ enableBlockSelect: {
+ set: function(val) {
+ this.$blockSelectEnabled = val;
+ },
+ value: true
+ }
+ });
+ }
+);
+
+ace.define(
+ "ace/mode/folding/fold_mode",
+ ["require", "exports", "module", "ace/range"],
+ function(require, exports, module) {
+ "use strict";
+
+ var Range = require("../../range").Range;
+
+ var FoldMode = (exports.FoldMode = function() {});
+
+ (function() {
+ this.foldingStartMarker = null;
+ this.foldingStopMarker = null;
+ this.getFoldWidget = function(session, foldStyle, row) {
+ var line = session.getLine(row);
+ if (this.foldingStartMarker.test(line)) return "start";
+ if (
+ foldStyle == "markbeginend" &&
+ this.foldingStopMarker &&
+ this.foldingStopMarker.test(line)
+ )
+ return "end";
+ return "";
+ };
+
+ this.getFoldWidgetRange = function(session, foldStyle, row) {
+ return null;
+ };
+
+ this.indentationBlock = function(session, row, column) {
+ var re = /\S/;
+ var line = session.getLine(row);
+ var startLevel = line.search(re);
+ if (startLevel == -1) return;
+
+ var startColumn = column || line.length;
+ var maxRow = session.getLength();
+ var startRow = row;
+ var endRow = row;
+
+ while (++row < maxRow) {
+ var level = session.getLine(row).search(re);
+
+ if (level == -1) continue;
+
+ if (level <= startLevel) {
+ var token = session.getTokenAt(row, 0);
+ if (!token || token.type !== "string") break;
+ }
+
+ endRow = row;
+ }
+
+ if (endRow > startRow) {
+ var endColumn = session.getLine(endRow).length;
+ return new Range(startRow, startColumn, endRow, endColumn);
+ }
+ };
+
+ this.openingBracketBlock = function(
+ session,
+ bracket,
+ row,
+ column,
+ typeRe
+ ) {
+ var start = { row: row, column: column + 1 };
+ var end = session.$findClosingBracket(bracket, start, typeRe);
+ if (!end) return;
+
+ var fw = session.foldWidgets[end.row];
+ if (fw == null) fw = session.getFoldWidget(end.row);
+
+ if (fw == "start" && end.row > start.row) {
+ end.row--;
+ end.column = session.getLine(end.row).length;
+ }
+ return Range.fromPoints(start, end);
+ };
+
+ this.closingBracketBlock = function(
+ session,
+ bracket,
+ row,
+ column,
+ typeRe
+ ) {
+ var end = { row: row, column: column };
+ var start = session.$findOpeningBracket(bracket, end);
+
+ if (!start) return;
+
+ start.column++;
+ end.column--;
+
+ return Range.fromPoints(start, end);
+ };
+ }.call(FoldMode.prototype));
+ }
+);
+
+ace.define(
+ "ace/theme/textmate",
+ ["require", "exports", "module", "ace/lib/dom"],
+ function(require, exports, module) {
+ "use strict";
+
+ exports.isDark = false;
+ exports.cssClass = "ace-tm";
+ exports.cssText =
+ '.ace-tm .ace_gutter {\
+ background: #f0f0f0;\
+ color: #333;\
+ }\
+ .ace-tm .ace_print-margin {\
+ width: 1px;\
+ background: #e8e8e8;\
+ }\
+ .ace-tm .ace_fold {\
+ background-color: #6B72E6;\
+ }\
+ .ace-tm {\
+ background-color: #FFFFFF;\
+ color: black;\
+ }\
+ .ace-tm .ace_cursor {\
+ color: black;\
+ }\
+ .ace-tm .ace_invisible {\
+ color: rgb(191, 191, 191);\
+ }\
+ .ace-tm .ace_storage,\
+ .ace-tm .ace_keyword {\
+ color: blue;\
+ }\
+ .ace-tm .ace_constant {\
+ color: rgb(197, 6, 11);\
+ }\
+ .ace-tm .ace_constant.ace_buildin {\
+ color: rgb(88, 72, 246);\
+ }\
+ .ace-tm .ace_constant.ace_language {\
+ color: rgb(88, 92, 246);\
+ }\
+ .ace-tm .ace_constant.ace_library {\
+ color: rgb(6, 150, 14);\
+ }\
+ .ace-tm .ace_invalid {\
+ background-color: rgba(255, 0, 0, 0.1);\
+ color: red;\
+ }\
+ .ace-tm .ace_support.ace_function {\
+ color: rgb(60, 76, 114);\
+ }\
+ .ace-tm .ace_support.ace_constant {\
+ color: rgb(6, 150, 14);\
+ }\
+ .ace-tm .ace_support.ace_type,\
+ .ace-tm .ace_support.ace_class {\
+ color: rgb(109, 121, 222);\
+ }\
+ .ace-tm .ace_keyword.ace_operator {\
+ color: rgb(104, 118, 135);\
+ }\
+ .ace-tm .ace_string {\
+ color: rgb(3, 106, 7);\
+ }\
+ .ace-tm .ace_comment {\
+ color: rgb(76, 136, 107);\
+ }\
+ .ace-tm .ace_comment.ace_doc {\
+ color: rgb(0, 102, 255);\
+ }\
+ .ace-tm .ace_comment.ace_doc.ace_tag {\
+ color: rgb(128, 159, 191);\
+ }\
+ .ace-tm .ace_constant.ace_numeric {\
+ color: rgb(0, 0, 205);\
+ }\
+ .ace-tm .ace_variable {\
+ color: rgb(49, 132, 149);\
+ }\
+ .ace-tm .ace_xml-pe {\
+ color: rgb(104, 104, 91);\
+ }\
+ .ace-tm .ace_entity.ace_name.ace_function {\
+ color: #0000A2;\
+ }\
+ .ace-tm .ace_heading {\
+ color: rgb(12, 7, 255);\
+ }\
+ .ace-tm .ace_list {\
+ color:rgb(185, 6, 144);\
+ }\
+ .ace-tm .ace_meta.ace_tag {\
+ color:rgb(0, 22, 142);\
+ }\
+ .ace-tm .ace_string.ace_regex {\
+ color: rgb(255, 0, 0)\
+ }\
+ .ace-tm .ace_marker-layer .ace_selection {\
+ background: rgb(181, 213, 255);\
+ }\
+ .ace-tm.ace_multiselect .ace_selection.ace_start {\
+ box-shadow: 0 0 3px 0px white;\
+ }\
+ .ace-tm .ace_marker-layer .ace_step {\
+ background: rgb(252, 255, 0);\
+ }\
+ .ace-tm .ace_marker-layer .ace_stack {\
+ background: rgb(164, 229, 101);\
+ }\
+ .ace-tm .ace_marker-layer .ace_bracket {\
+ margin: -1px 0 0 -1px;\
+ border: 1px solid rgb(192, 192, 192);\
+ }\
+ .ace-tm .ace_marker-layer .ace_active-line {\
+ background: rgba(0, 0, 0, 0.07);\
+ }\
+ .ace-tm .ace_gutter-active-line {\
+ background-color : #dcdcdc;\
+ }\
+ .ace-tm .ace_marker-layer .ace_selected-word {\
+ background: rgb(250, 250, 255);\
+ border: 1px solid rgb(200, 200, 250);\
+ }\
+ .ace-tm .ace_indent-guide {\
+ background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y;\
+ }\
+ ';
+ exports.$id = "ace/theme/textmate";
+
+ var dom = require("../lib/dom");
+ dom.importCssString(exports.cssText, exports.cssClass);
+ }
+);
+
+ace.define(
+ "ace/line_widgets",
+ ["require", "exports", "module", "ace/lib/dom"],
+ function(require, exports, module) {
+ "use strict";
+
+ var dom = require("./lib/dom");
+
+ function LineWidgets(session) {
+ this.session = session;
+ this.session.widgetManager = this;
+ this.session.getRowLength = this.getRowLength;
+ this.session.$getWidgetScreenLength = this.$getWidgetScreenLength;
+ this.updateOnChange = this.updateOnChange.bind(this);
+ this.renderWidgets = this.renderWidgets.bind(this);
+ this.measureWidgets = this.measureWidgets.bind(this);
+ this.session._changedWidgets = [];
+ this.$onChangeEditor = this.$onChangeEditor.bind(this);
+
+ this.session.on("change", this.updateOnChange);
+ this.session.on("changeFold", this.updateOnFold);
+ this.session.on("changeEditor", this.$onChangeEditor);
+ }
+
+ (function() {
+ this.getRowLength = function(row) {
+ var h;
+ if (this.lineWidgets)
+ h = (this.lineWidgets[row] && this.lineWidgets[row].rowCount) || 0;
+ else h = 0;
+ if (!this.$useWrapMode || !this.$wrapData[row]) {
+ return 1 + h;
+ } else {
+ return this.$wrapData[row].length + 1 + h;
+ }
+ };
+
+ this.$getWidgetScreenLength = function() {
+ var screenRows = 0;
+ this.lineWidgets.forEach(function(w) {
+ if (w && w.rowCount && !w.hidden) screenRows += w.rowCount;
+ });
+ return screenRows;
+ };
+
+ this.$onChangeEditor = function(e) {
+ this.attach(e.editor);
+ };
+
+ this.attach = function(editor) {
+ if (editor && editor.widgetManager && editor.widgetManager != this)
+ editor.widgetManager.detach();
+
+ if (this.editor == editor) return;
+
+ this.detach();
+ this.editor = editor;
+
+ if (editor) {
+ editor.widgetManager = this;
+ editor.renderer.on("beforeRender", this.measureWidgets);
+ editor.renderer.on("afterRender", this.renderWidgets);
+ }
+ };
+ this.detach = function(e) {
+ var editor = this.editor;
+ if (!editor) return;
+
+ this.editor = null;
+ editor.widgetManager = null;
+
+ editor.renderer.off("beforeRender", this.measureWidgets);
+ editor.renderer.off("afterRender", this.renderWidgets);
+ var lineWidgets = this.session.lineWidgets;
+ lineWidgets &&
+ lineWidgets.forEach(function(w) {
+ if (w && w.el && w.el.parentNode) {
+ w._inDocument = false;
+ w.el.parentNode.removeChild(w.el);
+ }
+ });
+ };
+
+ this.updateOnFold = function(e, session) {
+ var lineWidgets = session.lineWidgets;
+ if (!lineWidgets || !e.action) return;
+ var fold = e.data;
+ var start = fold.start.row;
+ var end = fold.end.row;
+ var hide = e.action == "add";
+ for (var i = start + 1; i < end; i++) {
+ if (lineWidgets[i]) lineWidgets[i].hidden = hide;
+ }
+ if (lineWidgets[end]) {
+ if (hide) {
+ if (!lineWidgets[start]) lineWidgets[start] = lineWidgets[end];
+ else lineWidgets[end].hidden = hide;
+ } else {
+ if (lineWidgets[start] == lineWidgets[end])
+ lineWidgets[start] = undefined;
+ lineWidgets[end].hidden = hide;
+ }
+ }
+ };
+
+ this.updateOnChange = function(delta) {
+ var lineWidgets = this.session.lineWidgets;
+ if (!lineWidgets) return;
+
+ var startRow = delta.start.row;
+ var len = delta.end.row - startRow;
+
+ if (len === 0) {
+ } else if (delta.action == "remove") {
+ var removed = lineWidgets.splice(startRow + 1, len);
+ if (!lineWidgets[startRow] && removed[removed.length - 1]) {
+ lineWidgets[startRow] = removed.pop();
+ }
+ removed.forEach(function(w) {
+ w && this.removeLineWidget(w);
+ }, this);
+ this.$updateRows();
+ } else {
+ var args = new Array(len);
+ if (lineWidgets[startRow] && lineWidgets[startRow].column != null) {
+ if (delta.start.column > lineWidgets[startRow].column) startRow++;
+ }
+ args.unshift(startRow, 0);
+ lineWidgets.splice.apply(lineWidgets, args);
+ this.$updateRows();
+ }
+ };
+
+ this.$updateRows = function() {
+ var lineWidgets = this.session.lineWidgets;
+ if (!lineWidgets) return;
+ var noWidgets = true;
+ lineWidgets.forEach(function(w, i) {
+ if (w) {
+ noWidgets = false;
+ w.row = i;
+ while (w.$oldWidget) {
+ w.$oldWidget.row = i;
+ w = w.$oldWidget;
+ }
+ }
+ });
+ if (noWidgets) this.session.lineWidgets = null;
+ };
+
+ this.$registerLineWidget = function(w) {
+ if (!this.session.lineWidgets)
+ this.session.lineWidgets = new Array(this.session.getLength());
+
+ var old = this.session.lineWidgets[w.row];
+ if (old) {
+ w.$oldWidget = old;
+ if (old.el && old.el.parentNode) {
+ old.el.parentNode.removeChild(old.el);
+ old._inDocument = false;
+ }
+ }
+
+ this.session.lineWidgets[w.row] = w;
+ return w;
+ };
+
+ this.addLineWidget = function(w) {
+ this.$registerLineWidget(w);
+ w.session = this.session;
+
+ if (!this.editor) return w;
+
+ var renderer = this.editor.renderer;
+ if (w.html && !w.el) {
+ w.el = dom.createElement("div");
+ w.el.innerHTML = w.html;
+ }
+ if (w.el) {
+ dom.addCssClass(w.el, "ace_lineWidgetContainer");
+ w.el.style.position = "absolute";
+ w.el.style.zIndex = 5;
+ renderer.container.appendChild(w.el);
+ w._inDocument = true;
+
+ if (!w.coverGutter) {
+ w.el.style.zIndex = 3;
+ }
+ if (w.pixelHeight == null) {
+ w.pixelHeight = w.el.offsetHeight;
+ }
+ }
+ if (w.rowCount == null) {
+ w.rowCount = w.pixelHeight / renderer.layerConfig.lineHeight;
+ }
+
+ var fold = this.session.getFoldAt(w.row, 0);
+ w.$fold = fold;
+ if (fold) {
+ var lineWidgets = this.session.lineWidgets;
+ if (w.row == fold.end.row && !lineWidgets[fold.start.row])
+ lineWidgets[fold.start.row] = w;
+ else w.hidden = true;
+ }
+
+ this.session._emit("changeFold", { data: { start: { row: w.row } } });
+
+ this.$updateRows();
+ this.renderWidgets(null, renderer);
+ this.onWidgetChanged(w);
+ return w;
+ };
+
+ this.removeLineWidget = function(w) {
+ w._inDocument = false;
+ w.session = null;
+ if (w.el && w.el.parentNode) w.el.parentNode.removeChild(w.el);
+ if (w.editor && w.editor.destroy)
+ try {
+ w.editor.destroy();
+ } catch (e) {}
+ if (this.session.lineWidgets) {
+ var w1 = this.session.lineWidgets[w.row];
+ if (w1 == w) {
+ this.session.lineWidgets[w.row] = w.$oldWidget;
+ if (w.$oldWidget) this.onWidgetChanged(w.$oldWidget);
+ } else {
+ while (w1) {
+ if (w1.$oldWidget == w) {
+ w1.$oldWidget = w.$oldWidget;
+ break;
+ }
+ w1 = w1.$oldWidget;
+ }
+ }
+ }
+ this.session._emit("changeFold", { data: { start: { row: w.row } } });
+ this.$updateRows();
+ };
+
+ this.getWidgetsAtRow = function(row) {
+ var lineWidgets = this.session.lineWidgets;
+ var w = lineWidgets && lineWidgets[row];
+ var list = [];
+ while (w) {
+ list.push(w);
+ w = w.$oldWidget;
+ }
+ return list;
+ };
+
+ this.onWidgetChanged = function(w) {
+ this.session._changedWidgets.push(w);
+ this.editor && this.editor.renderer.updateFull();
+ };
+
+ this.measureWidgets = function(e, renderer) {
+ var changedWidgets = this.session._changedWidgets;
+ var config = renderer.layerConfig;
+
+ if (!changedWidgets || !changedWidgets.length) return;
+ var min = Infinity;
+ for (var i = 0; i < changedWidgets.length; i++) {
+ var w = changedWidgets[i];
+ if (!w || !w.el) continue;
+ if (w.session != this.session) continue;
+ if (!w._inDocument) {
+ if (this.session.lineWidgets[w.row] != w) continue;
+ w._inDocument = true;
+ renderer.container.appendChild(w.el);
+ }
+
+ w.h = w.el.offsetHeight;
+
+ if (!w.fixedWidth) {
+ w.w = w.el.offsetWidth;
+ w.screenWidth = Math.ceil(w.w / config.characterWidth);
+ }
+
+ var rowCount = w.h / config.lineHeight;
+ if (w.coverLine) {
+ rowCount -= this.session.getRowLineCount(w.row);
+ if (rowCount < 0) rowCount = 0;
+ }
+ if (w.rowCount != rowCount) {
+ w.rowCount = rowCount;
+ if (w.row < min) min = w.row;
+ }
+ }
+ if (min != Infinity) {
+ this.session._emit("changeFold", { data: { start: { row: min } } });
+ this.session.lineWidgetWidth = null;
+ }
+ this.session._changedWidgets = [];
+ };
+
+ this.renderWidgets = function(e, renderer) {
+ var config = renderer.layerConfig;
+ var lineWidgets = this.session.lineWidgets;
+ if (!lineWidgets) return;
+ var first = Math.min(this.firstRow, config.firstRow);
+ var last = Math.max(this.lastRow, config.lastRow, lineWidgets.length);
+
+ while (first > 0 && !lineWidgets[first]) first--;
+
+ this.firstRow = config.firstRow;
+ this.lastRow = config.lastRow;
+
+ renderer.$cursorLayer.config = config;
+ for (var i = first; i <= last; i++) {
+ var w = lineWidgets[i];
+ if (!w || !w.el) continue;
+ if (w.hidden) {
+ w.el.style.top = -100 - (w.pixelHeight || 0) + "px";
+ continue;
+ }
+ if (!w._inDocument) {
+ w._inDocument = true;
+ renderer.container.appendChild(w.el);
+ }
+ var top = renderer.$cursorLayer.getPixelPosition(
+ { row: i, column: 0 },
+ true
+ ).top;
+ if (!w.coverLine)
+ top += config.lineHeight * this.session.getRowLineCount(w.row);
+ w.el.style.top = top - config.offset + "px";
+
+ var left = w.coverGutter ? 0 : renderer.gutterWidth;
+ if (!w.fixedWidth) left -= renderer.scrollLeft;
+ w.el.style.left = left + "px";
+
+ if (w.fullWidth && w.screenWidth) {
+ w.el.style.minWidth = config.width + 2 * config.padding + "px";
+ }
+
+ if (w.fixedWidth) {
+ w.el.style.right = renderer.scrollBar.getWidth() + "px";
+ } else {
+ w.el.style.right = "";
+ }
+ }
+ };
+ }.call(LineWidgets.prototype));
+
+ exports.LineWidgets = LineWidgets;
+ }
+);
+
+ace.define(
+ "ace/ext/error_marker",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/line_widgets",
+ "ace/lib/dom",
+ "ace/range"
+ ],
+ function(require, exports, module) {
+ "use strict";
+ var LineWidgets = require("../line_widgets").LineWidgets;
+ var dom = require("../lib/dom");
+ var Range = require("../range").Range;
+
+ function binarySearch(array, needle, comparator) {
+ var first = 0;
+ var last = array.length - 1;
+
+ while (first <= last) {
+ var mid = (first + last) >> 1;
+ var c = comparator(needle, array[mid]);
+ if (c > 0) first = mid + 1;
+ else if (c < 0) last = mid - 1;
+ else return mid;
+ }
+ return -(first + 1);
+ }
+
+ function findAnnotations(session, row, dir) {
+ var annotations = session.getAnnotations().sort(Range.comparePoints);
+ if (!annotations.length) return;
+
+ var i = binarySearch(
+ annotations,
+ { row: row, column: -1 },
+ Range.comparePoints
+ );
+ if (i < 0) i = -i - 1;
+
+ if (i >= annotations.length) i = dir > 0 ? 0 : annotations.length - 1;
+ else if (i === 0 && dir < 0) i = annotations.length - 1;
+
+ var annotation = annotations[i];
+ if (!annotation || !dir) return;
+
+ if (annotation.row === row) {
+ do {
+ annotation = annotations[(i += dir)];
+ } while (annotation && annotation.row === row);
+ if (!annotation) return annotations.slice();
+ }
+
+ var matched = [];
+ row = annotation.row;
+ do {
+ matched[dir < 0 ? "unshift" : "push"](annotation);
+ annotation = annotations[(i += dir)];
+ } while (annotation && annotation.row == row);
+ return matched.length && matched;
+ }
+
+ exports.showErrorMarker = function(editor, dir) {
+ var session = editor.session;
+ if (!session.widgetManager) {
+ session.widgetManager = new LineWidgets(session);
+ session.widgetManager.attach(editor);
+ }
+
+ var pos = editor.getCursorPosition();
+ var row = pos.row;
+ var oldWidget = session.widgetManager
+ .getWidgetsAtRow(row)
+ .filter(function(w) {
+ return w.type == "errorMarker";
+ })[0];
+ if (oldWidget) {
+ oldWidget.destroy();
+ } else {
+ row -= dir;
+ }
+ var annotations = findAnnotations(session, row, dir);
+ var gutterAnno;
+ if (annotations) {
+ var annotation = annotations[0];
+ pos.column =
+ (annotation.pos && typeof annotation.column != "number"
+ ? annotation.pos.sc
+ : annotation.column) || 0;
+ pos.row = annotation.row;
+ gutterAnno = editor.renderer.$gutterLayer.$annotations[pos.row];
+ } else if (oldWidget) {
+ return;
+ } else {
+ gutterAnno = {
+ text: ["Looks good!"],
+ className: "ace_ok"
+ };
+ }
+ editor.session.unfold(pos.row);
+ editor.selection.moveToPosition(pos);
+
+ var w = {
+ row: pos.row,
+ fixedWidth: true,
+ coverGutter: true,
+ el: dom.createElement("div"),
+ type: "errorMarker"
+ };
+ var el = w.el.appendChild(dom.createElement("div"));
+ var arrow = w.el.appendChild(dom.createElement("div"));
+ arrow.className = "error_widget_arrow " + gutterAnno.className;
+
+ var left = editor.renderer.$cursorLayer.getPixelPosition(pos).left;
+ arrow.style.left = left + editor.renderer.gutterWidth - 5 + "px";
+
+ w.el.className = "error_widget_wrapper";
+ el.className = "error_widget " + gutterAnno.className;
+ el.innerHTML = gutterAnno.text.join("
");
+
+ el.appendChild(dom.createElement("div"));
+
+ var kb = function(_, hashId, keyString) {
+ if (hashId === 0 && (keyString === "esc" || keyString === "return")) {
+ w.destroy();
+ return { command: "null" };
+ }
+ };
+
+ w.destroy = function() {
+ if (editor.$mouseHandler.isMousePressed) return;
+ editor.keyBinding.removeKeyboardHandler(kb);
+ session.widgetManager.removeLineWidget(w);
+ editor.off("changeSelection", w.destroy);
+ editor.off("changeSession", w.destroy);
+ editor.off("mouseup", w.destroy);
+ editor.off("change", w.destroy);
+ };
+
+ editor.keyBinding.addKeyboardHandler(kb);
+ editor.on("changeSelection", w.destroy);
+ editor.on("changeSession", w.destroy);
+ editor.on("mouseup", w.destroy);
+ editor.on("change", w.destroy);
+
+ editor.session.widgetManager.addLineWidget(w);
+
+ w.el.onmousedown = editor.focus.bind(editor);
+
+ editor.renderer.scrollCursorIntoView(null, 0.5, {
+ bottom: w.el.offsetHeight
+ });
+ };
+
+ dom.importCssString(
+ "\
+ .error_widget_wrapper {\
+ background: inherit;\
+ color: inherit;\
+ border:none\
+ }\
+ .error_widget {\
+ border-top: solid 2px;\
+ border-bottom: solid 2px;\
+ margin: 5px 0;\
+ padding: 10px 40px;\
+ white-space: pre-wrap;\
+ }\
+ .error_widget.ace_error, .error_widget_arrow.ace_error{\
+ border-color: #ff5a5a\
+ }\
+ .error_widget.ace_warning, .error_widget_arrow.ace_warning{\
+ border-color: #F1D817\
+ }\
+ .error_widget.ace_info, .error_widget_arrow.ace_info{\
+ border-color: #5a5a5a\
+ }\
+ .error_widget.ace_ok, .error_widget_arrow.ace_ok{\
+ border-color: #5aaa5a\
+ }\
+ .error_widget_arrow {\
+ position: absolute;\
+ border: solid 5px;\
+ border-top-color: transparent!important;\
+ border-right-color: transparent!important;\
+ border-left-color: transparent!important;\
+ top: -5px;\
+ }\
+ ",
+ ""
+ );
+ }
+);
+
+ace.define(
+ "ace/ace",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/lib/fixoldbrowsers",
+ "ace/lib/dom",
+ "ace/lib/event",
+ "ace/range",
+ "ace/editor",
+ "ace/edit_session",
+ "ace/undomanager",
+ "ace/virtual_renderer",
+ "ace/worker/worker_client",
+ "ace/keyboard/hash_handler",
+ "ace/placeholder",
+ "ace/multi_select",
+ "ace/mode/folding/fold_mode",
+ "ace/theme/textmate",
+ "ace/ext/error_marker",
+ "ace/config"
+ ],
+ function(require, exports, module) {
+ "use strict";
+
+ require("./lib/fixoldbrowsers");
+
+ var dom = require("./lib/dom");
+ var event = require("./lib/event");
+
+ var Range = require("./range").Range;
+ var Editor = require("./editor").Editor;
+ var EditSession = require("./edit_session").EditSession;
+ var UndoManager = require("./undomanager").UndoManager;
+ var Renderer = require("./virtual_renderer").VirtualRenderer;
+ require("./worker/worker_client");
+ require("./keyboard/hash_handler");
+ require("./placeholder");
+ require("./multi_select");
+ require("./mode/folding/fold_mode");
+ require("./theme/textmate");
+ require("./ext/error_marker");
+
+ exports.config = require("./config");
+ exports.require = require;
+
+ if (typeof define === "function") exports.define = define;
+ exports.edit = function(el, options) {
+ if (typeof el == "string") {
+ var _id = el;
+ el = document.getElementById(_id);
+ if (!el) throw new Error("ace.edit can't find div #" + _id);
+ }
+
+ if (el && el.env && el.env.editor instanceof Editor) return el.env.editor;
+
+ var value = "";
+ if (el && /input|textarea/i.test(el.tagName)) {
+ var oldNode = el;
+ value = oldNode.value;
+ el = dom.createElement("pre");
+ oldNode.parentNode.replaceChild(el, oldNode);
+ } else if (el) {
+ value = el.textContent;
+ el.innerHTML = "";
+ }
+
+ var doc = exports.createEditSession(value);
+
+ var editor = new Editor(new Renderer(el), doc, options);
+
+ var env = {
+ document: doc,
+ editor: editor,
+ onResize: editor.resize.bind(editor, null)
+ };
+ if (oldNode) env.textarea = oldNode;
+ event.addListener(window, "resize", env.onResize);
+ editor.on("destroy", function() {
+ event.removeListener(window, "resize", env.onResize);
+ env.editor.container.env = null; // prevent memory leak on old ie
+ });
+ editor.container.env = editor.env = env;
+ return editor;
+ };
+ exports.createEditSession = function(text, mode) {
+ var doc = new EditSession(text, mode);
+ doc.setUndoManager(new UndoManager());
+ return doc;
+ };
+ exports.Range = Range;
+ exports.Editor = Editor;
+ exports.EditSession = EditSession;
+ exports.UndoManager = UndoManager;
+ exports.VirtualRenderer = Renderer;
+ exports.version = exports.config.version;
+ }
+);
+(function() {
+ ace.require(["ace/ace"], function(a) {
+ if (a) {
+ a.config.init(true);
+ a.define = ace.define;
+ }
+ if (!window.ace) window.ace = a;
+ for (var key in a) if (a.hasOwnProperty(key)) window.ace[key] = a[key];
+ window.ace["default"] = window.ace;
+ if (typeof module == "object" && typeof exports == "object" && module) {
+ module.exports = window.ace;
+ }
+ });
+})();
diff --git a/pandora_console/include/javascript/ace/mode-json.js b/pandora_console/include/javascript/ace/mode-json.js
new file mode 100644
index 0000000000..89442986e7
--- /dev/null
+++ b/pandora_console/include/javascript/ace/mode-json.js
@@ -0,0 +1,396 @@
+ace.define(
+ "ace/mode/json_highlight_rules",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/lib/oop",
+ "ace/mode/text_highlight_rules"
+ ],
+ function(require, exports, module) {
+ "use strict";
+
+ var oop = require("../lib/oop");
+ var TextHighlightRules = require("./text_highlight_rules")
+ .TextHighlightRules;
+
+ var JsonHighlightRules = function() {
+ this.$rules = {
+ start: [
+ {
+ token: "variable", // single line
+ regex: '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)'
+ },
+ {
+ token: "string", // single line
+ regex: '"',
+ next: "string"
+ },
+ {
+ token: "constant.numeric", // hex
+ regex: "0[xX][0-9a-fA-F]+\\b"
+ },
+ {
+ token: "constant.numeric", // float
+ regex: "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
+ },
+ {
+ token: "constant.language.boolean",
+ regex: "(?:true|false)\\b"
+ },
+ {
+ token: "text", // single quoted strings are not allowed
+ regex: "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+ },
+ {
+ token: "comment", // comments are not allowed, but who cares?
+ regex: "\\/\\/.*$"
+ },
+ {
+ token: "comment.start", // comments are not allowed, but who cares?
+ regex: "\\/\\*",
+ next: "comment"
+ },
+ {
+ token: "paren.lparen",
+ regex: "[[({]"
+ },
+ {
+ token: "paren.rparen",
+ regex: "[\\])}]"
+ },
+ {
+ token: "text",
+ regex: "\\s+"
+ }
+ ],
+ string: [
+ {
+ token: "constant.language.escape",
+ regex: /\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|["\\\/bfnrt])/
+ },
+ {
+ token: "string",
+ regex: '"|$',
+ next: "start"
+ },
+ {
+ defaultToken: "string"
+ }
+ ],
+ comment: [
+ {
+ token: "comment.end", // comments are not allowed, but who cares?
+ regex: "\\*\\/",
+ next: "start"
+ },
+ {
+ defaultToken: "comment"
+ }
+ ]
+ };
+ };
+
+ oop.inherits(JsonHighlightRules, TextHighlightRules);
+
+ exports.JsonHighlightRules = JsonHighlightRules;
+ }
+);
+
+ace.define(
+ "ace/mode/matching_brace_outdent",
+ ["require", "exports", "module", "ace/range"],
+ function(require, exports, module) {
+ "use strict";
+
+ var Range = require("../range").Range;
+
+ var MatchingBraceOutdent = function() {};
+
+ (function() {
+ this.checkOutdent = function(line, input) {
+ if (!/^\s+$/.test(line)) return false;
+
+ return /^\s*\}/.test(input);
+ };
+
+ this.autoOutdent = function(doc, row) {
+ var line = doc.getLine(row);
+ var match = line.match(/^(\s*\})/);
+
+ if (!match) return 0;
+
+ var column = match[1].length;
+ var openBracePos = doc.findMatchingBracket({
+ row: row,
+ column: column
+ });
+
+ if (!openBracePos || openBracePos.row == row) return 0;
+
+ var indent = this.$getIndent(doc.getLine(openBracePos.row));
+ doc.replace(new Range(row, 0, row, column - 1), indent);
+ };
+
+ this.$getIndent = function(line) {
+ return line.match(/^\s*/)[0];
+ };
+ }.call(MatchingBraceOutdent.prototype));
+
+ exports.MatchingBraceOutdent = MatchingBraceOutdent;
+ }
+);
+
+ace.define(
+ "ace/mode/folding/cstyle",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/lib/oop",
+ "ace/range",
+ "ace/mode/folding/fold_mode"
+ ],
+ function(require, exports, module) {
+ "use strict";
+
+ var oop = require("../../lib/oop");
+ var Range = require("../../range").Range;
+ var BaseFoldMode = require("./fold_mode").FoldMode;
+
+ var FoldMode = (exports.FoldMode = function(commentRegex) {
+ if (commentRegex) {
+ this.foldingStartMarker = new RegExp(
+ this.foldingStartMarker.source.replace(
+ /\|[^|]*?$/,
+ "|" + commentRegex.start
+ )
+ );
+ this.foldingStopMarker = new RegExp(
+ this.foldingStopMarker.source.replace(
+ /\|[^|]*?$/,
+ "|" + commentRegex.end
+ )
+ );
+ }
+ });
+ oop.inherits(FoldMode, BaseFoldMode);
+
+ (function() {
+ this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+ this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+ this.singleLineBlockCommentRe = /^\s*(\/\*).*\*\/\s*$/;
+ this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+ this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+ this._getFoldWidgetBase = this.getFoldWidget;
+ this.getFoldWidget = function(session, foldStyle, row) {
+ var line = session.getLine(row);
+
+ if (this.singleLineBlockCommentRe.test(line)) {
+ if (
+ !this.startRegionRe.test(line) &&
+ !this.tripleStarBlockCommentRe.test(line)
+ )
+ return "";
+ }
+
+ var fw = this._getFoldWidgetBase(session, foldStyle, row);
+
+ if (!fw && this.startRegionRe.test(line)) return "start"; // lineCommentRegionStart
+
+ return fw;
+ };
+
+ this.getFoldWidgetRange = function(
+ session,
+ foldStyle,
+ row,
+ forceMultiline
+ ) {
+ var line = session.getLine(row);
+
+ if (this.startRegionRe.test(line))
+ return this.getCommentRegionBlock(session, line, row);
+
+ var match = line.match(this.foldingStartMarker);
+ if (match) {
+ var i = match.index;
+
+ if (match[1])
+ return this.openingBracketBlock(session, match[1], row, i);
+
+ var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+
+ if (range && !range.isMultiLine()) {
+ if (forceMultiline) {
+ range = this.getSectionRange(session, row);
+ } else if (foldStyle != "all") range = null;
+ }
+
+ return range;
+ }
+
+ if (foldStyle === "markbegin") return;
+
+ var match = line.match(this.foldingStopMarker);
+ if (match) {
+ var i = match.index + match[0].length;
+
+ if (match[1])
+ return this.closingBracketBlock(session, match[1], row, i);
+
+ return session.getCommentFoldRange(row, i, -1);
+ }
+ };
+
+ this.getSectionRange = function(session, row) {
+ var line = session.getLine(row);
+ var startIndent = line.search(/\S/);
+ var startRow = row;
+ var startColumn = line.length;
+ row = row + 1;
+ var endRow = row;
+ var maxRow = session.getLength();
+ while (++row < maxRow) {
+ line = session.getLine(row);
+ var indent = line.search(/\S/);
+ if (indent === -1) continue;
+ if (startIndent > indent) break;
+ var subRange = this.getFoldWidgetRange(session, "all", row);
+
+ if (subRange) {
+ if (subRange.start.row <= startRow) {
+ break;
+ } else if (subRange.isMultiLine()) {
+ row = subRange.end.row;
+ } else if (startIndent == indent) {
+ break;
+ }
+ }
+ endRow = row;
+ }
+
+ return new Range(
+ startRow,
+ startColumn,
+ endRow,
+ session.getLine(endRow).length
+ );
+ };
+ this.getCommentRegionBlock = function(session, line, row) {
+ var startColumn = line.search(/\s*$/);
+ var maxRow = session.getLength();
+ var startRow = row;
+
+ var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+ var depth = 1;
+ while (++row < maxRow) {
+ line = session.getLine(row);
+ var m = re.exec(line);
+ if (!m) continue;
+ if (m[1]) depth--;
+ else depth++;
+
+ if (!depth) break;
+ }
+
+ var endRow = row;
+ if (endRow > startRow) {
+ return new Range(startRow, startColumn, endRow, line.length);
+ }
+ };
+ }.call(FoldMode.prototype));
+ }
+);
+
+ace.define(
+ "ace/mode/json",
+ [
+ "require",
+ "exports",
+ "module",
+ "ace/lib/oop",
+ "ace/mode/text",
+ "ace/mode/json_highlight_rules",
+ "ace/mode/matching_brace_outdent",
+ "ace/mode/behaviour/cstyle",
+ "ace/mode/folding/cstyle",
+ "ace/worker/worker_client"
+ ],
+ function(require, exports, module) {
+ "use strict";
+
+ var oop = require("../lib/oop");
+ var TextMode = require("./text").Mode;
+ var HighlightRules = require("./json_highlight_rules").JsonHighlightRules;
+ var MatchingBraceOutdent = require("./matching_brace_outdent")
+ .MatchingBraceOutdent;
+ var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
+ var CStyleFoldMode = require("./folding/cstyle").FoldMode;
+ var WorkerClient = require("../worker/worker_client").WorkerClient;
+
+ var Mode = function() {
+ this.HighlightRules = HighlightRules;
+ this.$outdent = new MatchingBraceOutdent();
+ this.$behaviour = new CstyleBehaviour();
+ this.foldingRules = new CStyleFoldMode();
+ };
+ oop.inherits(Mode, TextMode);
+
+ (function() {
+ this.lineCommentStart = "//";
+ this.blockComment = { start: "/*", end: "*/" };
+
+ this.getNextLineIndent = function(state, line, tab) {
+ var indent = this.$getIndent(line);
+
+ if (state == "start") {
+ var match = line.match(/^.*[\{\(\[]\s*$/);
+ if (match) {
+ indent += tab;
+ }
+ }
+
+ return indent;
+ };
+
+ this.checkOutdent = function(state, line, input) {
+ return this.$outdent.checkOutdent(line, input);
+ };
+
+ this.autoOutdent = function(state, doc, row) {
+ this.$outdent.autoOutdent(doc, row);
+ };
+
+ this.createWorker = function(session) {
+ var worker = new WorkerClient(
+ ["ace"],
+ "ace/mode/json_worker",
+ "JsonWorker"
+ );
+ worker.attachToDocument(session.getDocument());
+
+ worker.on("annotate", function(e) {
+ session.setAnnotations(e.data);
+ });
+
+ worker.on("terminate", function() {
+ session.clearAnnotations();
+ });
+
+ return worker;
+ };
+
+ this.$id = "ace/mode/json";
+ }.call(Mode.prototype));
+
+ exports.Mode = Mode;
+ }
+);
+(function() {
+ ace.require(["ace/mode/json"], function(m) {
+ if (typeof module == "object" && typeof exports == "object" && module) {
+ module.exports = m;
+ }
+ });
+})();
diff --git a/pandora_console/include/javascript/ace/textmate.css b/pandora_console/include/javascript/ace/textmate.css
new file mode 100644
index 0000000000..ec2a96f4ea
--- /dev/null
+++ b/pandora_console/include/javascript/ace/textmate.css
@@ -0,0 +1,154 @@
+.ace-tm .ace_gutter {
+ background: #f0f0f0;
+ color: #333;
+}
+
+.ace-tm .ace_print-margin {
+ width: 1px;
+ background: #e8e8e8;
+}
+
+.ace-tm .ace_fold {
+ background-color: #6b72e6;
+}
+
+.ace-tm {
+ background-color: #ffffff;
+ color: black;
+}
+
+.ace-tm .ace_cursor {
+ color: black;
+}
+
+.ace-tm .ace_invisible {
+ color: rgb(191, 191, 191);
+}
+
+.ace-tm .ace_storage,
+.ace-tm .ace_keyword {
+ color: blue;
+}
+
+.ace-tm .ace_constant {
+ color: rgb(197, 6, 11);
+}
+
+.ace-tm .ace_constant.ace_buildin {
+ color: rgb(88, 72, 246);
+}
+
+.ace-tm .ace_constant.ace_language {
+ color: rgb(88, 92, 246);
+}
+
+.ace-tm .ace_constant.ace_library {
+ color: rgb(6, 150, 14);
+}
+
+.ace-tm .ace_invalid {
+ background-color: rgba(255, 0, 0, 0.1);
+ color: red;
+}
+
+.ace-tm .ace_support.ace_function {
+ color: rgb(60, 76, 114);
+}
+
+.ace-tm .ace_support.ace_constant {
+ color: rgb(6, 150, 14);
+}
+
+.ace-tm .ace_support.ace_type,
+.ace-tm .ace_support.ace_class {
+ color: rgb(109, 121, 222);
+}
+
+.ace-tm .ace_keyword.ace_operator {
+ color: rgb(104, 118, 135);
+}
+
+.ace-tm .ace_string {
+ color: rgb(3, 106, 7);
+}
+
+.ace-tm .ace_comment {
+ color: rgb(76, 136, 107);
+}
+
+.ace-tm .ace_comment.ace_doc {
+ color: rgb(0, 102, 255);
+}
+
+.ace-tm .ace_comment.ace_doc.ace_tag {
+ color: rgb(128, 159, 191);
+}
+
+.ace-tm .ace_constant.ace_numeric {
+ color: rgb(0, 0, 205);
+}
+
+.ace-tm .ace_variable {
+ color: rgb(49, 132, 149);
+}
+
+.ace-tm .ace_xml-pe {
+ color: rgb(104, 104, 91);
+}
+
+.ace-tm .ace_entity.ace_name.ace_function {
+ color: #0000a2;
+}
+
+.ace-tm .ace_heading {
+ color: rgb(12, 7, 255);
+}
+
+.ace-tm .ace_list {
+ color: rgb(185, 6, 144);
+}
+
+.ace-tm .ace_meta.ace_tag {
+ color: rgb(0, 22, 142);
+}
+
+.ace-tm .ace_string.ace_regex {
+ color: rgb(255, 0, 0);
+}
+
+.ace-tm .ace_marker-layer .ace_selection {
+ background: rgb(181, 213, 255);
+}
+.ace-tm.ace_multiselect .ace_selection.ace_start {
+ box-shadow: 0 0 3px 0px white;
+}
+.ace-tm .ace_marker-layer .ace_step {
+ background: rgb(252, 255, 0);
+}
+
+.ace-tm .ace_marker-layer .ace_stack {
+ background: rgb(164, 229, 101);
+}
+
+.ace-tm .ace_marker-layer .ace_bracket {
+ margin: -1px 0 0 -1px;
+ border: 1px solid rgb(192, 192, 192);
+}
+
+.ace-tm .ace_marker-layer .ace_active-line {
+ background: rgba(0, 0, 0, 0.07);
+}
+
+.ace-tm .ace_gutter-active-line {
+ background-color: #dcdcdc;
+}
+
+.ace-tm .ace_marker-layer .ace_selected-word {
+ background: rgb(250, 250, 255);
+ border: 1px solid rgb(200, 200, 250);
+}
+
+.ace-tm .ace_indent-guide {
+ background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==")
+ right repeat-y;
+}
diff --git a/pandora_console/include/javascript/ace/textmate.js b/pandora_console/include/javascript/ace/textmate.js
new file mode 100644
index 0000000000..7ad45d8da2
--- /dev/null
+++ b/pandora_console/include/javascript/ace/textmate.js
@@ -0,0 +1,41 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Distributed under the BSD license:
+ *
+ * Copyright (c) 2010, Ajax.org B.V.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Ajax.org B.V. nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define(function(require, exports, module) {
+ "use strict";
+
+ exports.isDark = false;
+ exports.cssClass = "ace-tm";
+ exports.cssText = require("../requirejs/text!./textmate.css");
+ exports.$id = "ace/theme/textmate";
+
+ var dom = require("../lib/dom");
+ dom.importCssString(exports.cssText, exports.cssClass);
+});
diff --git a/pandora_console/include/javascript/ace/worker-json.js b/pandora_console/include/javascript/ace/worker-json.js
new file mode 100644
index 0000000000..998180b778
--- /dev/null
+++ b/pandora_console/include/javascript/ace/worker-json.js
@@ -0,0 +1,2468 @@
+"no use strict";
+!(function(window) {
+ if (typeof window.window != "undefined" && window.document) return;
+ if (window.require && window.define) return;
+
+ if (!window.console) {
+ window.console = function() {
+ var msgs = Array.prototype.slice.call(arguments, 0);
+ postMessage({ type: "log", data: msgs });
+ };
+ window.console.error = window.console.warn = window.console.log = window.console.trace =
+ window.console;
+ }
+ window.window = window;
+ window.ace = window;
+
+ window.onerror = function(message, file, line, col, err) {
+ postMessage({
+ type: "error",
+ data: {
+ message: message,
+ data: err.data,
+ file: file,
+ line: line,
+ col: col,
+ stack: err.stack
+ }
+ });
+ };
+
+ window.normalizeModule = function(parentId, moduleName) {
+ // normalize plugin requires
+ if (moduleName.indexOf("!") !== -1) {
+ var chunks = moduleName.split("!");
+ return (
+ window.normalizeModule(parentId, chunks[0]) +
+ "!" +
+ window.normalizeModule(parentId, chunks[1])
+ );
+ }
+ // normalize relative requires
+ if (moduleName.charAt(0) == ".") {
+ var base = parentId
+ .split("/")
+ .slice(0, -1)
+ .join("/");
+ moduleName = (base ? base + "/" : "") + moduleName;
+
+ while (moduleName.indexOf(".") !== -1 && previous != moduleName) {
+ var previous = moduleName;
+ moduleName = moduleName
+ .replace(/^\.\//, "")
+ .replace(/\/\.\//, "/")
+ .replace(/[^\/]+\/\.\.\//, "");
+ }
+ }
+
+ return moduleName;
+ };
+
+ window.require = function require(parentId, id) {
+ if (!id) {
+ id = parentId;
+ parentId = null;
+ }
+ if (!id.charAt)
+ throw new Error(
+ "worker.js require() accepts only (parentId, id) as arguments"
+ );
+
+ id = window.normalizeModule(parentId, id);
+
+ var module = window.require.modules[id];
+ if (module) {
+ if (!module.initialized) {
+ module.initialized = true;
+ module.exports = module.factory().exports;
+ }
+ return module.exports;
+ }
+
+ if (!window.require.tlns) return console.log("unable to load " + id);
+
+ var path = resolveModuleId(id, window.require.tlns);
+ if (path.slice(-3) != ".js") path += ".js";
+
+ window.require.id = id;
+ window.require.modules[id] = {}; // prevent infinite loop on broken modules
+ importScripts(path);
+ return window.require(parentId, id);
+ };
+ function resolveModuleId(id, paths) {
+ var testPath = id,
+ tail = "";
+ while (testPath) {
+ var alias = paths[testPath];
+ if (typeof alias == "string") {
+ return alias + tail;
+ } else if (alias) {
+ return (
+ alias.location.replace(/\/*$/, "/") +
+ (tail || alias.main || alias.name)
+ );
+ } else if (alias === false) {
+ return "";
+ }
+ var i = testPath.lastIndexOf("/");
+ if (i === -1) break;
+ tail = testPath.substr(i) + tail;
+ testPath = testPath.slice(0, i);
+ }
+ return id;
+ }
+ window.require.modules = {};
+ window.require.tlns = {};
+
+ window.define = function(id, deps, factory) {
+ if (arguments.length == 2) {
+ factory = deps;
+ if (typeof id != "string") {
+ deps = id;
+ id = window.require.id;
+ }
+ } else if (arguments.length == 1) {
+ factory = id;
+ deps = [];
+ id = window.require.id;
+ }
+
+ if (typeof factory != "function") {
+ window.require.modules[id] = {
+ exports: factory,
+ initialized: true
+ };
+ return;
+ }
+
+ if (!deps.length)
+ // If there is no dependencies, we inject "require", "exports" and
+ // "module" as dependencies, to provide CommonJS compatibility.
+ deps = ["require", "exports", "module"];
+
+ var req = function(childId) {
+ return window.require(id, childId);
+ };
+
+ window.require.modules[id] = {
+ exports: {},
+ factory: function() {
+ var module = this;
+ var returnExports = factory.apply(
+ this,
+ deps.slice(0, factory.length).map(function(dep) {
+ switch (dep) {
+ // Because "require", "exports" and "module" aren't actual
+ // dependencies, we must handle them seperately.
+ case "require":
+ return req;
+ case "exports":
+ return module.exports;
+ case "module":
+ return module;
+ // But for all other dependencies, we can just go ahead and
+ // require them.
+ default:
+ return req(dep);
+ }
+ })
+ );
+ if (returnExports) module.exports = returnExports;
+ return module;
+ }
+ };
+ };
+ window.define.amd = {};
+ require.tlns = {};
+ window.initBaseUrls = function initBaseUrls(topLevelNamespaces) {
+ for (var i in topLevelNamespaces) require.tlns[i] = topLevelNamespaces[i];
+ };
+
+ window.initSender = function initSender() {
+ var EventEmitter = window.require("ace/lib/event_emitter").EventEmitter;
+ var oop = window.require("ace/lib/oop");
+
+ var Sender = function() {};
+
+ (function() {
+ oop.implement(this, EventEmitter);
+
+ this.callback = function(data, callbackId) {
+ postMessage({
+ type: "call",
+ id: callbackId,
+ data: data
+ });
+ };
+
+ this.emit = function(name, data) {
+ postMessage({
+ type: "event",
+ name: name,
+ data: data
+ });
+ };
+ }.call(Sender.prototype));
+
+ return new Sender();
+ };
+
+ var main = (window.main = null);
+ var sender = (window.sender = null);
+
+ window.onmessage = function(e) {
+ var msg = e.data;
+ if (msg.event && sender) {
+ sender._signal(msg.event, msg.data);
+ } else if (msg.command) {
+ if (main[msg.command]) main[msg.command].apply(main, msg.args);
+ else if (window[msg.command]) window[msg.command].apply(window, msg.args);
+ else throw new Error("Unknown command:" + msg.command);
+ } else if (msg.init) {
+ window.initBaseUrls(msg.tlns);
+ require("ace/lib/es5-shim");
+ sender = window.sender = window.initSender();
+ var clazz = require(msg.module)[msg.classname];
+ main = window.main = new clazz(sender);
+ }
+ };
+})(this);
+
+ace.define("ace/lib/oop", [], function(require, exports, module) {
+ "use strict";
+
+ exports.inherits = function(ctor, superCtor) {
+ ctor.super_ = superCtor;
+ ctor.prototype = Object.create(superCtor.prototype, {
+ constructor: {
+ value: ctor,
+ enumerable: false,
+ writable: true,
+ configurable: true
+ }
+ });
+ };
+
+ exports.mixin = function(obj, mixin) {
+ for (var key in mixin) {
+ obj[key] = mixin[key];
+ }
+ return obj;
+ };
+
+ exports.implement = function(proto, mixin) {
+ exports.mixin(proto, mixin);
+ };
+});
+
+ace.define("ace/range", [], function(require, exports, module) {
+ "use strict";
+ var comparePoints = function(p1, p2) {
+ return p1.row - p2.row || p1.column - p2.column;
+ };
+ var Range = function(startRow, startColumn, endRow, endColumn) {
+ this.start = {
+ row: startRow,
+ column: startColumn
+ };
+
+ this.end = {
+ row: endRow,
+ column: endColumn
+ };
+ };
+
+ (function() {
+ this.isEqual = function(range) {
+ return (
+ this.start.row === range.start.row &&
+ this.end.row === range.end.row &&
+ this.start.column === range.start.column &&
+ this.end.column === range.end.column
+ );
+ };
+ this.toString = function() {
+ return (
+ "Range: [" +
+ this.start.row +
+ "/" +
+ this.start.column +
+ "] -> [" +
+ this.end.row +
+ "/" +
+ this.end.column +
+ "]"
+ );
+ };
+
+ this.contains = function(row, column) {
+ return this.compare(row, column) == 0;
+ };
+ this.compareRange = function(range) {
+ var cmp,
+ end = range.end,
+ start = range.start;
+
+ cmp = this.compare(end.row, end.column);
+ if (cmp == 1) {
+ cmp = this.compare(start.row, start.column);
+ if (cmp == 1) {
+ return 2;
+ } else if (cmp == 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+ } else if (cmp == -1) {
+ return -2;
+ } else {
+ cmp = this.compare(start.row, start.column);
+ if (cmp == -1) {
+ return -1;
+ } else if (cmp == 1) {
+ return 42;
+ } else {
+ return 0;
+ }
+ }
+ };
+ this.comparePoint = function(p) {
+ return this.compare(p.row, p.column);
+ };
+ this.containsRange = function(range) {
+ return (
+ this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0
+ );
+ };
+ this.intersects = function(range) {
+ var cmp = this.compareRange(range);
+ return cmp == -1 || cmp == 0 || cmp == 1;
+ };
+ this.isEnd = function(row, column) {
+ return this.end.row == row && this.end.column == column;
+ };
+ this.isStart = function(row, column) {
+ return this.start.row == row && this.start.column == column;
+ };
+ this.setStart = function(row, column) {
+ if (typeof row == "object") {
+ this.start.column = row.column;
+ this.start.row = row.row;
+ } else {
+ this.start.row = row;
+ this.start.column = column;
+ }
+ };
+ this.setEnd = function(row, column) {
+ if (typeof row == "object") {
+ this.end.column = row.column;
+ this.end.row = row.row;
+ } else {
+ this.end.row = row;
+ this.end.column = column;
+ }
+ };
+ this.inside = function(row, column) {
+ if (this.compare(row, column) == 0) {
+ if (this.isEnd(row, column) || this.isStart(row, column)) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+ return false;
+ };
+ this.insideStart = function(row, column) {
+ if (this.compare(row, column) == 0) {
+ if (this.isEnd(row, column)) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+ return false;
+ };
+ this.insideEnd = function(row, column) {
+ if (this.compare(row, column) == 0) {
+ if (this.isStart(row, column)) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+ return false;
+ };
+ this.compare = function(row, column) {
+ if (!this.isMultiLine()) {
+ if (row === this.start.row) {
+ return column < this.start.column
+ ? -1
+ : column > this.end.column
+ ? 1
+ : 0;
+ }
+ }
+
+ if (row < this.start.row) return -1;
+
+ if (row > this.end.row) return 1;
+
+ if (this.start.row === row) return column >= this.start.column ? 0 : -1;
+
+ if (this.end.row === row) return column <= this.end.column ? 0 : 1;
+
+ return 0;
+ };
+ this.compareStart = function(row, column) {
+ if (this.start.row == row && this.start.column == column) {
+ return -1;
+ } else {
+ return this.compare(row, column);
+ }
+ };
+ this.compareEnd = function(row, column) {
+ if (this.end.row == row && this.end.column == column) {
+ return 1;
+ } else {
+ return this.compare(row, column);
+ }
+ };
+ this.compareInside = function(row, column) {
+ if (this.end.row == row && this.end.column == column) {
+ return 1;
+ } else if (this.start.row == row && this.start.column == column) {
+ return -1;
+ } else {
+ return this.compare(row, column);
+ }
+ };
+ this.clipRows = function(firstRow, lastRow) {
+ if (this.end.row > lastRow) var end = { row: lastRow + 1, column: 0 };
+ else if (this.end.row < firstRow) var end = { row: firstRow, column: 0 };
+
+ if (this.start.row > lastRow) var start = { row: lastRow + 1, column: 0 };
+ else if (this.start.row < firstRow)
+ var start = { row: firstRow, column: 0 };
+
+ return Range.fromPoints(start || this.start, end || this.end);
+ };
+ this.extend = function(row, column) {
+ var cmp = this.compare(row, column);
+
+ if (cmp == 0) return this;
+ else if (cmp == -1) var start = { row: row, column: column };
+ else var end = { row: row, column: column };
+
+ return Range.fromPoints(start || this.start, end || this.end);
+ };
+
+ this.isEmpty = function() {
+ return (
+ this.start.row === this.end.row && this.start.column === this.end.column
+ );
+ };
+ this.isMultiLine = function() {
+ return this.start.row !== this.end.row;
+ };
+ this.clone = function() {
+ return Range.fromPoints(this.start, this.end);
+ };
+ this.collapseRows = function() {
+ if (this.end.column == 0)
+ return new Range(
+ this.start.row,
+ 0,
+ Math.max(this.start.row, this.end.row - 1),
+ 0
+ );
+ else return new Range(this.start.row, 0, this.end.row, 0);
+ };
+ this.toScreenRange = function(session) {
+ var screenPosStart = session.documentToScreenPosition(this.start);
+ var screenPosEnd = session.documentToScreenPosition(this.end);
+
+ return new Range(
+ screenPosStart.row,
+ screenPosStart.column,
+ screenPosEnd.row,
+ screenPosEnd.column
+ );
+ };
+ this.moveBy = function(row, column) {
+ this.start.row += row;
+ this.start.column += column;
+ this.end.row += row;
+ this.end.column += column;
+ };
+ }.call(Range.prototype));
+ Range.fromPoints = function(start, end) {
+ return new Range(start.row, start.column, end.row, end.column);
+ };
+ Range.comparePoints = comparePoints;
+
+ Range.comparePoints = function(p1, p2) {
+ return p1.row - p2.row || p1.column - p2.column;
+ };
+
+ exports.Range = Range;
+});
+
+ace.define("ace/apply_delta", [], function(require, exports, module) {
+ "use strict";
+
+ function throwDeltaError(delta, errorText) {
+ console.log("Invalid Delta:", delta);
+ throw "Invalid Delta: " + errorText;
+ }
+
+ function positionInDocument(docLines, position) {
+ return (
+ position.row >= 0 &&
+ position.row < docLines.length &&
+ position.column >= 0 &&
+ position.column <= docLines[position.row].length
+ );
+ }
+
+ function validateDelta(docLines, delta) {
+ if (delta.action != "insert" && delta.action != "remove")
+ throwDeltaError(delta, "delta.action must be 'insert' or 'remove'");
+ if (!(delta.lines instanceof Array))
+ throwDeltaError(delta, "delta.lines must be an Array");
+ if (!delta.start || !delta.end)
+ throwDeltaError(delta, "delta.start/end must be an present");
+ var start = delta.start;
+ if (!positionInDocument(docLines, delta.start))
+ throwDeltaError(delta, "delta.start must be contained in document");
+ var end = delta.end;
+ if (delta.action == "remove" && !positionInDocument(docLines, end))
+ throwDeltaError(
+ delta,
+ "delta.end must contained in document for 'remove' actions"
+ );
+ var numRangeRows = end.row - start.row;
+ var numRangeLastLineChars =
+ end.column - (numRangeRows == 0 ? start.column : 0);
+ if (
+ numRangeRows != delta.lines.length - 1 ||
+ delta.lines[numRangeRows].length != numRangeLastLineChars
+ )
+ throwDeltaError(delta, "delta.range must match delta lines");
+ }
+
+ exports.applyDelta = function(docLines, delta, doNotValidate) {
+ var row = delta.start.row;
+ var startColumn = delta.start.column;
+ var line = docLines[row] || "";
+ switch (delta.action) {
+ case "insert":
+ var lines = delta.lines;
+ if (lines.length === 1) {
+ docLines[row] =
+ line.substring(0, startColumn) +
+ delta.lines[0] +
+ line.substring(startColumn);
+ } else {
+ var args = [row, 1].concat(delta.lines);
+ docLines.splice.apply(docLines, args);
+ docLines[row] = line.substring(0, startColumn) + docLines[row];
+ docLines[row + delta.lines.length - 1] += line.substring(startColumn);
+ }
+ break;
+ case "remove":
+ var endColumn = delta.end.column;
+ var endRow = delta.end.row;
+ if (row === endRow) {
+ docLines[row] =
+ line.substring(0, startColumn) + line.substring(endColumn);
+ } else {
+ docLines.splice(
+ row,
+ endRow - row + 1,
+ line.substring(0, startColumn) +
+ docLines[endRow].substring(endColumn)
+ );
+ }
+ break;
+ }
+ };
+});
+
+ace.define("ace/lib/event_emitter", [], function(require, exports, module) {
+ "use strict";
+
+ var EventEmitter = {};
+ var stopPropagation = function() {
+ this.propagationStopped = true;
+ };
+ var preventDefault = function() {
+ this.defaultPrevented = true;
+ };
+
+ EventEmitter._emit = EventEmitter._dispatchEvent = function(eventName, e) {
+ this._eventRegistry || (this._eventRegistry = {});
+ this._defaultHandlers || (this._defaultHandlers = {});
+
+ var listeners = this._eventRegistry[eventName] || [];
+ var defaultHandler = this._defaultHandlers[eventName];
+ if (!listeners.length && !defaultHandler) return;
+
+ if (typeof e != "object" || !e) e = {};
+
+ if (!e.type) e.type = eventName;
+ if (!e.stopPropagation) e.stopPropagation = stopPropagation;
+ if (!e.preventDefault) e.preventDefault = preventDefault;
+
+ listeners = listeners.slice();
+ for (var i = 0; i < listeners.length; i++) {
+ listeners[i](e, this);
+ if (e.propagationStopped) break;
+ }
+
+ if (defaultHandler && !e.defaultPrevented) return defaultHandler(e, this);
+ };
+
+ EventEmitter._signal = function(eventName, e) {
+ var listeners = (this._eventRegistry || {})[eventName];
+ if (!listeners) return;
+ listeners = listeners.slice();
+ for (var i = 0; i < listeners.length; i++) listeners[i](e, this);
+ };
+
+ EventEmitter.once = function(eventName, callback) {
+ var _self = this;
+ this.on(eventName, function newCallback() {
+ _self.off(eventName, newCallback);
+ callback.apply(null, arguments);
+ });
+ if (!callback) {
+ return new Promise(function(resolve) {
+ callback = resolve;
+ });
+ }
+ };
+
+ EventEmitter.setDefaultHandler = function(eventName, callback) {
+ var handlers = this._defaultHandlers;
+ if (!handlers) handlers = this._defaultHandlers = { _disabled_: {} };
+
+ if (handlers[eventName]) {
+ var old = handlers[eventName];
+ var disabled = handlers._disabled_[eventName];
+ if (!disabled) handlers._disabled_[eventName] = disabled = [];
+ disabled.push(old);
+ var i = disabled.indexOf(callback);
+ if (i != -1) disabled.splice(i, 1);
+ }
+ handlers[eventName] = callback;
+ };
+ EventEmitter.removeDefaultHandler = function(eventName, callback) {
+ var handlers = this._defaultHandlers;
+ if (!handlers) return;
+ var disabled = handlers._disabled_[eventName];
+
+ if (handlers[eventName] == callback) {
+ if (disabled) this.setDefaultHandler(eventName, disabled.pop());
+ } else if (disabled) {
+ var i = disabled.indexOf(callback);
+ if (i != -1) disabled.splice(i, 1);
+ }
+ };
+
+ EventEmitter.on = EventEmitter.addEventListener = function(
+ eventName,
+ callback,
+ capturing
+ ) {
+ this._eventRegistry = this._eventRegistry || {};
+
+ var listeners = this._eventRegistry[eventName];
+ if (!listeners) listeners = this._eventRegistry[eventName] = [];
+
+ if (listeners.indexOf(callback) == -1)
+ listeners[capturing ? "unshift" : "push"](callback);
+ return callback;
+ };
+
+ EventEmitter.off = EventEmitter.removeListener = EventEmitter.removeEventListener = function(
+ eventName,
+ callback
+ ) {
+ this._eventRegistry = this._eventRegistry || {};
+
+ var listeners = this._eventRegistry[eventName];
+ if (!listeners) return;
+
+ var index = listeners.indexOf(callback);
+ if (index !== -1) listeners.splice(index, 1);
+ };
+
+ EventEmitter.removeAllListeners = function(eventName) {
+ if (!eventName) this._eventRegistry = this._defaultHandlers = undefined;
+ if (this._eventRegistry) this._eventRegistry[eventName] = undefined;
+ if (this._defaultHandlers) this._defaultHandlers[eventName] = undefined;
+ };
+
+ exports.EventEmitter = EventEmitter;
+});
+
+ace.define("ace/anchor", [], function(require, exports, module) {
+ "use strict";
+
+ var oop = require("./lib/oop");
+ var EventEmitter = require("./lib/event_emitter").EventEmitter;
+
+ var Anchor = (exports.Anchor = function(doc, row, column) {
+ this.$onChange = this.onChange.bind(this);
+ this.attach(doc);
+
+ if (typeof column == "undefined") this.setPosition(row.row, row.column);
+ else this.setPosition(row, column);
+ });
+
+ (function() {
+ oop.implement(this, EventEmitter);
+ this.getPosition = function() {
+ return this.$clipPositionToDocument(this.row, this.column);
+ };
+ this.getDocument = function() {
+ return this.document;
+ };
+ this.$insertRight = false;
+ this.onChange = function(delta) {
+ if (delta.start.row == delta.end.row && delta.start.row != this.row)
+ return;
+
+ if (delta.start.row > this.row) return;
+
+ var point = $getTransformedPoint(
+ delta,
+ { row: this.row, column: this.column },
+ this.$insertRight
+ );
+ this.setPosition(point.row, point.column, true);
+ };
+
+ function $pointsInOrder(point1, point2, equalPointsInOrder) {
+ var bColIsAfter = equalPointsInOrder
+ ? point1.column <= point2.column
+ : point1.column < point2.column;
+ return (
+ point1.row < point2.row || (point1.row == point2.row && bColIsAfter)
+ );
+ }
+
+ function $getTransformedPoint(delta, point, moveIfEqual) {
+ var deltaIsInsert = delta.action == "insert";
+ var deltaRowShift =
+ (deltaIsInsert ? 1 : -1) * (delta.end.row - delta.start.row);
+ var deltaColShift =
+ (deltaIsInsert ? 1 : -1) * (delta.end.column - delta.start.column);
+ var deltaStart = delta.start;
+ var deltaEnd = deltaIsInsert ? deltaStart : delta.end; // Collapse insert range.
+ if ($pointsInOrder(point, deltaStart, moveIfEqual)) {
+ return {
+ row: point.row,
+ column: point.column
+ };
+ }
+ if ($pointsInOrder(deltaEnd, point, !moveIfEqual)) {
+ return {
+ row: point.row + deltaRowShift,
+ column: point.column + (point.row == deltaEnd.row ? deltaColShift : 0)
+ };
+ }
+
+ return {
+ row: deltaStart.row,
+ column: deltaStart.column
+ };
+ }
+ this.setPosition = function(row, column, noClip) {
+ var pos;
+ if (noClip) {
+ pos = {
+ row: row,
+ column: column
+ };
+ } else {
+ pos = this.$clipPositionToDocument(row, column);
+ }
+
+ if (this.row == pos.row && this.column == pos.column) return;
+
+ var old = {
+ row: this.row,
+ column: this.column
+ };
+
+ this.row = pos.row;
+ this.column = pos.column;
+ this._signal("change", {
+ old: old,
+ value: pos
+ });
+ };
+ this.detach = function() {
+ this.document.off("change", this.$onChange);
+ };
+ this.attach = function(doc) {
+ this.document = doc || this.document;
+ this.document.on("change", this.$onChange);
+ };
+ this.$clipPositionToDocument = function(row, column) {
+ var pos = {};
+
+ if (row >= this.document.getLength()) {
+ pos.row = Math.max(0, this.document.getLength() - 1);
+ pos.column = this.document.getLine(pos.row).length;
+ } else if (row < 0) {
+ pos.row = 0;
+ pos.column = 0;
+ } else {
+ pos.row = row;
+ pos.column = Math.min(
+ this.document.getLine(pos.row).length,
+ Math.max(0, column)
+ );
+ }
+
+ if (column < 0) pos.column = 0;
+
+ return pos;
+ };
+ }.call(Anchor.prototype));
+});
+
+ace.define("ace/document", [], function(require, exports, module) {
+ "use strict";
+
+ var oop = require("./lib/oop");
+ var applyDelta = require("./apply_delta").applyDelta;
+ var EventEmitter = require("./lib/event_emitter").EventEmitter;
+ var Range = require("./range").Range;
+ var Anchor = require("./anchor").Anchor;
+
+ var Document = function(textOrLines) {
+ this.$lines = [""];
+ if (textOrLines.length === 0) {
+ this.$lines = [""];
+ } else if (Array.isArray(textOrLines)) {
+ this.insertMergedLines({ row: 0, column: 0 }, textOrLines);
+ } else {
+ this.insert({ row: 0, column: 0 }, textOrLines);
+ }
+ };
+
+ (function() {
+ oop.implement(this, EventEmitter);
+ this.setValue = function(text) {
+ var len = this.getLength() - 1;
+ this.remove(new Range(0, 0, len, this.getLine(len).length));
+ this.insert({ row: 0, column: 0 }, text);
+ };
+ this.getValue = function() {
+ return this.getAllLines().join(this.getNewLineCharacter());
+ };
+ this.createAnchor = function(row, column) {
+ return new Anchor(this, row, column);
+ };
+ if ("aaa".split(/a/).length === 0) {
+ this.$split = function(text) {
+ return text.replace(/\r\n|\r/g, "\n").split("\n");
+ };
+ } else {
+ this.$split = function(text) {
+ return text.split(/\r\n|\r|\n/);
+ };
+ }
+
+ this.$detectNewLine = function(text) {
+ var match = text.match(/^.*?(\r\n|\r|\n)/m);
+ this.$autoNewLine = match ? match[1] : "\n";
+ this._signal("changeNewLineMode");
+ };
+ this.getNewLineCharacter = function() {
+ switch (this.$newLineMode) {
+ case "windows":
+ return "\r\n";
+ case "unix":
+ return "\n";
+ default:
+ return this.$autoNewLine || "\n";
+ }
+ };
+
+ this.$autoNewLine = "";
+ this.$newLineMode = "auto";
+ this.setNewLineMode = function(newLineMode) {
+ if (this.$newLineMode === newLineMode) return;
+
+ this.$newLineMode = newLineMode;
+ this._signal("changeNewLineMode");
+ };
+ this.getNewLineMode = function() {
+ return this.$newLineMode;
+ };
+ this.isNewLine = function(text) {
+ return text == "\r\n" || text == "\r" || text == "\n";
+ };
+ this.getLine = function(row) {
+ return this.$lines[row] || "";
+ };
+ this.getLines = function(firstRow, lastRow) {
+ return this.$lines.slice(firstRow, lastRow + 1);
+ };
+ this.getAllLines = function() {
+ return this.getLines(0, this.getLength());
+ };
+ this.getLength = function() {
+ return this.$lines.length;
+ };
+ this.getTextRange = function(range) {
+ return this.getLinesForRange(range).join(this.getNewLineCharacter());
+ };
+ this.getLinesForRange = function(range) {
+ var lines;
+ if (range.start.row === range.end.row) {
+ lines = [
+ this.getLine(range.start.row).substring(
+ range.start.column,
+ range.end.column
+ )
+ ];
+ } else {
+ lines = this.getLines(range.start.row, range.end.row);
+ lines[0] = (lines[0] || "").substring(range.start.column);
+ var l = lines.length - 1;
+ if (range.end.row - range.start.row == l)
+ lines[l] = lines[l].substring(0, range.end.column);
+ }
+ return lines;
+ };
+ this.insertLines = function(row, lines) {
+ console.warn(
+ "Use of document.insertLines is deprecated. Use the insertFullLines method instead."
+ );
+ return this.insertFullLines(row, lines);
+ };
+ this.removeLines = function(firstRow, lastRow) {
+ console.warn(
+ "Use of document.removeLines is deprecated. Use the removeFullLines method instead."
+ );
+ return this.removeFullLines(firstRow, lastRow);
+ };
+ this.insertNewLine = function(position) {
+ console.warn(
+ "Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead."
+ );
+ return this.insertMergedLines(position, ["", ""]);
+ };
+ this.insert = function(position, text) {
+ if (this.getLength() <= 1) this.$detectNewLine(text);
+
+ return this.insertMergedLines(position, this.$split(text));
+ };
+ this.insertInLine = function(position, text) {
+ var start = this.clippedPos(position.row, position.column);
+ var end = this.pos(position.row, position.column + text.length);
+
+ this.applyDelta(
+ {
+ start: start,
+ end: end,
+ action: "insert",
+ lines: [text]
+ },
+ true
+ );
+
+ return this.clonePos(end);
+ };
+
+ this.clippedPos = function(row, column) {
+ var length = this.getLength();
+ if (row === undefined) {
+ row = length;
+ } else if (row < 0) {
+ row = 0;
+ } else if (row >= length) {
+ row = length - 1;
+ column = undefined;
+ }
+ var line = this.getLine(row);
+ if (column == undefined) column = line.length;
+ column = Math.min(Math.max(column, 0), line.length);
+ return { row: row, column: column };
+ };
+
+ this.clonePos = function(pos) {
+ return { row: pos.row, column: pos.column };
+ };
+
+ this.pos = function(row, column) {
+ return { row: row, column: column };
+ };
+
+ this.$clipPosition = function(position) {
+ var length = this.getLength();
+ if (position.row >= length) {
+ position.row = Math.max(0, length - 1);
+ position.column = this.getLine(length - 1).length;
+ } else {
+ position.row = Math.max(0, position.row);
+ position.column = Math.min(
+ Math.max(position.column, 0),
+ this.getLine(position.row).length
+ );
+ }
+ return position;
+ };
+ this.insertFullLines = function(row, lines) {
+ row = Math.min(Math.max(row, 0), this.getLength());
+ var column = 0;
+ if (row < this.getLength()) {
+ lines = lines.concat([""]);
+ column = 0;
+ } else {
+ lines = [""].concat(lines);
+ row--;
+ column = this.$lines[row].length;
+ }
+ this.insertMergedLines({ row: row, column: column }, lines);
+ };
+ this.insertMergedLines = function(position, lines) {
+ var start = this.clippedPos(position.row, position.column);
+ var end = {
+ row: start.row + lines.length - 1,
+ column:
+ (lines.length == 1 ? start.column : 0) +
+ lines[lines.length - 1].length
+ };
+
+ this.applyDelta({
+ start: start,
+ end: end,
+ action: "insert",
+ lines: lines
+ });
+
+ return this.clonePos(end);
+ };
+ this.remove = function(range) {
+ var start = this.clippedPos(range.start.row, range.start.column);
+ var end = this.clippedPos(range.end.row, range.end.column);
+ this.applyDelta({
+ start: start,
+ end: end,
+ action: "remove",
+ lines: this.getLinesForRange({ start: start, end: end })
+ });
+ return this.clonePos(start);
+ };
+ this.removeInLine = function(row, startColumn, endColumn) {
+ var start = this.clippedPos(row, startColumn);
+ var end = this.clippedPos(row, endColumn);
+
+ this.applyDelta(
+ {
+ start: start,
+ end: end,
+ action: "remove",
+ lines: this.getLinesForRange({ start: start, end: end })
+ },
+ true
+ );
+
+ return this.clonePos(start);
+ };
+ this.removeFullLines = function(firstRow, lastRow) {
+ firstRow = Math.min(Math.max(0, firstRow), this.getLength() - 1);
+ lastRow = Math.min(Math.max(0, lastRow), this.getLength() - 1);
+ var deleteFirstNewLine = lastRow == this.getLength() - 1 && firstRow > 0;
+ var deleteLastNewLine = lastRow < this.getLength() - 1;
+ var startRow = deleteFirstNewLine ? firstRow - 1 : firstRow;
+ var startCol = deleteFirstNewLine ? this.getLine(startRow).length : 0;
+ var endRow = deleteLastNewLine ? lastRow + 1 : lastRow;
+ var endCol = deleteLastNewLine ? 0 : this.getLine(endRow).length;
+ var range = new Range(startRow, startCol, endRow, endCol);
+ var deletedLines = this.$lines.slice(firstRow, lastRow + 1);
+
+ this.applyDelta({
+ start: range.start,
+ end: range.end,
+ action: "remove",
+ lines: this.getLinesForRange(range)
+ });
+ return deletedLines;
+ };
+ this.removeNewLine = function(row) {
+ if (row < this.getLength() - 1 && row >= 0) {
+ this.applyDelta({
+ start: this.pos(row, this.getLine(row).length),
+ end: this.pos(row + 1, 0),
+ action: "remove",
+ lines: ["", ""]
+ });
+ }
+ };
+ this.replace = function(range, text) {
+ if (!(range instanceof Range))
+ range = Range.fromPoints(range.start, range.end);
+ if (text.length === 0 && range.isEmpty()) return range.start;
+ if (text == this.getTextRange(range)) return range.end;
+
+ this.remove(range);
+ var end;
+ if (text) {
+ end = this.insert(range.start, text);
+ } else {
+ end = range.start;
+ }
+
+ return end;
+ };
+ this.applyDeltas = function(deltas) {
+ for (var i = 0; i < deltas.length; i++) {
+ this.applyDelta(deltas[i]);
+ }
+ };
+ this.revertDeltas = function(deltas) {
+ for (var i = deltas.length - 1; i >= 0; i--) {
+ this.revertDelta(deltas[i]);
+ }
+ };
+ this.applyDelta = function(delta, doNotValidate) {
+ var isInsert = delta.action == "insert";
+ if (
+ isInsert
+ ? delta.lines.length <= 1 && !delta.lines[0]
+ : !Range.comparePoints(delta.start, delta.end)
+ ) {
+ return;
+ }
+
+ if (isInsert && delta.lines.length > 20000) {
+ this.$splitAndapplyLargeDelta(delta, 20000);
+ } else {
+ applyDelta(this.$lines, delta, doNotValidate);
+ this._signal("change", delta);
+ }
+ };
+
+ this.$safeApplyDelta = function(delta) {
+ var docLength = this.$lines.length;
+ if (
+ (delta.action == "remove" &&
+ delta.start.row < docLength &&
+ delta.end.row < docLength) ||
+ (delta.action == "insert" && delta.start.row <= docLength)
+ ) {
+ this.applyDelta(delta);
+ }
+ };
+
+ this.$splitAndapplyLargeDelta = function(delta, MAX) {
+ var lines = delta.lines;
+ var l = lines.length - MAX + 1;
+ var row = delta.start.row;
+ var column = delta.start.column;
+ for (var from = 0, to = 0; from < l; from = to) {
+ to += MAX - 1;
+ var chunk = lines.slice(from, to);
+ chunk.push("");
+ this.applyDelta(
+ {
+ start: this.pos(row + from, column),
+ end: this.pos(row + to, (column = 0)),
+ action: delta.action,
+ lines: chunk
+ },
+ true
+ );
+ }
+ delta.lines = lines.slice(from);
+ delta.start.row = row + from;
+ delta.start.column = column;
+ this.applyDelta(delta, true);
+ };
+ this.revertDelta = function(delta) {
+ this.$safeApplyDelta({
+ start: this.clonePos(delta.start),
+ end: this.clonePos(delta.end),
+ action: delta.action == "insert" ? "remove" : "insert",
+ lines: delta.lines.slice()
+ });
+ };
+ this.indexToPosition = function(index, startRow) {
+ var lines = this.$lines || this.getAllLines();
+ var newlineLength = this.getNewLineCharacter().length;
+ for (var i = startRow || 0, l = lines.length; i < l; i++) {
+ index -= lines[i].length + newlineLength;
+ if (index < 0)
+ return { row: i, column: index + lines[i].length + newlineLength };
+ }
+ return {
+ row: l - 1,
+ column: index + lines[l - 1].length + newlineLength
+ };
+ };
+ this.positionToIndex = function(pos, startRow) {
+ var lines = this.$lines || this.getAllLines();
+ var newlineLength = this.getNewLineCharacter().length;
+ var index = 0;
+ var row = Math.min(pos.row, lines.length);
+ for (var i = startRow || 0; i < row; ++i)
+ index += lines[i].length + newlineLength;
+
+ return index + pos.column;
+ };
+ }.call(Document.prototype));
+
+ exports.Document = Document;
+});
+
+ace.define("ace/lib/lang", [], function(require, exports, module) {
+ "use strict";
+
+ exports.last = function(a) {
+ return a[a.length - 1];
+ };
+
+ exports.stringReverse = function(string) {
+ return string
+ .split("")
+ .reverse()
+ .join("");
+ };
+
+ exports.stringRepeat = function(string, count) {
+ var result = "";
+ while (count > 0) {
+ if (count & 1) result += string;
+
+ if ((count >>= 1)) string += string;
+ }
+ return result;
+ };
+
+ var trimBeginRegexp = /^\s\s*/;
+ var trimEndRegexp = /\s\s*$/;
+
+ exports.stringTrimLeft = function(string) {
+ return string.replace(trimBeginRegexp, "");
+ };
+
+ exports.stringTrimRight = function(string) {
+ return string.replace(trimEndRegexp, "");
+ };
+
+ exports.copyObject = function(obj) {
+ var copy = {};
+ for (var key in obj) {
+ copy[key] = obj[key];
+ }
+ return copy;
+ };
+
+ exports.copyArray = function(array) {
+ var copy = [];
+ for (var i = 0, l = array.length; i < l; i++) {
+ if (array[i] && typeof array[i] == "object")
+ copy[i] = this.copyObject(array[i]);
+ else copy[i] = array[i];
+ }
+ return copy;
+ };
+
+ exports.deepCopy = function deepCopy(obj) {
+ if (typeof obj !== "object" || !obj) return obj;
+ var copy;
+ if (Array.isArray(obj)) {
+ copy = [];
+ for (var key = 0; key < obj.length; key++) {
+ copy[key] = deepCopy(obj[key]);
+ }
+ return copy;
+ }
+ if (Object.prototype.toString.call(obj) !== "[object Object]") return obj;
+
+ copy = {};
+ for (var key in obj) copy[key] = deepCopy(obj[key]);
+ return copy;
+ };
+
+ exports.arrayToMap = function(arr) {
+ var map = {};
+ for (var i = 0; i < arr.length; i++) {
+ map[arr[i]] = 1;
+ }
+ return map;
+ };
+
+ exports.createMap = function(props) {
+ var map = Object.create(null);
+ for (var i in props) {
+ map[i] = props[i];
+ }
+ return map;
+ };
+ exports.arrayRemove = function(array, value) {
+ for (var i = 0; i <= array.length; i++) {
+ if (value === array[i]) {
+ array.splice(i, 1);
+ }
+ }
+ };
+
+ exports.escapeRegExp = function(str) {
+ return str.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
+ };
+
+ exports.escapeHTML = function(str) {
+ return ("" + str)
+ .replace(/&/g, "&")
+ .replace(/"/g, """)
+ .replace(/'/g, "'")
+ .replace(/= "0" && ch <= "9") {
+ string += ch;
+ next();
+ }
+ if (ch === ".") {
+ string += ".";
+ while (next() && ch >= "0" && ch <= "9") {
+ string += ch;
+ }
+ }
+ if (ch === "e" || ch === "E") {
+ string += ch;
+ next();
+ if (ch === "-" || ch === "+") {
+ string += ch;
+ next();
+ }
+ while (ch >= "0" && ch <= "9") {
+ string += ch;
+ next();
+ }
+ }
+ number = +string;
+ if (isNaN(number)) {
+ error("Bad number");
+ } else {
+ return number;
+ }
+ },
+ string = function() {
+ var hex,
+ i,
+ string = "",
+ uffff;
+
+ if (ch === '"') {
+ while (next()) {
+ if (ch === '"') {
+ next();
+ return string;
+ } else if (ch === "\\") {
+ next();
+ if (ch === "u") {
+ uffff = 0;
+ for (i = 0; i < 4; i += 1) {
+ hex = parseInt(next(), 16);
+ if (!isFinite(hex)) {
+ break;
+ }
+ uffff = uffff * 16 + hex;
+ }
+ string += String.fromCharCode(uffff);
+ } else if (typeof escapee[ch] === "string") {
+ string += escapee[ch];
+ } else {
+ break;
+ }
+ } else if (ch == "\n" || ch == "\r") {
+ break;
+ } else {
+ string += ch;
+ }
+ }
+ }
+ error("Bad string");
+ },
+ white = function() {
+ while (ch && ch <= " ") {
+ next();
+ }
+ },
+ word = function() {
+ switch (ch) {
+ case "t":
+ next("t");
+ next("r");
+ next("u");
+ next("e");
+ return true;
+ case "f":
+ next("f");
+ next("a");
+ next("l");
+ next("s");
+ next("e");
+ return false;
+ case "n":
+ next("n");
+ next("u");
+ next("l");
+ next("l");
+ return null;
+ }
+ error("Unexpected '" + ch + "'");
+ },
+ value, // Place holder for the value function.
+ array = function() {
+ var array = [];
+
+ if (ch === "[") {
+ next("[");
+ white();
+ if (ch === "]") {
+ next("]");
+ return array; // empty array
+ }
+ while (ch) {
+ array.push(value());
+ white();
+ if (ch === "]") {
+ next("]");
+ return array;
+ }
+ next(",");
+ white();
+ }
+ }
+ error("Bad array");
+ },
+ object = function() {
+ var key,
+ object = {};
+
+ if (ch === "{") {
+ next("{");
+ white();
+ if (ch === "}") {
+ next("}");
+ return object; // empty object
+ }
+ while (ch) {
+ key = string();
+ white();
+ next(":");
+ if (Object.hasOwnProperty.call(object, key)) {
+ error('Duplicate key "' + key + '"');
+ }
+ object[key] = value();
+ white();
+ if (ch === "}") {
+ next("}");
+ return object;
+ }
+ next(",");
+ white();
+ }
+ }
+ error("Bad object");
+ };
+
+ value = function() {
+ white();
+ switch (ch) {
+ case "{":
+ return object();
+ case "[":
+ return array();
+ case '"':
+ return string();
+ case "-":
+ return number();
+ default:
+ return ch >= "0" && ch <= "9" ? number() : word();
+ }
+ };
+
+ return function(source, reviver) {
+ var result;
+
+ text = source;
+ at = 0;
+ ch = " ";
+ result = value();
+ white();
+ if (ch) {
+ error("Syntax error");
+ }
+
+ return typeof reviver === "function"
+ ? (function walk(holder, key) {
+ var k,
+ v,
+ value = holder[key];
+ if (value && typeof value === "object") {
+ for (k in value) {
+ if (Object.hasOwnProperty.call(value, k)) {
+ v = walk(value, k);
+ if (v !== undefined) {
+ value[k] = v;
+ } else {
+ delete value[k];
+ }
+ }
+ }
+ }
+ return reviver.call(holder, key, value);
+ })({ "": result }, "")
+ : result;
+ };
+});
+
+ace.define("ace/mode/json_worker", [], function(require, exports, module) {
+ "use strict";
+
+ var oop = require("../lib/oop");
+ var Mirror = require("../worker/mirror").Mirror;
+ var parse = require("./json/json_parse");
+
+ var JsonWorker = (exports.JsonWorker = function(sender) {
+ Mirror.call(this, sender);
+ this.setTimeout(200);
+ });
+
+ oop.inherits(JsonWorker, Mirror);
+
+ (function() {
+ this.onUpdate = function() {
+ var value = this.doc.getValue();
+ var errors = [];
+ try {
+ if (value) parse(value);
+ } catch (e) {
+ var pos = this.doc.indexToPosition(e.at - 1);
+ errors.push({
+ row: pos.row,
+ column: pos.column,
+ text: e.message,
+ type: "error"
+ });
+ }
+ this.sender.emit("annotate", errors);
+ };
+ }.call(JsonWorker.prototype));
+});
+
+ace.define("ace/lib/es5-shim", [], function(require, exports, module) {
+ function Empty() {}
+
+ if (!Function.prototype.bind) {
+ Function.prototype.bind = function bind(that) {
+ // .length is 1
+ var target = this;
+ if (typeof target != "function") {
+ throw new TypeError(
+ "Function.prototype.bind called on incompatible " + target
+ );
+ }
+ var args = slice.call(arguments, 1); // for normal call
+ var bound = function() {
+ if (this instanceof bound) {
+ var result = target.apply(this, args.concat(slice.call(arguments)));
+ if (Object(result) === result) {
+ return result;
+ }
+ return this;
+ } else {
+ return target.apply(that, args.concat(slice.call(arguments)));
+ }
+ };
+ if (target.prototype) {
+ Empty.prototype = target.prototype;
+ bound.prototype = new Empty();
+ Empty.prototype = null;
+ }
+ return bound;
+ };
+ }
+ var call = Function.prototype.call;
+ var prototypeOfArray = Array.prototype;
+ var prototypeOfObject = Object.prototype;
+ var slice = prototypeOfArray.slice;
+ var _toString = call.bind(prototypeOfObject.toString);
+ var owns = call.bind(prototypeOfObject.hasOwnProperty);
+ var defineGetter;
+ var defineSetter;
+ var lookupGetter;
+ var lookupSetter;
+ var supportsAccessors;
+ if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) {
+ defineGetter = call.bind(prototypeOfObject.__defineGetter__);
+ defineSetter = call.bind(prototypeOfObject.__defineSetter__);
+ lookupGetter = call.bind(prototypeOfObject.__lookupGetter__);
+ lookupSetter = call.bind(prototypeOfObject.__lookupSetter__);
+ }
+ if ([1, 2].splice(0).length != 2) {
+ if (
+ (function() {
+ // test IE < 9 to splice bug - see issue #138
+ function makeArray(l) {
+ var a = new Array(l + 2);
+ a[0] = a[1] = 0;
+ return a;
+ }
+ var array = [],
+ lengthBefore;
+
+ array.splice.apply(array, makeArray(20));
+ array.splice.apply(array, makeArray(26));
+
+ lengthBefore = array.length; //46
+ array.splice(5, 0, "XXX"); // add one element
+
+ lengthBefore + 1 == array.length;
+
+ if (lengthBefore + 1 == array.length) {
+ return true; // has right splice implementation without bugs
+ }
+ })()
+ ) {
+ //IE 6/7
+ var array_splice = Array.prototype.splice;
+ Array.prototype.splice = function(start, deleteCount) {
+ if (!arguments.length) {
+ return [];
+ } else {
+ return array_splice.apply(
+ this,
+ [
+ start === void 0 ? 0 : start,
+ deleteCount === void 0 ? this.length - start : deleteCount
+ ].concat(slice.call(arguments, 2))
+ );
+ }
+ };
+ } else {
+ //IE8
+ Array.prototype.splice = function(pos, removeCount) {
+ var length = this.length;
+ if (pos > 0) {
+ if (pos > length) pos = length;
+ } else if (pos == void 0) {
+ pos = 0;
+ } else if (pos < 0) {
+ pos = Math.max(length + pos, 0);
+ }
+
+ if (!(pos + removeCount < length)) removeCount = length - pos;
+
+ var removed = this.slice(pos, pos + removeCount);
+ var insert = slice.call(arguments, 2);
+ var add = insert.length;
+ if (pos === length) {
+ if (add) {
+ this.push.apply(this, insert);
+ }
+ } else {
+ var remove = Math.min(removeCount, length - pos);
+ var tailOldPos = pos + remove;
+ var tailNewPos = tailOldPos + add - remove;
+ var tailCount = length - tailOldPos;
+ var lengthAfterRemove = length - remove;
+
+ if (tailNewPos < tailOldPos) {
+ // case A
+ for (var i = 0; i < tailCount; ++i) {
+ this[tailNewPos + i] = this[tailOldPos + i];
+ }
+ } else if (tailNewPos > tailOldPos) {
+ // case B
+ for (i = tailCount; i--; ) {
+ this[tailNewPos + i] = this[tailOldPos + i];
+ }
+ } // else, add == remove (nothing to do)
+
+ if (add && pos === lengthAfterRemove) {
+ this.length = lengthAfterRemove; // truncate array
+ this.push.apply(this, insert);
+ } else {
+ this.length = lengthAfterRemove + add; // reserves space
+ for (i = 0; i < add; ++i) {
+ this[pos + i] = insert[i];
+ }
+ }
+ }
+ return removed;
+ };
+ }
+ }
+ if (!Array.isArray) {
+ Array.isArray = function isArray(obj) {
+ return _toString(obj) == "[object Array]";
+ };
+ }
+ var boxedString = Object("a"),
+ splitString = boxedString[0] != "a" || !(0 in boxedString);
+
+ if (!Array.prototype.forEach) {
+ Array.prototype.forEach = function forEach(fun /*, thisp*/) {
+ var object = toObject(this),
+ self =
+ splitString && _toString(this) == "[object String]"
+ ? this.split("")
+ : object,
+ thisp = arguments[1],
+ i = -1,
+ length = self.length >>> 0;
+ if (_toString(fun) != "[object Function]") {
+ throw new TypeError(); // TODO message
+ }
+
+ while (++i < length) {
+ if (i in self) {
+ fun.call(thisp, self[i], i, object);
+ }
+ }
+ };
+ }
+ if (!Array.prototype.map) {
+ Array.prototype.map = function map(fun /*, thisp*/) {
+ var object = toObject(this),
+ self =
+ splitString && _toString(this) == "[object String]"
+ ? this.split("")
+ : object,
+ length = self.length >>> 0,
+ result = Array(length),
+ thisp = arguments[1];
+ if (_toString(fun) != "[object Function]") {
+ throw new TypeError(fun + " is not a function");
+ }
+
+ for (var i = 0; i < length; i++) {
+ if (i in self) result[i] = fun.call(thisp, self[i], i, object);
+ }
+ return result;
+ };
+ }
+ if (!Array.prototype.filter) {
+ Array.prototype.filter = function filter(fun /*, thisp */) {
+ var object = toObject(this),
+ self =
+ splitString && _toString(this) == "[object String]"
+ ? this.split("")
+ : object,
+ length = self.length >>> 0,
+ result = [],
+ value,
+ thisp = arguments[1];
+ if (_toString(fun) != "[object Function]") {
+ throw new TypeError(fun + " is not a function");
+ }
+
+ for (var i = 0; i < length; i++) {
+ if (i in self) {
+ value = self[i];
+ if (fun.call(thisp, value, i, object)) {
+ result.push(value);
+ }
+ }
+ }
+ return result;
+ };
+ }
+ if (!Array.prototype.every) {
+ Array.prototype.every = function every(fun /*, thisp */) {
+ var object = toObject(this),
+ self =
+ splitString && _toString(this) == "[object String]"
+ ? this.split("")
+ : object,
+ length = self.length >>> 0,
+ thisp = arguments[1];
+ if (_toString(fun) != "[object Function]") {
+ throw new TypeError(fun + " is not a function");
+ }
+
+ for (var i = 0; i < length; i++) {
+ if (i in self && !fun.call(thisp, self[i], i, object)) {
+ return false;
+ }
+ }
+ return true;
+ };
+ }
+ if (!Array.prototype.some) {
+ Array.prototype.some = function some(fun /*, thisp */) {
+ var object = toObject(this),
+ self =
+ splitString && _toString(this) == "[object String]"
+ ? this.split("")
+ : object,
+ length = self.length >>> 0,
+ thisp = arguments[1];
+ if (_toString(fun) != "[object Function]") {
+ throw new TypeError(fun + " is not a function");
+ }
+
+ for (var i = 0; i < length; i++) {
+ if (i in self && fun.call(thisp, self[i], i, object)) {
+ return true;
+ }
+ }
+ return false;
+ };
+ }
+ if (!Array.prototype.reduce) {
+ Array.prototype.reduce = function reduce(fun /*, initial*/) {
+ var object = toObject(this),
+ self =
+ splitString && _toString(this) == "[object String]"
+ ? this.split("")
+ : object,
+ length = self.length >>> 0;
+ if (_toString(fun) != "[object Function]") {
+ throw new TypeError(fun + " is not a function");
+ }
+ if (!length && arguments.length == 1) {
+ throw new TypeError("reduce of empty array with no initial value");
+ }
+
+ var i = 0;
+ var result;
+ if (arguments.length >= 2) {
+ result = arguments[1];
+ } else {
+ do {
+ if (i in self) {
+ result = self[i++];
+ break;
+ }
+ if (++i >= length) {
+ throw new TypeError("reduce of empty array with no initial value");
+ }
+ } while (true);
+ }
+
+ for (; i < length; i++) {
+ if (i in self) {
+ result = fun.call(void 0, result, self[i], i, object);
+ }
+ }
+
+ return result;
+ };
+ }
+ if (!Array.prototype.reduceRight) {
+ Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) {
+ var object = toObject(this),
+ self =
+ splitString && _toString(this) == "[object String]"
+ ? this.split("")
+ : object,
+ length = self.length >>> 0;
+ if (_toString(fun) != "[object Function]") {
+ throw new TypeError(fun + " is not a function");
+ }
+ if (!length && arguments.length == 1) {
+ throw new TypeError("reduceRight of empty array with no initial value");
+ }
+
+ var result,
+ i = length - 1;
+ if (arguments.length >= 2) {
+ result = arguments[1];
+ } else {
+ do {
+ if (i in self) {
+ result = self[i--];
+ break;
+ }
+ if (--i < 0) {
+ throw new TypeError(
+ "reduceRight of empty array with no initial value"
+ );
+ }
+ } while (true);
+ }
+
+ do {
+ if (i in this) {
+ result = fun.call(void 0, result, self[i], i, object);
+ }
+ } while (i--);
+
+ return result;
+ };
+ }
+ if (!Array.prototype.indexOf || [0, 1].indexOf(1, 2) != -1) {
+ Array.prototype.indexOf = function indexOf(sought /*, fromIndex */) {
+ var self =
+ splitString && _toString(this) == "[object String]"
+ ? this.split("")
+ : toObject(this),
+ length = self.length >>> 0;
+
+ if (!length) {
+ return -1;
+ }
+
+ var i = 0;
+ if (arguments.length > 1) {
+ i = toInteger(arguments[1]);
+ }
+ i = i >= 0 ? i : Math.max(0, length + i);
+ for (; i < length; i++) {
+ if (i in self && self[i] === sought) {
+ return i;
+ }
+ }
+ return -1;
+ };
+ }
+ if (!Array.prototype.lastIndexOf || [0, 1].lastIndexOf(0, -3) != -1) {
+ Array.prototype.lastIndexOf = function lastIndexOf(
+ sought /*, fromIndex */
+ ) {
+ var self =
+ splitString && _toString(this) == "[object String]"
+ ? this.split("")
+ : toObject(this),
+ length = self.length >>> 0;
+
+ if (!length) {
+ return -1;
+ }
+ var i = length - 1;
+ if (arguments.length > 1) {
+ i = Math.min(i, toInteger(arguments[1]));
+ }
+ i = i >= 0 ? i : length - Math.abs(i);
+ for (; i >= 0; i--) {
+ if (i in self && sought === self[i]) {
+ return i;
+ }
+ }
+ return -1;
+ };
+ }
+ if (!Object.getPrototypeOf) {
+ Object.getPrototypeOf = function getPrototypeOf(object) {
+ return (
+ object.__proto__ ||
+ (object.constructor ? object.constructor.prototype : prototypeOfObject)
+ );
+ };
+ }
+ if (!Object.getOwnPropertyDescriptor) {
+ var ERR_NON_OBJECT =
+ "Object.getOwnPropertyDescriptor called on a " + "non-object: ";
+ Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(
+ object,
+ property
+ ) {
+ if (
+ (typeof object != "object" && typeof object != "function") ||
+ object === null
+ )
+ throw new TypeError(ERR_NON_OBJECT + object);
+ if (!owns(object, property)) return;
+
+ var descriptor, getter, setter;
+ descriptor = { enumerable: true, configurable: true };
+ if (supportsAccessors) {
+ var prototype = object.__proto__;
+ object.__proto__ = prototypeOfObject;
+
+ var getter = lookupGetter(object, property);
+ var setter = lookupSetter(object, property);
+ object.__proto__ = prototype;
+
+ if (getter || setter) {
+ if (getter) descriptor.get = getter;
+ if (setter) descriptor.set = setter;
+ return descriptor;
+ }
+ }
+ descriptor.value = object[property];
+ return descriptor;
+ };
+ }
+ if (!Object.getOwnPropertyNames) {
+ Object.getOwnPropertyNames = function getOwnPropertyNames(object) {
+ return Object.keys(object);
+ };
+ }
+ if (!Object.create) {
+ var createEmpty;
+ if (Object.prototype.__proto__ === null) {
+ createEmpty = function() {
+ return { __proto__: null };
+ };
+ } else {
+ createEmpty = function() {
+ var empty = {};
+ for (var i in empty) empty[i] = null;
+ empty.constructor = empty.hasOwnProperty = empty.propertyIsEnumerable = empty.isPrototypeOf = empty.toLocaleString = empty.toString = empty.valueOf = empty.__proto__ = null;
+ return empty;
+ };
+ }
+
+ Object.create = function create(prototype, properties) {
+ var object;
+ if (prototype === null) {
+ object = createEmpty();
+ } else {
+ if (typeof prototype != "object")
+ throw new TypeError(
+ "typeof prototype[" + typeof prototype + "] != 'object'"
+ );
+ var Type = function() {};
+ Type.prototype = prototype;
+ object = new Type();
+ object.__proto__ = prototype;
+ }
+ if (properties !== void 0) Object.defineProperties(object, properties);
+ return object;
+ };
+ }
+
+ function doesDefinePropertyWork(object) {
+ try {
+ Object.defineProperty(object, "sentinel", {});
+ return "sentinel" in object;
+ } catch (exception) {}
+ }
+ if (Object.defineProperty) {
+ var definePropertyWorksOnObject = doesDefinePropertyWork({});
+ var definePropertyWorksOnDom =
+ typeof document == "undefined" ||
+ doesDefinePropertyWork(document.createElement("div"));
+ if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) {
+ var definePropertyFallback = Object.defineProperty;
+ }
+ }
+
+ if (!Object.defineProperty || definePropertyFallback) {
+ var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: ";
+ var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: ";
+ var ERR_ACCESSORS_NOT_SUPPORTED =
+ "getters & setters can not be defined " + "on this javascript engine";
+
+ Object.defineProperty = function defineProperty(
+ object,
+ property,
+ descriptor
+ ) {
+ if (
+ (typeof object != "object" && typeof object != "function") ||
+ object === null
+ )
+ throw new TypeError(ERR_NON_OBJECT_TARGET + object);
+ if (
+ (typeof descriptor != "object" && typeof descriptor != "function") ||
+ descriptor === null
+ )
+ throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);
+ if (definePropertyFallback) {
+ try {
+ return definePropertyFallback.call(
+ Object,
+ object,
+ property,
+ descriptor
+ );
+ } catch (exception) {}
+ }
+ if (owns(descriptor, "value")) {
+ if (
+ supportsAccessors &&
+ (lookupGetter(object, property) || lookupSetter(object, property))
+ ) {
+ var prototype = object.__proto__;
+ object.__proto__ = prototypeOfObject;
+ delete object[property];
+ object[property] = descriptor.value;
+ object.__proto__ = prototype;
+ } else {
+ object[property] = descriptor.value;
+ }
+ } else {
+ if (!supportsAccessors)
+ throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
+ if (owns(descriptor, "get"))
+ defineGetter(object, property, descriptor.get);
+ if (owns(descriptor, "set"))
+ defineSetter(object, property, descriptor.set);
+ }
+
+ return object;
+ };
+ }
+ if (!Object.defineProperties) {
+ Object.defineProperties = function defineProperties(object, properties) {
+ for (var property in properties) {
+ if (owns(properties, property))
+ Object.defineProperty(object, property, properties[property]);
+ }
+ return object;
+ };
+ }
+ if (!Object.seal) {
+ Object.seal = function seal(object) {
+ return object;
+ };
+ }
+ if (!Object.freeze) {
+ Object.freeze = function freeze(object) {
+ return object;
+ };
+ }
+ try {
+ Object.freeze(function() {});
+ } catch (exception) {
+ Object.freeze = (function freeze(freezeObject) {
+ return function freeze(object) {
+ if (typeof object == "function") {
+ return object;
+ } else {
+ return freezeObject(object);
+ }
+ };
+ })(Object.freeze);
+ }
+ if (!Object.preventExtensions) {
+ Object.preventExtensions = function preventExtensions(object) {
+ return object;
+ };
+ }
+ if (!Object.isSealed) {
+ Object.isSealed = function isSealed(object) {
+ return false;
+ };
+ }
+ if (!Object.isFrozen) {
+ Object.isFrozen = function isFrozen(object) {
+ return false;
+ };
+ }
+ if (!Object.isExtensible) {
+ Object.isExtensible = function isExtensible(object) {
+ if (Object(object) === object) {
+ throw new TypeError(); // TODO message
+ }
+ var name = "";
+ while (owns(object, name)) {
+ name += "?";
+ }
+ object[name] = true;
+ var returnValue = owns(object, name);
+ delete object[name];
+ return returnValue;
+ };
+ }
+ if (!Object.keys) {
+ var hasDontEnumBug = true,
+ dontEnums = [
+ "toString",
+ "toLocaleString",
+ "valueOf",
+ "hasOwnProperty",
+ "isPrototypeOf",
+ "propertyIsEnumerable",
+ "constructor"
+ ],
+ dontEnumsLength = dontEnums.length;
+
+ for (var key in { toString: null }) {
+ hasDontEnumBug = false;
+ }
+
+ Object.keys = function keys(object) {
+ if (
+ (typeof object != "object" && typeof object != "function") ||
+ object === null
+ ) {
+ throw new TypeError("Object.keys called on a non-object");
+ }
+
+ var keys = [];
+ for (var name in object) {
+ if (owns(object, name)) {
+ keys.push(name);
+ }
+ }
+
+ if (hasDontEnumBug) {
+ for (var i = 0, ii = dontEnumsLength; i < ii; i++) {
+ var dontEnum = dontEnums[i];
+ if (owns(object, dontEnum)) {
+ keys.push(dontEnum);
+ }
+ }
+ }
+ return keys;
+ };
+ }
+ if (!Date.now) {
+ Date.now = function now() {
+ return new Date().getTime();
+ };
+ }
+ var ws =
+ "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u2000\u2001\u2002\u2003" +
+ "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" +
+ "\u2029\uFEFF";
+ if (!String.prototype.trim) {
+ ws = "[" + ws + "]";
+ var trimBeginRegexp = new RegExp("^" + ws + ws + "*"),
+ trimEndRegexp = new RegExp(ws + ws + "*$");
+ String.prototype.trim = function trim() {
+ return String(this)
+ .replace(trimBeginRegexp, "")
+ .replace(trimEndRegexp, "");
+ };
+ }
+
+ function toInteger(n) {
+ n = +n;
+ if (n !== n) {
+ // isNaN
+ n = 0;
+ } else if (n !== 0 && n !== 1 / 0 && n !== -(1 / 0)) {
+ n = (n > 0 || -1) * Math.floor(Math.abs(n));
+ }
+ return n;
+ }
+
+ function isPrimitive(input) {
+ var type = typeof input;
+ return (
+ input === null ||
+ type === "undefined" ||
+ type === "boolean" ||
+ type === "number" ||
+ type === "string"
+ );
+ }
+
+ function toPrimitive(input) {
+ var val, valueOf, toString;
+ if (isPrimitive(input)) {
+ return input;
+ }
+ valueOf = input.valueOf;
+ if (typeof valueOf === "function") {
+ val = valueOf.call(input);
+ if (isPrimitive(val)) {
+ return val;
+ }
+ }
+ toString = input.toString;
+ if (typeof toString === "function") {
+ val = toString.call(input);
+ if (isPrimitive(val)) {
+ return val;
+ }
+ }
+ throw new TypeError();
+ }
+ var toObject = function(o) {
+ if (o == null) {
+ // this matches both null and undefined
+ throw new TypeError("can't convert " + o + " to object");
+ }
+ return Object(o);
+ };
+});
diff --git a/pandora_console/include/javascript/connection_check.js b/pandora_console/include/javascript/connection_check.js
index 5ea72d2184..65b893ef51 100644
--- a/pandora_console/include/javascript/connection_check.js
+++ b/pandora_console/include/javascript/connection_check.js
@@ -29,22 +29,30 @@ function handleConnection() {
var connected;
var msg = "online";
+ var homeurl = getServerUrl();
+ if (homeurl == null || homeurl == "") {
+ return;
+ }
+
if (navigator.onLine) {
- isReachable(getServerUrl())
- .then(function(online) {
- if (online) {
- // handle online status
- connected = true;
- showConnectionMessage(connected, msg);
- } else {
- connected = false;
- msg = "No connectivity with server";
- showConnectionMessage(connected, msg);
- }
+ $.ajax({
+ url: homeurl + "include/connection_check.php",
+ type: "post",
+ dataType: "json"
+ })
+ .done(function(response) {
+ connected = true;
+ showConnectionMessage(connected, msg);
})
- .catch(function(err) {
- connected = false;
- msg = err;
+ .fail(function(err) {
+ // If test connection file is not found, do not show message.
+ if (err.status != 404) {
+ connected = false;
+ msg = err;
+ } else {
+ connected = true;
+ }
+
showConnectionMessage(connected, msg);
});
} else {
@@ -55,38 +63,17 @@ function handleConnection() {
}
}
-/**
- * Test server reachibilty and get response.
- *
- * @param {String} url
- *
- * Return {promise}
- */
-function isReachable(url) {
- /**
- * Note: fetch() still "succeeds" for 404s on subdirectories,
- * which is ok when only testing for domain reachability.
- *
- * Example:
- * https://google.com/noexist does not throw
- * https://noexist.com/noexist does throw
- */
- return fetch(url, { method: "HEAD", mode: "no-cors" })
- .then(function(resp) {
- return resp && (resp.ok || resp.type === "opaque");
- })
- .catch(function(error) {
- console.warn("[conn test failure]:", error);
- });
-}
-
/**
* Gets server origin url
*/
function getServerUrl() {
var server_url;
- server_url = window.location.origin;
+ try {
+ server_url = get_php_value("absolute_homeurl");
+ } catch (error) {
+ return "";
+ }
return server_url;
}
@@ -99,7 +86,7 @@ function getServerUrl() {
*/
function showConnectionMessage(conn = true, msg = "") {
var data = {};
- if (conn) {
+ if (conn && closed == false) {
$("div#message_dialog_connection")
.closest(".ui-dialog-content")
.dialog("close");
@@ -164,6 +151,7 @@ function infoMessage(data, idMsg) {
},
close: function(event, ui) {
$(".ui-widget-overlay").removeClass("error-modal-opened");
+ closed = true;
}
})
.show();
diff --git a/pandora_console/include/javascript/dynamic_service.js b/pandora_console/include/javascript/dynamic_service.js
new file mode 100644
index 0000000000..236e652159
--- /dev/null
+++ b/pandora_console/include/javascript/dynamic_service.js
@@ -0,0 +1,72 @@
+function updateSmartValue(event) {
+ var eventType = event.type;
+ var inputElement = $("#" + event.target.id);
+ var inputValue = inputElement.val();
+ var valueType = event.target.id.split("-");
+
+ if (eventType === "focus") {
+ inputElement.val(parseInt(inputValue));
+ } else if (eventType === "blur") {
+ change_mode();
+ } else {
+ var keyPressed = event.keyCode;
+ if (
+ (keyPressed <= 48 && keyPressed >= 57) ||
+ inputElement.val() < 0 ||
+ inputElement.val() > 100
+ ) {
+ event.preventDefault();
+ } else {
+ $("#text-" + valueType[0]).val(inputElement.val());
+ }
+ }
+}
+
+function change_mode(alt) {
+ var modeStatus = $("#mode").val();
+ var serviceMode = $("#hidden-service_mode_smart").val();
+ if (modeStatus == serviceMode) {
+ $(".smart_thresholds").css("display", "inline-flex");
+
+ var crit = parseFloat($("#text-critical").val());
+ var warn = parseFloat($("#text-warning").val());
+
+ if (crit < warn) {
+ $("#text-critical").val($("#text-warning").val());
+ }
+
+ $("#critical-val-d").val($("#text-critical").val() + " %");
+ $("#warning-val-d").val($("#text-warning").val() + " %");
+
+ if (alt != 1) {
+ $("#text-critical")
+ .prop("type", "range")
+ .prop("step", "0.01")
+ .prop("min", "0")
+ .prop("max", "100")
+ .on("input", function() {
+ change_mode(1);
+ });
+
+ $("#text-warning")
+ .prop("type", "range")
+ .prop("step", "0.01")
+ .prop("min", "0")
+ .prop("max", "100")
+ .on("input", function() {
+ change_mode(1);
+ });
+ }
+ } else {
+ $(".smart_thresholds").css("display", "none");
+
+ $("#text-critical")
+ .prop("type", "number")
+ .on("input", function() {})
+ .show();
+ $("#text-warning")
+ .prop("type", "number")
+ .on("input", function() {})
+ .show();
+ }
+}
diff --git a/pandora_console/include/javascript/elasticsearch_queryResult.js b/pandora_console/include/javascript/elasticsearch_queryResult.js
new file mode 100644
index 0000000000..82b63217b1
--- /dev/null
+++ b/pandora_console/include/javascript/elasticsearch_queryResult.js
@@ -0,0 +1,69 @@
+var editor = ace.edit("elasticsearch_editor");
+editor.setValue(`GET _search \n{\n "query": {\n "match_all": {}\n }\n}`);
+editor.clearSelection();
+
+var view = ace.edit("elasticsearch_view");
+view.setTheme("ace/theme/textmate");
+view.session.setMode("ace/mode/json");
+view.renderer.setShowGutter(false);
+view.setReadOnly(true);
+view.setShowPrintMargin(false);
+
+$("#submit-execute_query").click(function() {
+ view.setValue("");
+ let selectText = editor.getSelectedText();
+ if (selectText === "") {
+ let allText = editor.getValue();
+ if (allText === "") {
+ return;
+ }
+
+ allText = allText.split("\n").join("");
+ allText = allText.concat("\n");
+ var text = allText.match("(GET|PUT|POST)(.*?)({.*?}.*?)?(GET|POST|PUT|\n)");
+ } else {
+ selectText = selectText.split("\n").join("");
+ selectText = selectText.concat("\n");
+ var text = selectText.match("(GET|PUT|POST)(.*?)({.*?}.*?)?(\n)");
+ }
+
+ if (
+ text === null ||
+ text === undefined ||
+ text[2] === "" ||
+ text[2] === undefined
+ ) {
+ view.setValue(`Syntax error`);
+ view.clearSelection();
+ return;
+ }
+
+ const head = text[1];
+ let index = text[2].trim();
+ if (index.match("^/") === null) {
+ index = `/${index}`;
+ }
+
+ let json = text[3];
+ if (json !== "" && json !== undefined) {
+ json = json.match("^{.*}")[0];
+ }
+
+ jQuery.post(
+ $("#pandora_full_url").text() + "ajax.php",
+ {
+ page: "enterprise/include/ajax/log_viewer.ajax",
+ elasticsearch_curl: 1,
+ head: head,
+ index: index,
+ json: json
+ },
+ function(data) {
+ view.setValue(data);
+ view.clearSelection();
+
+ forced_title_callback();
+ },
+ "html"
+ );
+});
diff --git a/pandora_console/include/javascript/functions_pandora_networkmap.js b/pandora_console/include/javascript/functions_pandora_networkmap.js
index bb306ccd66..3450caa518 100644
--- a/pandora_console/include/javascript/functions_pandora_networkmap.js
+++ b/pandora_console/include/javascript/functions_pandora_networkmap.js
@@ -771,139 +771,137 @@ function move_to_networkmap(node) {
}
function edit_node(data_node, dblClick) {
- if (enterprise_installed) {
- var flag_edit_node = true;
- var edit_node = null;
+ var flag_edit_node = true;
+ var edit_node = null;
- //Only select one node
- var selection = d3.selectAll(".node_selected");
- var id;
+ //Only select one node
+ var selection = d3.selectAll(".node_selected");
+ var id;
- if (selection[0].length == 1) {
- edit_node = selection[0].pop();
- } else if (selection[0].length > 1) {
- edit_node = selection[0].pop();
- } else if (dblClick) {
- edit_node = d3.select("#id_node_" + data_node["id"] + networkmap_id);
- edit_node = edit_node[0][0];
- } else {
- flag_edit_node = false;
+ if (selection[0].length == 1) {
+ edit_node = selection[0].pop();
+ } else if (selection[0].length > 1) {
+ edit_node = selection[0].pop();
+ } else if (dblClick) {
+ edit_node = d3.select("#id_node_" + data_node["id"] + networkmap_id);
+ edit_node = edit_node[0][0];
+ } else {
+ flag_edit_node = false;
+ }
+
+ if (flag_edit_node) {
+ d3.selectAll(".node_selected").classed("node_selected", false);
+ d3.select(edit_node).classed("node_selected", true);
+
+ id = d3
+ .select(edit_node)
+ .attr("id")
+ .replace("id_node_", "");
+ var id_networkmap_lenght = networkmap_id.toString().length;
+ var id_node_length = id.length - id_networkmap_lenght;
+ id = id.substring(0, id_node_length);
+ var index_node = $.inArray(data_node, graph.nodes);
+ var node_selected = graph.nodes[index_node];
+ var selected_links = get_relations(node_selected);
+
+ $("select[name='shape'] option[value='" + node_selected.shape + "']").prop(
+ "selected",
+ true
+ );
+ $("select[name='shape']").attr(
+ "onchange",
+ "javascript: change_shape(" + node_selected.id_db + ");"
+ );
+ $("#node_options-fictional_node_update_button-1 input").attr(
+ "onclick",
+ "update_fictional_node(" + node_selected.id_db + ");"
+ );
+
+ $("#node_options-node_name-2 input").attr(
+ "onclick",
+ "update_node_name(" + node_selected.id_db + ");"
+ );
+
+ var params = [];
+ params.push("get_agent_info=1");
+ params.push("id_agent=" + node_selected["id_agent"]);
+ params.push("page=enterprise/operation/agentes/pandora_networkmap.view");
+
+ if (!enterprise_installed) {
+ params.push("page=operation/agentes/pandora_networkmap.view");
}
- if (flag_edit_node) {
- d3.selectAll(".node_selected").classed("node_selected", false);
- d3.select(edit_node).classed("node_selected", true);
-
- id = d3
- .select(edit_node)
- .attr("id")
- .replace("id_node_", "");
- var id_networkmap_lenght = networkmap_id.toString().length;
- var id_node_length = id.length - id_networkmap_lenght;
- id = id.substring(0, id_node_length);
- var index_node = $.inArray(data_node, graph.nodes);
- var node_selected = graph.nodes[index_node];
- var selected_links = get_relations(node_selected);
-
- $(
- "select[name='shape'] option[value='" + node_selected.shape + "']"
- ).prop("selected", true);
- $("select[name='shape']").attr(
- "onchange",
- "javascript: change_shape(" + node_selected.id_db + ");"
- );
- $("#node_options-fictional_node_update_button-1 input").attr(
- "onclick",
- "update_fictional_node(" + node_selected.id_db + ");"
- );
-
- $("#node_options-node_name-2 input").attr(
- "onclick",
- "update_node_name(" + node_selected.id_db + ");"
- );
-
- var params = [];
- params.push("get_agent_info=1");
- params.push("id_agent=" + node_selected["id_agent"]);
- params.push("page=enterprise/operation/agentes/pandora_networkmap.view");
-
- jQuery.ajax({
- data: params.join("&"),
- dataType: "json",
- type: "POST",
- url: window.base_url_homedir + "/ajax.php",
- success: function(data) {
- $("#node_details-0-1").html(
- '' +
- data["alias"] +
- ""
- );
-
- var addresses = "";
- if (data["adressess"] instanceof Array) {
- for (var i; i < data["adressess"].length; i++) {
- addresses += data["adressess"][i] + "
";
- }
- } else {
- for (var address in data["adressess"]) {
- addresses += address + "
";
- }
- }
- $("#node_details-1-1").html(addresses);
- $("#node_details-2-1").html(data["os"]);
- $("#node_details-3-1").html(data["group"]);
-
- $("[aria-describedby=dialog_node_edit]").css({ top: "200px" });
- $("#foot").css({
- top: parseInt(
- $("[aria-describedby=dialog_node_edit]").css("height") +
- $("[aria-describedby=dialog_node_edit]").css("top")
- ),
- position: "relative"
- });
-
- get_interface_data_to_table(node_selected, selected_links);
- }
- });
-
- $("#dialog_node_edit").dialog(
- "option",
- "title",
- dialog_node_edit_title.replace(
- "%s",
- ellipsize(node_selected["text"], 40)
- )
- ); // It doesn't eval the possible XSS so it's ok
- $("#dialog_node_edit").dialog("open");
-
- if (node_selected.id_agent == undefined || node_selected.type == 3) {
- //Fictional node
- $("#node_options-fictional_node_name").css("display", "");
- $("input[name='edit_name_fictional_node']").val(node_selected.text); // It doesn't eval the possible XSS so it's ok
- $("#node_options-fictional_node_networkmap_link").css("display", "");
- $("#edit_networkmap_to_link").val(node_selected.networkmap_id);
- $("#node_options-fictional_node_update_button").css("display", "");
- $("#node_options-node_name").css("display", "none");
- $("#node_options-node_update_button").css("display", "none");
- } else {
- $("input[name='edit_name_node']").val(node_selected.text); // It doesn't eval the possible XSS so it's ok
- $("#node_options-fictional_node_name").css("display", "none");
- $("#node_options-fictional_node_networkmap_link").css(
- "display",
- "none"
+ jQuery.ajax({
+ data: params.join("&"),
+ dataType: "json",
+ type: "POST",
+ url: window.base_url_homedir + "/ajax.php",
+ success: function(data) {
+ $("#node_details-0-1").html(
+ '' +
+ data["alias"] +
+ ""
);
- $("#node_options-fictional_node_update_button").css("display", "none");
- $("#node_options-node_name").css("display", "");
- }
- //Clean
- $("#relations_table .relation_link_row").remove();
- //Show the no relations
- $("#relations_table-loading").css("display", "none");
- $("#relations_table-no_relations").css("display", "");
+ var addresses = "";
+ if (data["adressess"] instanceof Array) {
+ for (var i; i < data["adressess"].length; i++) {
+ addresses += data["adressess"][i] + "
";
+ }
+ } else {
+ for (var address in data["adressess"]) {
+ addresses += address + "
";
+ }
+ }
+ $("#node_details-1-1").html(addresses);
+ $("#node_details-2-1").html(data["os"]);
+ $("#node_details-3-1").html(data["group"]);
+
+ $("[aria-describedby=dialog_node_edit]").css({ top: "200px" });
+ $("#foot").css({
+ top: parseInt(
+ $("[aria-describedby=dialog_node_edit]").css("height") +
+ $("[aria-describedby=dialog_node_edit]").css("top")
+ ),
+ position: "relative"
+ });
+
+ get_interface_data_to_table(node_selected, selected_links);
+ }
+ });
+
+ $("#dialog_node_edit").dialog(
+ "option",
+ "title",
+ dialog_node_edit_title.replace("%s", ellipsize(node_selected["text"], 40))
+ ); // It doesn't eval the possible XSS so it's ok
+ $("#dialog_node_edit").dialog("open");
+ $("#open_version_dialog").dialog();
+
+ if (node_selected.id_agent == undefined || node_selected.type == 3) {
+ //Fictional node
+ $("#node_options-fictional_node_name").css("display", "");
+ $("input[name='edit_name_fictional_node']").val(node_selected.text); // It doesn't eval the possible XSS so it's ok
+ $("#node_options-fictional_node_networkmap_link").css("display", "");
+ $("#edit_networkmap_to_link").val(node_selected.networkmap_id);
+ $("#node_options-fictional_node_update_button").css("display", "");
+ $("#node_options-node_name").css("display", "none");
+ $("#node_options-node_update_button").css("display", "none");
+ } else {
+ $("input[name='edit_name_node']").val(node_selected.text); // It doesn't eval the possible XSS so it's ok
+ $("#node_options-fictional_node_name").css("display", "none");
+ $("#node_options-fictional_node_networkmap_link").css("display", "none");
+ $("#node_options-fictional_node_update_button").css("display", "none");
+ $("#node_options-node_name").css("display", "");
}
+
+ //Clean
+ $("#relations_table .relation_link_row").remove();
+ //Show the no relations
+ $("#relations_table-loading").css("display", "none");
+ $("#relations_table-no_relations").css("display", "");
}
}
@@ -2871,18 +2869,35 @@ function init_drag_and_drop() {
});
});
} else {
- var params = [];
- params.push("update_node_alert=1");
- params.push("map_id=" + networkmap_id);
- params.push("page=operation/agentes/pandora_networkmap.view");
jQuery.ajax({
- data: params.join("&"),
dataType: "json",
type: "POST",
url: window.base_url_homedir + "/ajax.php",
+ data: {
+ node: JSON.stringify(d),
+ update_node: 1,
+ page: "operation/agentes/pandora_networkmap.view"
+ },
success: function(data) {
- if (data["correct"]) {
- $("#open_version_dialog").dialog();
+ if (d.state == "holding_area") {
+ //It is out the holding area
+ if (data["state"] == "") {
+ //Remove the style of nodes and links
+ //in holding area
+ d3.select("#id_node_" + d.id + networkmap_id).classed(
+ "holding_area",
+ false
+ );
+ d3.select(".source_" + d.id + networkmap_id).classed(
+ "holding_area_link",
+ false
+ );
+ d3.select(".target_" + d.id + networkmap_id).classed(
+ "holding_area_link",
+ false
+ );
+ graph.nodes[d.id].state = "";
+ }
}
}
});
diff --git a/pandora_console/include/javascript/gridstack.jQueryUI.js b/pandora_console/include/javascript/gridstack.jQueryUI.js
index de036b5bb3..8c1cb061a4 100644
--- a/pandora_console/include/javascript/gridstack.jQueryUI.js
+++ b/pandora_console/include/javascript/gridstack.jQueryUI.js
@@ -1,86 +1,64 @@
+/** gridstack.js 1.2.1 - JQuery UI Drag&Drop plugin @preserve */
/**
- * gridstack.js 0.3.0
- * http://troolee.github.io/gridstack.js/
- * (c) 2014-2016 Pavel Reznikov, Dylan Weiss
+ * https://gridstackjs.com/
+ * (c) 2014-2020 Alain Dumesny, Dylan Weiss, Pavel Reznikov
* gridstack.js may be freely distributed under the MIT license.
- * @preserve
*/
(function(factory) {
if (typeof define === "function" && define.amd) {
- define([
- "jquery",
- "lodash",
- "gridstack",
- "jquery-ui/data",
- "jquery-ui/disable-selection",
- "jquery-ui/focusable",
- "jquery-ui/form",
- "jquery-ui/ie",
- "jquery-ui/keycode",
- "jquery-ui/labels",
- "jquery-ui/jquery-1-7",
- "jquery-ui/plugin",
- "jquery-ui/safe-active-element",
- "jquery-ui/safe-blur",
- "jquery-ui/scroll-parent",
- "jquery-ui/tabbable",
- "jquery-ui/unique-id",
- "jquery-ui/version",
- "jquery-ui/widget",
- "jquery-ui/widgets/mouse",
- "jquery-ui/widgets/draggable",
- "jquery-ui/widgets/droppable",
- "jquery-ui/widgets/resizable"
- ], factory);
+ define(["jquery", "gridstack", "exports"], factory);
} else if (typeof exports !== "undefined") {
try {
jQuery = require("jquery");
} catch (e) {}
try {
- _ = require("lodash");
+ gridstack = require("gridstack");
} catch (e) {}
- try {
- GridStackUI = require("gridstack");
- } catch (e) {}
- factory(jQuery, _, GridStackUI);
+ factory(jQuery, gridstack.GridStack, exports);
} else {
- factory(jQuery, _, GridStackUI);
+ factory(jQuery, GridStack, window);
}
-})(function($, _, GridStackUI) {
- var scope = window;
-
+})(function($, GridStack, scope) {
/**
* @class JQueryUIGridStackDragDropPlugin
* jQuery UI implementation of drag'n'drop gridstack plugin.
*/
function JQueryUIGridStackDragDropPlugin(grid) {
- GridStackUI.GridStackDragDropPlugin.call(this, grid);
+ GridStack.DragDropPlugin.call(this, grid);
}
- GridStackUI.GridStackDragDropPlugin.registerPlugin(
- JQueryUIGridStackDragDropPlugin
- );
+ GridStack.DragDropPlugin.registerPlugin(JQueryUIGridStackDragDropPlugin);
JQueryUIGridStackDragDropPlugin.prototype = Object.create(
- GridStackUI.GridStackDragDropPlugin.prototype
+ GridStack.DragDropPlugin.prototype
);
JQueryUIGridStackDragDropPlugin.prototype.constructor = JQueryUIGridStackDragDropPlugin;
JQueryUIGridStackDragDropPlugin.prototype.resizable = function(el, opts) {
el = $(el);
- if (opts === "disable" || opts === "enable") {
+ if (opts === "disable" || opts === "enable" || opts === "destroy") {
el.resizable(opts);
} else if (opts === "option") {
var key = arguments[2];
var value = arguments[3];
el.resizable(opts, key, value);
} else {
+ var handles = el.data("gs-resize-handles")
+ ? el.data("gs-resize-handles")
+ : this.grid.opts.resizable.handles;
el.resizable(
- _.extend({}, this.grid.opts.resizable, {
- start: opts.start || function() {},
- stop: opts.stop || function() {},
- resize: opts.resize || function() {}
- })
+ $.extend(
+ {},
+ this.grid.opts.resizable,
+ {
+ handles: handles
+ },
+ {
+ start: opts.start || function() {},
+ stop: opts.stop || function() {},
+ resize: opts.resize || function() {}
+ }
+ )
);
}
return this;
@@ -88,14 +66,15 @@
JQueryUIGridStackDragDropPlugin.prototype.draggable = function(el, opts) {
el = $(el);
- if (opts === "disable" || opts === "enable") {
+ if (opts === "disable" || opts === "enable" || opts === "destroy") {
el.draggable(opts);
} else {
el.draggable(
- _.extend({}, this.grid.opts.draggable, {
- containment: this.grid.opts.isNested
- ? this.grid.container.parent()
- : null,
+ $.extend({}, this.grid.opts.draggable, {
+ containment:
+ this.grid.opts.isNested && !this.grid.opts.dragOut
+ ? this.grid.$el.parent()
+ : this.grid.opts.draggable.containment || null,
start: opts.start || function() {},
stop: opts.stop || function() {},
drag: opts.drag || function() {}
@@ -107,13 +86,7 @@
JQueryUIGridStackDragDropPlugin.prototype.droppable = function(el, opts) {
el = $(el);
- if (opts === "disable" || opts === "enable") {
- el.droppable(opts);
- } else {
- el.droppable({
- accept: opts.accept
- });
- }
+ el.droppable(opts);
return this;
};
@@ -131,5 +104,7 @@
return this;
};
+ scope.JQueryUIGridStackDragDropPlugin = JQueryUIGridStackDragDropPlugin;
+
return JQueryUIGridStackDragDropPlugin;
});
diff --git a/pandora_console/include/javascript/gridstack.js b/pandora_console/include/javascript/gridstack.js
index 22ee8ad18f..67d0a2d41b 100644
--- a/pandora_console/include/javascript/gridstack.js
+++ b/pandora_console/include/javascript/gridstack.js
@@ -1,36 +1,37 @@
/**
- * gridstack.js 0.3.0
- * http://troolee.github.io/gridstack.js/
- * (c) 2014-2016 Pavel Reznikov, Dylan Weiss
+ * gridstack.js 1.2.1
+ * https://gridstackjs.com/
+ * (c) 2014-2020 Alain Dumesny, Dylan Weiss, Pavel Reznikov
* gridstack.js may be freely distributed under the MIT license.
* @preserve
*/
(function(factory) {
if (typeof define === "function" && define.amd) {
- define(["jquery", "lodash"], factory);
+ define(["jquery", "exports"], factory);
} else if (typeof exports !== "undefined") {
- try {
- jQuery = require("jquery");
- } catch (e) {}
- try {
- _ = require("lodash");
- } catch (e) {}
- factory(jQuery, _);
- } else {
- factory(jQuery, _);
- }
-})(function($, _) {
- var scope = window;
+ var jQueryModule;
- var obsolete = function(f, oldName, newName) {
+ try {
+ jQueryModule = require("jquery");
+ } catch (e) {}
+
+ factory(jQueryModule || window.jQuery, exports);
+ } else {
+ factory(window.jQuery, window);
+ }
+})(function($, scope) {
+ // checks for obsolete method names
+ var obsolete = function(f, oldName, newName, rev) {
var wrapper = function() {
console.warn(
"gridstack.js: Function `" +
oldName +
- "` is deprecated as of v0.2.5 and has been replaced " +
+ "` is deprecated in " +
+ rev +
+ " and has been replaced " +
"with `" +
newName +
- "`. It will be **completely** removed in v1.0."
+ "`. It will be **completely** removed in v1.0"
);
return f.apply(this, arguments);
};
@@ -39,14 +40,48 @@
return wrapper;
};
- var obsoleteOpts = function(oldName, newName) {
- console.warn(
- "gridstack.js: Option `" +
- oldName +
- "` is deprecated as of v0.2.5 and has been replaced with `" +
- newName +
- "`. It will be **completely** removed in v1.0."
- );
+ // checks for obsolete grid options (can be used for any fields, but msg is about options)
+ var obsoleteOpts = function(opts, oldName, newName, rev) {
+ if (opts[oldName] !== undefined) {
+ opts[newName] = opts[oldName];
+ console.warn(
+ "gridstack.js: Option `" +
+ oldName +
+ "` is deprecated in " +
+ rev +
+ " and has been replaced with `" +
+ newName +
+ "`. It will be **completely** removed in v1.0"
+ );
+ }
+ };
+
+ // checks for obsolete grid options which are gone
+ var obsoleteOptsDel = function(opts, oldName, rev, info) {
+ if (opts[oldName] !== undefined) {
+ console.warn(
+ "gridstack.js: Option `" + oldName + "` is deprecated in " + rev + info
+ );
+ }
+ };
+
+ // checks for obsolete Jquery element attributes
+ var obsoleteAttr = function(el, oldName, newName, rev) {
+ var oldAttr = el.attr(oldName);
+ if (oldAttr !== undefined) {
+ el.attr(newName, oldAttr);
+ console.warn(
+ "gridstack.js: attribute `" +
+ oldName +
+ "`=" +
+ oldAttr +
+ " is deprecated on this object in " +
+ rev +
+ " and has been replaced with `" +
+ newName +
+ "`. It will be **completely** removed in v1.0"
+ );
+ }
};
var Utils = {
@@ -59,22 +94,25 @@
);
},
- sort: function(nodes, dir, width) {
- width =
- width ||
- _.chain(nodes)
- .map(function(node) {
- return node.x + node.width;
- })
- .max()
- .value();
- dir = dir != -1 ? 1 : -1;
- return _.sortBy(nodes, function(n) {
- return dir * (n.x + n.y * width);
- });
+ sort: function(nodes, dir, column) {
+ if (!column) {
+ var widths = nodes.map(function(node) {
+ return node.x + node.width;
+ });
+ column = Math.max.apply(Math, widths);
+ }
+
+ if (dir === -1)
+ return Utils.sortBy(nodes, function(n) {
+ return -(n.x + n.y * column);
+ });
+ else
+ return Utils.sortBy(nodes, function(n) {
+ return n.x + n.y * column;
+ });
},
- createStylesheet: function(id) {
+ createStylesheet: function(id, parent) {
var style = document.createElement("style");
style.setAttribute("type", "text/css");
style.setAttribute("data-gs-style-id", id);
@@ -83,7 +121,10 @@
} else {
style.appendChild(document.createTextNode(""));
}
- document.getElementsByTagName("head")[0].appendChild(style);
+ if (!parent) {
+ parent = document.getElementsByTagName("head")[0];
+ } // default to head
+ parent.insertBefore(style, parent.firstChild);
return style.sheet;
},
@@ -100,18 +141,18 @@
},
toBool: function(v) {
- if (typeof v == "boolean") {
+ if (typeof v === "boolean") {
return v;
}
- if (typeof v == "string") {
+ if (typeof v === "string") {
v = v.toLowerCase();
- return !(v === "" || v == "no" || v == "false" || v == "0");
+ return !(v === "" || v === "no" || v === "false" || v === "0");
}
return Boolean(v);
},
_collisionNodeCheck: function(n) {
- return n != this.node && Utils.isIntercepted(n, this.nn);
+ return n !== this.node && Utils.isIntercepted(n, this.nn);
},
_didCollide: function(bn) {
@@ -141,9 +182,9 @@
parseHeight: function(val) {
var height = val;
var heightUnit = "px";
- if (height && _.isString(height)) {
+ if (height && typeof height === "string") {
var match = height.match(
- /^(-[0-9]+\.[0-9]+|[0-9]*\.[0-9]+|-[0-9]+|[0-9]+)(px|em|rem|vh|vw)?$/
+ /^(-[0-9]+\.[0-9]+|[0-9]*\.[0-9]+|-[0-9]+|[0-9]+)(px|em|rem|vh|vw|%)?$/
);
if (!match) {
throw new Error("Invalid height");
@@ -152,35 +193,137 @@
height = parseFloat(match[1]);
}
return { height: height, unit: heightUnit };
+ },
+
+ without: function(array, item) {
+ var index = array.indexOf(item);
+
+ if (index !== -1) {
+ array = array.slice(0);
+ array.splice(index, 1);
+ }
+
+ return array;
+ },
+
+ sortBy: function(array, getter) {
+ return array.slice(0).sort(function(left, right) {
+ var valueLeft = getter(left);
+ var valueRight = getter(right);
+
+ if (valueRight === valueLeft) {
+ return 0;
+ }
+
+ return valueLeft > valueRight ? 1 : -1;
+ });
+ },
+
+ defaults: function(target) {
+ var sources = Array.prototype.slice.call(arguments, 1);
+
+ sources.forEach(function(source) {
+ for (var prop in source) {
+ if (
+ Object.prototype.hasOwnProperty.call(source, prop) &&
+ (!Object.prototype.hasOwnProperty.call(target, prop) ||
+ target[prop] === undefined)
+ ) {
+ target[prop] = source[prop];
+ }
+ }
+ });
+
+ return target;
+ },
+
+ clone: function(target) {
+ return $.extend({}, target);
+ },
+
+ throttle: function(callback, delay) {
+ var isWaiting = false;
+
+ return function() {
+ if (!isWaiting) {
+ callback.apply(this, arguments);
+ isWaiting = true;
+ setTimeout(function() {
+ isWaiting = false;
+ }, delay);
+ }
+ };
+ },
+
+ removePositioningStyles: function(el) {
+ var style = el[0].style;
+ if (style.position) {
+ style.removeProperty("position");
+ }
+ if (style.left) {
+ style.removeProperty("left");
+ }
+ if (style.top) {
+ style.removeProperty("top");
+ }
+ if (style.width) {
+ style.removeProperty("width");
+ }
+ if (style.height) {
+ style.removeProperty("height");
+ }
+ },
+ getScrollParent: function(el) {
+ var returnEl;
+ if (el === null) {
+ returnEl = null;
+ } else if (el.scrollHeight > el.clientHeight) {
+ returnEl = el;
+ } else {
+ returnEl = Utils.getScrollParent(el.parentNode);
+ }
+ return returnEl;
+ },
+ updateScrollPosition: function(el, ui, distance) {
+ // is widget in view?
+ var rect = el.getBoundingClientRect();
+ var innerHeightOrClientHeight =
+ window.innerHeight || document.documentElement.clientHeight;
+ if (rect.top < 0 || rect.bottom > innerHeightOrClientHeight) {
+ // set scrollTop of first parent that scrolls
+ // if parent is larger than el, set as low as possible
+ // to get entire widget on screen
+ var offsetDiffDown = rect.bottom - innerHeightOrClientHeight;
+ var offsetDiffUp = rect.top;
+ var scrollEl = Utils.getScrollParent(el);
+ if (scrollEl !== null) {
+ var prevScroll = scrollEl.scrollTop;
+ if (rect.top < 0 && distance < 0) {
+ // moving up
+ if (el.offsetHeight > innerHeightOrClientHeight) {
+ scrollEl.scrollTop += distance;
+ } else {
+ scrollEl.scrollTop +=
+ Math.abs(offsetDiffUp) > Math.abs(distance)
+ ? distance
+ : offsetDiffUp;
+ }
+ } else if (distance > 0) {
+ // moving down
+ if (el.offsetHeight > innerHeightOrClientHeight) {
+ scrollEl.scrollTop += distance;
+ } else {
+ scrollEl.scrollTop +=
+ offsetDiffDown > distance ? distance : offsetDiffDown;
+ }
+ }
+ // move widget y by amount scrolled
+ ui.position.top += scrollEl.scrollTop - prevScroll;
+ }
+ }
}
};
- // jscs:disable requireCamelCaseOrUpperCaseIdentifiers
- Utils.is_intercepted = obsolete(
- Utils.isIntercepted,
- "is_intercepted",
- "isIntercepted"
- );
-
- Utils.create_stylesheet = obsolete(
- Utils.createStylesheet,
- "create_stylesheet",
- "createStylesheet"
- );
-
- Utils.remove_stylesheet = obsolete(
- Utils.removeStylesheet,
- "remove_stylesheet",
- "removeStylesheet"
- );
-
- Utils.insert_css_rule = obsolete(
- Utils.insertCSSRule,
- "insert_css_rule",
- "insertCSSRule"
- );
- // jscs:enable requireCamelCaseOrUpperCaseIdentifiers
-
/**
* @class GridStackDragDropPlugin
* Base class for drag'n'drop plugin.
@@ -217,39 +360,39 @@
var idSeq = 0;
- var GridStackEngine = function(width, onchange, floatMode, height, items) {
- this.width = width;
- this.float = floatMode || false;
- this.height = height || 0;
+ var GridStackEngine = function(column, onchange, float, maxRow, items) {
+ this.column = column || 12;
+ this.float = float || false;
+ this.maxRow = maxRow || 0;
this.nodes = items || [];
this.onchange = onchange || function() {};
- this._updateCounter = 0;
- this._float = this.float;
-
this._addedNodes = [];
this._removedNodes = [];
+ this._batchMode = false;
};
GridStackEngine.prototype.batchUpdate = function() {
- this._updateCounter = 1;
- this.float = true;
+ if (this._batchMode) return;
+ this._batchMode = true;
+ this._prevFloat = this.float;
+ this.float = true; // let things go anywhere for now... commit() will restore and possibly reposition
};
GridStackEngine.prototype.commit = function() {
- if (this._updateCounter !== 0) {
- this._updateCounter = 0;
- this.float = this._float;
- this._packNodes();
- this._notify();
- }
+ if (!this._batchMode) return;
+ this._batchMode = false;
+ this.float = this._prevFloat;
+ delete this._prevFloat;
+ this._packNodes();
+ this._notify();
};
- // For Meteor support: https://github.com/troolee/gridstack.js/pull/272
+ // For Meteor support: https://github.com/gridstack/gridstack.js/pull/272
GridStackEngine.prototype.getNodeDataByDOMEl = function(el) {
- return _.find(this.nodes, function(n) {
- return el.get(0) === n.el.get(0);
+ return this.nodes.find(function(node) {
+ return el === node.el;
});
};
@@ -259,168 +402,244 @@
var nn = node;
var hasLocked = Boolean(
- _.find(this.nodes, function(n) {
+ this.nodes.find(function(n) {
return n.locked;
})
);
if (!this.float && !hasLocked) {
- nn = { x: 0, y: node.y, width: this.width, height: node.height };
+ nn = { x: 0, y: node.y, width: this.column, height: node.height };
}
while (true) {
- var collisionNode = _.find(
- this.nodes,
- _.bind(Utils._collisionNodeCheck, { node: node, nn: nn })
- );
- if (typeof collisionNode == "undefined") {
+ var collisionNode = this.nodes.find(Utils._collisionNodeCheck, {
+ node: node,
+ nn: nn
+ });
+ if (!collisionNode) {
return;
}
- this.moveNode(
- collisionNode,
- collisionNode.x,
- node.y + node.height,
- collisionNode.width,
- collisionNode.height,
- true
- );
+ var moved;
+ if (collisionNode.locked) {
+ // if colliding with a locked item, move ourself instead
+ moved = this.moveNode(
+ node,
+ node.x,
+ collisionNode.y + collisionNode.height,
+ node.width,
+ node.height,
+ true
+ );
+ } else {
+ moved = this.moveNode(
+ collisionNode,
+ collisionNode.x,
+ node.y + node.height,
+ collisionNode.width,
+ collisionNode.height,
+ true
+ );
+ }
+ if (!moved) {
+ return;
+ } // break inf loop if we couldn't move after all (ex: maxRow, fixed)
}
};
GridStackEngine.prototype.isAreaEmpty = function(x, y, width, height) {
var nn = { x: x || 0, y: y || 0, width: width || 1, height: height || 1 };
- var collisionNode = _.find(
- this.nodes,
- _.bind(function(n) {
- return Utils.isIntercepted(n, nn);
- }, this)
- );
- return collisionNode === null || typeof collisionNode === "undefined";
+ var collisionNode = this.nodes.find(function(n) {
+ return Utils.isIntercepted(n, nn);
+ });
+ return !collisionNode;
};
GridStackEngine.prototype._sortNodes = function(dir) {
- this.nodes = Utils.sort(this.nodes, dir, this.width);
+ this.nodes = Utils.sort(this.nodes, dir, this.column);
};
GridStackEngine.prototype._packNodes = function() {
this._sortNodes();
if (this.float) {
- _.each(
- this.nodes,
- _.bind(function(n, i) {
- if (
- n._updating ||
- typeof n._origY == "undefined" ||
- n.y == n._origY
- ) {
- return;
- }
+ this.nodes.forEach(function(n, i) {
+ if (n._updating || n._packY === undefined || n.y === n._packY) {
+ return;
+ }
- var newY = n.y;
- while (newY >= n._origY) {
- var collisionNode = _.chain(this.nodes)
- .find(_.bind(Utils._didCollide, { n: n, newY: newY }))
- .value();
+ var newY = n.y;
+ while (newY >= n._packY) {
+ var collisionNode = this.nodes
+ .slice(0, i)
+ .find(Utils._didCollide, { n: n, newY: newY });
- if (!collisionNode) {
- n._dirty = true;
- n.y = newY;
- }
- --newY;
- }
- }, this)
- );
- } else {
- _.each(
- this.nodes,
- _.bind(function(n, i) {
- if (n.locked) {
- return;
- }
- while (n.y > 0) {
- var newY = n.y - 1;
- var canBeMoved = i === 0;
-
- if (i > 0) {
- var collisionNode = _.chain(this.nodes)
- .take(i)
- .find(_.bind(Utils._didCollide, { n: n, newY: newY }))
- .value();
- canBeMoved = typeof collisionNode == "undefined";
- }
-
- if (!canBeMoved) {
- break;
- }
- n._dirty = n.y != newY;
+ if (!collisionNode) {
+ n._dirty = true;
n.y = newY;
}
- }, this)
- );
+ --newY;
+ }
+ }, this);
+ } else {
+ this.nodes.forEach(function(n, i) {
+ if (n.locked) {
+ return;
+ }
+ while (n.y > 0) {
+ var newY = n.y - 1;
+ var canBeMoved = i === 0;
+
+ if (i > 0) {
+ var collisionNode = this.nodes
+ .slice(0, i)
+ .find(Utils._didCollide, { n: n, newY: newY });
+ canBeMoved = collisionNode === undefined;
+ }
+
+ if (!canBeMoved) {
+ break;
+ }
+ // Note: must be dirty (from last position) for GridStack::OnChange CB to update positions
+ // and move items back. The user 'change' CB should detect changes from the original
+ // starting position instead.
+ n._dirty = n.y !== newY;
+ n.y = newY;
+ }
+ }, this);
}
};
GridStackEngine.prototype._prepareNode = function(node, resizing) {
- node = _.defaults(node || {}, { width: 1, height: 1, x: 0, y: 0 });
+ node = node || {};
+ // if we're missing position, have the grid position us automatically (before we set them to 0,0)
+ if (
+ node.x === undefined ||
+ node.y === undefined ||
+ node.x === null ||
+ node.y === null
+ ) {
+ node.autoPosition = true;
+ }
- node.x = parseInt("" + node.x);
- node.y = parseInt("" + node.y);
- node.width = parseInt("" + node.width);
- node.height = parseInt("" + node.height);
+ // assign defaults for missing required fields
+ var defaults = { width: 1, height: 1, x: 0, y: 0 };
+ node = Utils.defaults(node, defaults);
+
+ // convert any strings over
+ node.x = parseInt(node.x);
+ node.y = parseInt(node.y);
+ node.width = parseInt(node.width);
+ node.height = parseInt(node.height);
node.autoPosition = node.autoPosition || false;
node.noResize = node.noResize || false;
node.noMove = node.noMove || false;
- if (node.width > this.width) {
- node.width = this.width;
+ // check for NaN (in case messed up strings were passed. can't do parseInt() || defaults.x above as 0 is valid #)
+ if (Number.isNaN(node.x)) {
+ node.x = defaults.x;
+ node.autoPosition = true;
+ }
+ if (Number.isNaN(node.y)) {
+ node.y = defaults.y;
+ node.autoPosition = true;
+ }
+ if (Number.isNaN(node.width)) {
+ node.width = defaults.width;
+ }
+ if (Number.isNaN(node.height)) {
+ node.height = defaults.height;
+ }
+
+ if (node.maxWidth !== undefined) {
+ node.width = Math.min(node.width, node.maxWidth);
+ }
+ if (node.maxHeight !== undefined) {
+ node.height = Math.min(node.height, node.maxHeight);
+ }
+ if (node.minWidth !== undefined) {
+ node.width = Math.max(node.width, node.minWidth);
+ }
+ if (node.minHeight !== undefined) {
+ node.height = Math.max(node.height, node.minHeight);
+ }
+
+ if (node.width > this.column) {
+ node.width = this.column;
} else if (node.width < 1) {
node.width = 1;
}
-
- if (node.height < 1) {
+ if (this.maxRow && node.height > this.maxRow) {
+ node.height = this.maxRow;
+ } else if (node.height < 1) {
node.height = 1;
}
if (node.x < 0) {
node.x = 0;
}
-
- if (node.x + node.width > this.width) {
- if (resizing) {
- node.width = this.width - node.x;
- } else {
- node.x = this.width - node.width;
- }
- }
-
if (node.y < 0) {
node.y = 0;
}
+ if (node.x + node.width > this.column) {
+ if (resizing) {
+ node.width = this.column - node.x;
+ } else {
+ node.x = this.column - node.width;
+ }
+ }
+ if (this.maxRow && node.y + node.height > this.maxRow) {
+ if (resizing) {
+ node.height = this.maxRow - node.y;
+ } else {
+ node.y = this.maxRow - node.height;
+ }
+ }
+
return node;
};
GridStackEngine.prototype._notify = function() {
- var args = Array.prototype.slice.call(arguments, 0);
- args[0] = typeof args[0] === "undefined" ? [] : [args[0]];
- args[1] = typeof args[1] === "undefined" ? true : args[1];
- if (this._updateCounter) {
+ if (this._batchMode) {
return;
}
- var deletedNodes = args[0].concat(this.getDirtyNodes());
- this.onchange(deletedNodes, args[1]);
+ var args = Array.prototype.slice.call(arguments, 0);
+ args[0] =
+ args[0] === undefined ? [] : Array.isArray(args[0]) ? args[0] : [args[0]];
+ args[1] = args[1] === undefined ? true : args[1];
+ var dirtyNodes = args[0].concat(this.getDirtyNodes());
+ this.onchange(dirtyNodes, args[1]);
};
GridStackEngine.prototype.cleanNodes = function() {
- if (this._updateCounter) {
+ if (this._batchMode) {
return;
}
- _.each(this.nodes, function(n) {
- n._dirty = false;
+ this.nodes.forEach(function(n) {
+ delete n._dirty;
});
};
- GridStackEngine.prototype.getDirtyNodes = function() {
- return _.filter(this.nodes, function(n) {
+ GridStackEngine.prototype.getDirtyNodes = function(verify) {
+ // compare original X,Y,W,H (or entire node?) instead as _dirty can be a temporary state
+ if (verify) {
+ var dirtNodes = [];
+ this.nodes.forEach(function(n) {
+ if (n._dirty) {
+ if (
+ n.y === n._origY &&
+ n.x === n._origX &&
+ n.width === n._origW &&
+ n.height === n._origH
+ ) {
+ delete n._dirty;
+ } else {
+ dirtNodes.push(n);
+ }
+ }
+ });
+ return dirtNodes;
+ }
+
+ return this.nodes.filter(function(n) {
return n._dirty;
});
};
@@ -428,47 +647,35 @@
GridStackEngine.prototype.addNode = function(node, triggerAddEvent) {
node = this._prepareNode(node);
- if (typeof node.maxWidth != "undefined") {
- node.width = Math.min(node.width, node.maxWidth);
- }
- if (typeof node.maxHeight != "undefined") {
- node.height = Math.min(node.height, node.maxHeight);
- }
- if (typeof node.minWidth != "undefined") {
- node.width = Math.max(node.width, node.minWidth);
- }
- if (typeof node.minHeight != "undefined") {
- node.height = Math.max(node.height, node.minHeight);
- }
-
- node._id = ++idSeq;
- node._dirty = true;
+ node._id = node._id || ++idSeq;
if (node.autoPosition) {
this._sortNodes();
for (var i = 0; ; ++i) {
- var x = i % this.width;
- var y = Math.floor(i / this.width);
- if (x + node.width > this.width) {
+ var x = i % this.column;
+ var y = Math.floor(i / this.column);
+ if (x + node.width > this.column) {
continue;
}
if (
- !_.find(
- this.nodes,
- _.bind(Utils._isAddNodeIntercepted, { x: x, y: y, node: node })
- )
+ !this.nodes.find(Utils._isAddNodeIntercepted, {
+ x: x,
+ y: y,
+ node: node
+ })
) {
node.x = x;
node.y = y;
+ delete node.autoPosition; // found our slot
break;
}
}
}
this.nodes.push(node);
- if (typeof triggerAddEvent != "undefined" && triggerAddEvent) {
- this._addedNodes.push(_.clone(node));
+ if (triggerAddEvent) {
+ this._addedNodes.push(node);
}
this._fixCollisions(node);
@@ -478,36 +685,50 @@
};
GridStackEngine.prototype.removeNode = function(node, detachNode) {
- detachNode = typeof detachNode === "undefined" ? true : detachNode;
- this._removedNodes.push(_.clone(node));
- node._id = null;
- this.nodes = _.without(this.nodes, node);
+ detachNode = detachNode === undefined ? true : detachNode;
+ this._removedNodes.push(node);
+ node._id = null; // hint that node is being removed
+ this.nodes = Utils.without(this.nodes, node);
this._packNodes();
this._notify(node, detachNode);
};
+ GridStackEngine.prototype.removeAll = function(detachNode) {
+ delete this._layouts;
+ if (this.nodes.length === 0) {
+ return;
+ }
+ detachNode = detachNode === undefined ? true : detachNode;
+ this.nodes.forEach(function(n) {
+ n._id = null;
+ }); // hint that node is being removed
+ this._removedNodes = this.nodes;
+ this.nodes = [];
+ this._notify(this._removedNodes, detachNode);
+ };
+
GridStackEngine.prototype.canMoveNode = function(node, x, y, width, height) {
if (!this.isNodeChangedPosition(node, x, y, width, height)) {
return false;
}
var hasLocked = Boolean(
- _.find(this.nodes, function(n) {
+ this.nodes.find(function(n) {
return n.locked;
})
);
- if (!this.height && !hasLocked) {
+ if (!this.maxRow && !hasLocked) {
return true;
}
var clonedNode;
var clone = new GridStackEngine(
- this.width,
+ this.column,
null,
this.float,
0,
- _.map(this.nodes, function(n) {
- if (n == node) {
+ this.nodes.map(function(n) {
+ if (n === node) {
clonedNode = $.extend({}, n);
return clonedNode;
}
@@ -515,7 +736,7 @@
})
);
- if (typeof clonedNode === "undefined") {
+ if (!clonedNode) {
return true;
}
@@ -525,34 +746,34 @@
if (hasLocked) {
res &= !Boolean(
- _.find(clone.nodes, function(n) {
- return n != clonedNode && Boolean(n.locked) && Boolean(n._dirty);
+ clone.nodes.find(function(n) {
+ return n !== clonedNode && Boolean(n.locked) && Boolean(n._dirty);
})
);
}
- if (this.height) {
- res &= clone.getGridHeight() <= this.height;
+ if (this.maxRow) {
+ res &= clone.getRow() <= this.maxRow;
}
return res;
};
GridStackEngine.prototype.canBePlacedWithRespectToHeight = function(node) {
- if (!this.height) {
+ if (!this.maxRow) {
return true;
}
var clone = new GridStackEngine(
- this.width,
+ this.column,
null,
this.float,
0,
- _.map(this.nodes, function(n) {
+ this.nodes.map(function(n) {
return $.extend({}, n);
})
);
clone.addNode(node);
- return clone.getGridHeight() <= this.height;
+ return clone.getRow() <= this.maxRow;
};
GridStackEngine.prototype.isNodeChangedPosition = function(
@@ -562,37 +783,37 @@
width,
height
) {
- if (typeof x != "number") {
+ if (typeof x !== "number") {
x = node.x;
}
- if (typeof y != "number") {
+ if (typeof y !== "number") {
y = node.y;
}
- if (typeof width != "number") {
+ if (typeof width !== "number") {
width = node.width;
}
- if (typeof height != "number") {
+ if (typeof height !== "number") {
height = node.height;
}
- if (typeof node.maxWidth != "undefined") {
+ if (node.maxWidth !== undefined) {
width = Math.min(width, node.maxWidth);
}
- if (typeof node.maxHeight != "undefined") {
+ if (node.maxHeight !== undefined) {
height = Math.min(height, node.maxHeight);
}
- if (typeof node.minWidth != "undefined") {
+ if (node.minWidth !== undefined) {
width = Math.max(width, node.minWidth);
}
- if (typeof node.minHeight != "undefined") {
+ if (node.minHeight !== undefined) {
height = Math.max(height, node.minHeight);
}
if (
- node.x == x &&
- node.y == y &&
- node.width == width &&
- node.height == height
+ node.x === x &&
+ node.y === y &&
+ node.width === width &&
+ node.height === height
) {
return false;
}
@@ -607,58 +828,50 @@
height,
noPack
) {
- if (!this.isNodeChangedPosition(node, x, y, width, height)) {
- return node;
+ if (node.locked) {
+ return null;
}
- if (typeof x != "number") {
+ if (typeof x !== "number") {
x = node.x;
}
- if (typeof y != "number") {
+ if (typeof y !== "number") {
y = node.y;
}
- if (typeof width != "number") {
+ if (typeof width !== "number") {
width = node.width;
}
- if (typeof height != "number") {
+ if (typeof height !== "number") {
height = node.height;
}
- if (typeof node.maxWidth != "undefined") {
- width = Math.min(width, node.maxWidth);
- }
- if (typeof node.maxHeight != "undefined") {
- height = Math.min(height, node.maxHeight);
- }
- if (typeof node.minWidth != "undefined") {
- width = Math.max(width, node.minWidth);
- }
- if (typeof node.minHeight != "undefined") {
- height = Math.max(height, node.minHeight);
- }
-
+ // constrain the passed in values and check if we're still changing our node
+ var resizing = node.width !== width || node.height !== height;
+ var nn = {
+ x: x,
+ y: y,
+ width: width,
+ height: height,
+ maxWidth: node.maxWidth,
+ maxHeight: node.maxHeight,
+ minWidth: node.minWidth,
+ minHeight: node.minHeight
+ };
+ nn = this._prepareNode(nn, resizing);
if (
- node.x == x &&
- node.y == y &&
- node.width == width &&
- node.height == height
+ node.x === nn.x &&
+ node.y === nn.y &&
+ node.width === nn.width &&
+ node.height === nn.height
) {
- return node;
+ return null;
}
- var resizing = node.width != width;
node._dirty = true;
- node.x = x;
- node.y = y;
- node.width = width;
- node.height = height;
-
- node.lastTriedX = x;
- node.lastTriedY = y;
- node.lastTriedWidth = width;
- node.lastTriedHeight = height;
-
- node = this._prepareNode(node, resizing);
+ node.x = node.lastTriedX = nn.x;
+ node.y = node.lastTriedY = nn.y;
+ node.width = node.lastTriedWidth = nn.width;
+ node.height = node.lastTriedHeight = nn.height;
this._fixCollisions(node);
if (!noPack) {
@@ -668,97 +881,90 @@
return node;
};
- GridStackEngine.prototype.getGridHeight = function() {
- return _.reduce(
- this.nodes,
- function(memo, n) {
- return Math.max(memo, n.y + n.height);
- },
- 0
- );
+ GridStackEngine.prototype.getRow = function() {
+ return this.nodes.reduce(function(memo, n) {
+ return Math.max(memo, n.y + n.height);
+ }, 0);
};
GridStackEngine.prototype.beginUpdate = function(node) {
- _.each(this.nodes, function(n) {
- n._origY = n.y;
- });
+ if (node._updating) return;
node._updating = true;
+ this.nodes.forEach(function(n) {
+ n._packY = n.y;
+ });
};
GridStackEngine.prototype.endUpdate = function() {
- _.each(this.nodes, function(n) {
- n._origY = n.y;
- });
- var n = _.find(this.nodes, function(n) {
+ var n = this.nodes.find(function(n) {
return n._updating;
});
if (n) {
n._updating = false;
+ this.nodes.forEach(function(n) {
+ delete n._packY;
+ });
}
};
+ /**
+ * Construct a grid item from the given element and options
+ * @param {GridStackElement} el
+ * @param {GridstackOptions} opts
+ */
var GridStack = function(el, opts) {
var self = this;
- var oneColumnMode, isAutoCellHeight;
+ var oneColumnMode, _prevColumn, isAutoCellHeight;
opts = opts || {};
- this.container = $(el);
+ this.$el = $(el); // TODO: legacy code
+ this.el = this.$el.get(0); // exposed HTML element to the user
- // jscs:disable requireCamelCaseOrUpperCaseIdentifiers
- if (typeof opts.handle_class !== "undefined") {
- opts.handleClass = opts.handle_class;
- obsoleteOpts("handle_class", "handleClass");
- }
- if (typeof opts.item_class !== "undefined") {
- opts.itemClass = opts.item_class;
- obsoleteOpts("item_class", "itemClass");
- }
- if (typeof opts.placeholder_class !== "undefined") {
- opts.placeholderClass = opts.placeholder_class;
- obsoleteOpts("placeholder_class", "placeholderClass");
- }
- if (typeof opts.placeholder_text !== "undefined") {
- opts.placeholderText = opts.placeholder_text;
- obsoleteOpts("placeholder_text", "placeholderText");
- }
- if (typeof opts.cell_height !== "undefined") {
- opts.cellHeight = opts.cell_height;
- obsoleteOpts("cell_height", "cellHeight");
- }
- if (typeof opts.vertical_margin !== "undefined") {
- opts.verticalMargin = opts.vertical_margin;
- obsoleteOpts("vertical_margin", "verticalMargin");
- }
- if (typeof opts.min_width !== "undefined") {
- opts.minWidth = opts.min_width;
- obsoleteOpts("min_width", "minWidth");
- }
- if (typeof opts.static_grid !== "undefined") {
- opts.staticGrid = opts.static_grid;
- obsoleteOpts("static_grid", "staticGrid");
- }
- if (typeof opts.is_nested !== "undefined") {
- opts.isNested = opts.is_nested;
- obsoleteOpts("is_nested", "isNested");
- }
- if (typeof opts.always_show_resize_handle !== "undefined") {
- opts.alwaysShowResizeHandle = opts.always_show_resize_handle;
- obsoleteOpts("always_show_resize_handle", "alwaysShowResizeHandle");
- }
- // jscs:enable requireCamelCaseOrUpperCaseIdentifiers
+ obsoleteOpts(opts, "width", "column", "v0.5.3");
+ obsoleteOpts(opts, "height", "maxRow", "v0.5.3");
+ obsoleteOptsDel(
+ opts,
+ "oneColumnModeClass",
+ "v0.6.3",
+ ". Use class `.grid-stack-1` instead"
+ );
+
+ // container attributes
+ obsoleteAttr(this.$el, "data-gs-width", "data-gs-column", "v0.5.3");
+ obsoleteAttr(this.$el, "data-gs-height", "data-gs-max-row", "v0.5.3");
+ obsoleteAttr(
+ this.$el,
+ "data-gs-current-height",
+ "data-gs-current-row",
+ "v1.0.0"
+ );
opts.itemClass = opts.itemClass || "grid-stack-item";
- var isNested = this.container.closest("." + opts.itemClass).length > 0;
+ var isNested = this.$el.closest("." + opts.itemClass).length > 0;
- this.opts = _.defaults(opts || {}, {
- width: parseInt(this.container.attr("data-gs-width")) || 12,
- height: parseInt(this.container.attr("data-gs-height")) || 0,
+ // if row property exists, replace minRow and maxRow instead
+ if (opts.row) {
+ opts.minRow = opts.maxRow = opts.row;
+ delete opts.row;
+ }
+ var rowAttr = parseInt(this.$el.attr("data-gs-row"));
+
+ // elements attributes override any passed options (like CSS style) - merge the two together
+ this.opts = Utils.defaults(opts, {
+ column: parseInt(this.$el.attr("data-gs-column")) || 12,
+ minRow: rowAttr
+ ? rowAttr
+ : parseInt(this.$el.attr("data-gs-min-row")) || 0,
+ maxRow: rowAttr
+ ? rowAttr
+ : parseInt(this.$el.attr("data-gs-max-row")) || 0,
itemClass: "grid-stack-item",
placeholderClass: "grid-stack-placeholder",
placeholderText: "",
handle: ".grid-stack-item-content",
handleClass: null,
+ styleInHead: false,
cellHeight: 60,
verticalMargin: 20,
auto: true,
@@ -766,13 +972,13 @@
float: false,
staticGrid: false,
_class: "grid-stack-instance-" + (Math.random() * 10000).toFixed(0),
- animate: Boolean(this.container.attr("data-gs-animate")) || false,
+ animate: Boolean(this.$el.attr("data-gs-animate")) || false,
alwaysShowResizeHandle: opts.alwaysShowResizeHandle || false,
- resizable: _.defaults(opts.resizable || {}, {
+ resizable: Utils.defaults(opts.resizable || {}, {
autoHide: !(opts.alwaysShowResizeHandle || false),
handles: "se"
}),
- draggable: _.defaults(opts.draggable || {}, {
+ draggable: Utils.defaults(opts.draggable || {}, {
handle:
(opts.handleClass
? "." + opts.handleClass
@@ -786,12 +992,14 @@
disableResize: opts.disableResize || false,
rtl: "auto",
removable: false,
+ removableOptions: Utils.defaults(opts.removableOptions || {}, {
+ accept: "." + opts.itemClass
+ }),
removeTimeout: 2000,
verticalMarginUnit: "px",
cellHeightUnit: "px",
disableOneColumnMode: opts.disableOneColumnMode || false,
- oneColumnModeClass:
- opts.oneColumnModeClass || "grid-stack-one-column-mode",
+ oneColumnModeDomSort: opts.oneColumnModeDomSort,
ddPlugin: null
});
@@ -799,69 +1007,71 @@
this.opts.ddPlugin = GridStackDragDropPlugin;
} else if (this.opts.ddPlugin === null) {
this.opts.ddPlugin =
- _.first(GridStackDragDropPlugin.registeredPlugins) ||
- GridStackDragDropPlugin;
+ GridStackDragDropPlugin.registeredPlugins[0] || GridStackDragDropPlugin;
}
this.dd = new this.opts.ddPlugin(this);
if (this.opts.rtl === "auto") {
- this.opts.rtl = this.container.css("direction") === "rtl";
+ this.opts.rtl = this.$el.css("direction") === "rtl";
}
if (this.opts.rtl) {
- this.container.addClass("grid-stack-rtl");
+ this.$el.addClass("grid-stack-rtl");
}
this.opts.isNested = isNested;
isAutoCellHeight = this.opts.cellHeight === "auto";
if (isAutoCellHeight) {
+ // make the cell square initially
self.cellHeight(self.cellWidth(), true);
} else {
this.cellHeight(this.opts.cellHeight, true);
}
this.verticalMargin(this.opts.verticalMargin, true);
- this.container.addClass(this.opts._class);
+ this.$el.addClass(this.opts._class);
this._setStaticClass();
if (isNested) {
- this.container.addClass("grid-stack-nested");
+ this.$el.addClass("grid-stack-nested");
}
this._initStyles();
- this.grid = new GridStackEngine(
- this.opts.width,
+ this.engine = new GridStackEngine(
+ this.opts.column,
function(nodes, detachNode) {
- detachNode = typeof detachNode === "undefined" ? true : detachNode;
+ detachNode = detachNode === undefined ? true : detachNode;
var maxHeight = 0;
- _.each(nodes, function(n) {
+ this.nodes.forEach(function(n) {
+ maxHeight = Math.max(maxHeight, n.y + n.height);
+ });
+ nodes.forEach(function(n) {
if (detachNode && n._id === null) {
if (n.el) {
- n.el.remove();
+ $(n.el).remove();
}
} else {
- n.el
+ $(n.el)
.attr("data-gs-x", n.x)
.attr("data-gs-y", n.y)
.attr("data-gs-width", n.width)
.attr("data-gs-height", n.height);
- maxHeight = Math.max(maxHeight, n.y + n.height);
}
});
self._updateStyles(maxHeight + 10);
},
this.opts.float,
- this.opts.height
+ this.opts.maxRow
);
if (this.opts.auto) {
var elements = [];
var _this = this;
- this.container
+ this.$el
.children(
"." +
this.opts.itemClass +
@@ -871,22 +1081,23 @@
)
.each(function(index, el) {
el = $(el);
+ var x = parseInt(el.attr("data-gs-x"));
+ var y = parseInt(el.attr("data-gs-y"));
elements.push({
- el: el,
+ el: el.get(0),
+ // if x,y are missing (autoPosition) add them to end of list - but keep their respective DOM order
i:
- parseInt(el.attr("data-gs-x")) +
- parseInt(el.attr("data-gs-y")) * _this.opts.width
+ (Number.isNaN(x) ? 1000 : x) +
+ (Number.isNaN(y) ? 1000 : y) * _this.opts.column
});
});
- _.chain(elements)
- .sortBy(function(x) {
- return x.i;
- })
- .each(function(i) {
- self._prepareElement(i.el);
- })
- .value();
+ Utils.sortBy(elements, function(x) {
+ return x.i;
+ }).forEach(function(item) {
+ this._prepareElement(item.el);
+ }, this);
}
+ this.engine._saveInitial(); // initial start of items
this.setAnimation(this.opts.animate);
@@ -903,56 +1114,36 @@
this._updateContainerHeight();
- this._updateHeightsOnResize = _.throttle(function() {
+ this._updateHeightsOnResize = Utils.throttle(function() {
self.cellHeight(self.cellWidth(), false);
}, 100);
+ /**
+ * called when we are being resized - check if the one Column Mode needs to be turned on/off
+ * and remember the prev columns we used.
+ */
this.onResizeHandler = function() {
if (isAutoCellHeight) {
self._updateHeightsOnResize();
}
- if (self._isOneColumnMode() && !self.opts.disableOneColumnMode) {
- if (oneColumnMode) {
+ if (
+ !self.opts.disableOneColumnMode &&
+ (window.innerWidth ||
+ document.documentElement.clientWidth ||
+ document.body.clientWidth) <= self.opts.minWidth
+ ) {
+ if (self.oneColumnMode) {
return;
}
- self.container.addClass(self.opts.oneColumnModeClass);
- oneColumnMode = true;
-
- self.grid._sortNodes();
- _.each(self.grid.nodes, function(node) {
- self.container.append(node.el);
-
- if (self.opts.staticGrid) {
- return;
- }
- self.dd.draggable(node.el, "disable");
- self.dd.resizable(node.el, "disable");
-
- node.el.trigger("resize");
- });
+ self.oneColumnMode = true;
+ self.column(1);
} else {
- if (!oneColumnMode) {
+ if (!self.oneColumnMode) {
return;
}
-
- self.container.removeClass(self.opts.oneColumnModeClass);
- oneColumnMode = false;
-
- if (self.opts.staticGrid) {
- return;
- }
-
- _.each(self.grid.nodes, function(node) {
- if (!node.noMove && !self.opts.disableDrag) {
- self.dd.draggable(node.el, "enable");
- }
- if (!node.noResize && !self.opts.disableResize) {
- self.dd.resizable(node.el, "enable");
- }
-
- node.el.trigger("resize");
- });
+ self.oneColumnMode = false;
+ self.column(self._prevColumn);
}
};
@@ -962,25 +1153,25 @@
if (!self.opts.staticGrid && typeof self.opts.removable === "string") {
var trashZone = $(self.opts.removable);
if (!this.dd.isDroppable(trashZone)) {
- this.dd.droppable(trashZone, {
- accept: "." + self.opts.itemClass
- });
+ this.dd.droppable(trashZone, self.opts.removableOptions);
}
this.dd
.on(trashZone, "dropover", function(event, ui) {
var el = $(ui.draggable);
var node = el.data("_gridstack_node");
- if (node._grid !== self) {
+ if (!node || node._grid !== self) {
return;
}
+ el.data("inTrashZone", true);
self._setupRemovingTimeout(el);
})
.on(trashZone, "dropout", function(event, ui) {
var el = $(ui.draggable);
var node = el.data("_gridstack_node");
- if (node._grid !== self) {
+ if (!node || node._grid !== self) {
return;
}
+ el.data("inTrashZone", false);
self._clearRemovingTimeout(el);
});
}
@@ -991,42 +1182,45 @@
var onDrag = function(event, ui) {
var el = draggingElement;
var node = el.data("_gridstack_node");
- var pos = self.getCellFromPixel(ui.offset, true);
+ var pos = self.getCellFromPixel(
+ { left: event.pageX, top: event.pageY },
+ true
+ );
var x = Math.max(0, pos.x);
var y = Math.max(0, pos.y);
if (!node._added) {
node._added = true;
- node.el = el;
+ node.el = el.get(0);
+ node.autoPosition = true;
node.x = x;
node.y = y;
- self.grid.cleanNodes();
- self.grid.beginUpdate(node);
- self.grid.addNode(node);
+ self.engine.cleanNodes();
+ self.engine.beginUpdate(node);
+ self.engine.addNode(node);
- self.container.append(self.placeholder);
+ self.$el.append(self.placeholder);
self.placeholder
.attr("data-gs-x", node.x)
.attr("data-gs-y", node.y)
.attr("data-gs-width", node.width)
.attr("data-gs-height", node.height)
.show();
- node.el = self.placeholder;
+ node.el = self.placeholder.get(0);
node._beforeDragX = node.x;
node._beforeDragY = node.y;
- self._updateContainerHeight();
- } else {
- if (!self.grid.canMoveNode(node, x, y)) {
- return;
- }
- self.grid.moveNode(node, x, y);
self._updateContainerHeight();
}
+ if (!self.engine.canMoveNode(node, x, y)) {
+ return;
+ }
+ self.engine.moveNode(node, x, y);
+ self._updateContainerHeight();
};
this.dd
- .droppable(self.container, {
+ .droppable(self.$el, {
accept: function(el) {
el = $(el);
var node = el.data("_gridstack_node");
@@ -1040,110 +1234,162 @@
);
}
})
- .on(self.container, "dropover", function(event, ui) {
- var offset = self.container.offset();
+ .on(self.$el, "dropover", function(event, ui) {
var el = $(ui.draggable);
+ var width, height;
+
+ // see if we already have a node with widget/height and check for attributes
+ var origNode = el.data("_gridstack_node");
+ if (!origNode || !origNode.width || !origNode.height) {
+ var w = parseInt(el.attr("data-gs-width"));
+ if (w > 0) {
+ origNode = origNode || {};
+ origNode.width = w;
+ }
+ var h = parseInt(el.attr("data-gs-height"));
+ if (h > 0) {
+ origNode = origNode || {};
+ origNode.height = h;
+ }
+ }
+
+ // if not calculate the grid size based on element outer size
+ // height: Each row is cellHeight + verticalMargin, until last one which has no margin below
var cellWidth = self.cellWidth();
var cellHeight = self.cellHeight();
- var origNode = el.data("_gridstack_node");
-
- var width = origNode
- ? origNode.width
- : Math.ceil(el.outerWidth() / cellWidth);
- var height = origNode
- ? origNode.height
- : Math.ceil(el.outerHeight() / cellHeight);
+ var verticalMargin = self.opts.verticalMargin;
+ width =
+ origNode && origNode.width
+ ? origNode.width
+ : Math.ceil(el.outerWidth() / cellWidth);
+ height =
+ origNode && origNode.height
+ ? origNode.height
+ : Math.round(
+ (el.outerHeight() + verticalMargin) /
+ (cellHeight + verticalMargin)
+ );
draggingElement = el;
- var node = self.grid._prepareNode({
+ var node = self.engine._prepareNode({
width: width,
height: height,
_added: false,
_temporary: true
});
+ node.isOutOfGrid = true;
el.data("_gridstack_node", node);
el.data("_gridstack_node_orig", origNode);
el.on("drag", onDrag);
+ return false; // prevent parent from receiving msg (which may be grid as well)
})
- .on(self.container, "dropout", function(event, ui) {
+ .on(self.$el, "dropout", function(event, ui) {
+ // jquery-ui bug. Must verify widget is being dropped out
+ // check node variable that gets set when widget is out of grid
var el = $(ui.draggable);
- el.unbind("drag", onDrag);
+ if (!el.data("_gridstack_node")) {
+ return;
+ }
var node = el.data("_gridstack_node");
+ if (!node.isOutOfGrid) {
+ return;
+ }
+ el.unbind("drag", onDrag);
node.el = null;
- self.grid.removeNode(node);
+ self.engine.removeNode(node);
self.placeholder.detach();
self._updateContainerHeight();
el.data("_gridstack_node", el.data("_gridstack_node_orig"));
+ return false; // prevent parent from receiving msg (which may be grid as well)
})
- .on(self.container, "drop", function(event, ui) {
+ .on(self.$el, "drop", function(event, ui) {
self.placeholder.detach();
var node = $(ui.draggable).data("_gridstack_node");
+ node.isOutOfGrid = false;
node._grid = self;
var el = $(ui.draggable).clone(false);
el.data("_gridstack_node", node);
var originalNode = $(ui.draggable).data("_gridstack_node_orig");
- if (typeof originalNode !== "undefined") {
+ if (originalNode !== undefined && originalNode._grid !== undefined) {
originalNode._grid._triggerRemoveEvent();
}
- $(ui.draggable).remove();
- node.el = el;
+ $(ui.helper).remove();
+ node.el = el.get(0);
self.placeholder.hide();
+ Utils.removePositioningStyles(el);
+ el.find("div.ui-resizable-handle").remove();
+
el.attr("data-gs-x", node.x)
.attr("data-gs-y", node.y)
.attr("data-gs-width", node.width)
.attr("data-gs-height", node.height)
.addClass(self.opts.itemClass)
- .removeAttr("style")
.enableSelection()
.removeData("draggable")
.removeClass(
"ui-draggable ui-draggable-dragging ui-draggable-disabled"
)
.unbind("drag", onDrag);
- self.container.append(el);
+ self.$el.append(el);
self._prepareElementsByNode(el, node);
self._updateContainerHeight();
- self.grid._addedNodes.push(node);
+ self.engine._addedNodes.push(node);
self._triggerAddEvent();
self._triggerChangeEvent();
- self.grid.endUpdate();
+ self.engine.endUpdate();
+ $(ui.draggable).unbind("drag", onDrag);
+ $(ui.draggable).removeData("_gridstack_node");
+ $(ui.draggable).removeData("_gridstack_node_orig");
+ self.$el.trigger("dropped", [originalNode, node]);
+ return false; // prevent parent from receiving msg (which may be grid as well)
});
}
};
- GridStack.prototype._triggerChangeEvent = function(forceTrigger) {
- var elements = this.grid.getDirtyNodes();
- var hasChanges = false;
-
- var eventParams = [];
+ GridStack.prototype._triggerChangeEvent = function(/*forceTrigger*/) {
+ if (this.engine._batchMode) {
+ return;
+ }
+ var elements = this.engine.getDirtyNodes(true); // verify they really changed
if (elements && elements.length) {
- eventParams.push(elements);
- hasChanges = true;
- }
-
- if (hasChanges || forceTrigger === true) {
- this.container.trigger("change", eventParams);
+ this.engine._layoutsNodesChange(elements);
+ this._triggerEvent("change", elements);
}
+ this.engine._saveInitial(); // we called, now reset initial values & dirty flags
};
GridStack.prototype._triggerAddEvent = function() {
- if (this.grid._addedNodes && this.grid._addedNodes.length > 0) {
- this.container.trigger("added", [_.map(this.grid._addedNodes, _.clone)]);
- this.grid._addedNodes = [];
+ if (this.engine._batchMode) {
+ return;
+ }
+ if (this.engine._addedNodes && this.engine._addedNodes.length > 0) {
+ this.engine._layoutsNodesChange(this.engine._addedNodes);
+ // prevent added nodes from also triggering 'change' event (which is called next)
+ this.engine._addedNodes.forEach(function(n) {
+ delete n._dirty;
+ });
+ this._triggerEvent("added", this.engine._addedNodes);
+ this.engine._addedNodes = [];
}
};
GridStack.prototype._triggerRemoveEvent = function() {
- if (this.grid._removedNodes && this.grid._removedNodes.length > 0) {
- this.container.trigger("removed", [
- _.map(this.grid._removedNodes, _.clone)
- ]);
- this.grid._removedNodes = [];
+ if (this.engine._batchMode) {
+ return;
}
+ if (this.engine._removedNodes && this.engine._removedNodes.length > 0) {
+ this._triggerEvent("removed", this.engine._removedNodes);
+ this.engine._removedNodes = [];
+ }
+ };
+
+ GridStack.prototype._triggerEvent = function(name, data) {
+ var event = new CustomEvent(name, { detail: data });
+ this.el.dispatchEvent(event);
};
GridStack.prototype._initStyles = function() {
@@ -1151,14 +1397,16 @@
Utils.removeStylesheet(this._stylesId);
}
this._stylesId = "gridstack-style-" + (Math.random() * 100000).toFixed();
- this._styles = Utils.createStylesheet(this._stylesId);
+ var styleLocation = this.opts.styleInHead ? undefined : this.el.parentNode;
+ // if styleInHead === false insert style to parent to support WebComponent
+ this._styles = Utils.createStylesheet(this._stylesId, styleLocation);
if (this._styles !== null) {
this._styles._max = 0;
}
};
GridStack.prototype._updateStyles = function(maxHeight) {
- if (this._styles === null || typeof this._styles === "undefined") {
+ if (this._styles === null || this._styles === undefined) {
return;
}
@@ -1166,9 +1414,10 @@
var self = this;
var getHeight;
- if (typeof maxHeight == "undefined") {
+ if (maxHeight === undefined) {
maxHeight = this._styles._max;
}
+
this._initStyles();
this._updateContainerHeight();
if (!this.opts.cellHeight) {
@@ -1176,6 +1425,7 @@
return;
}
if (this._styles._max !== 0 && maxHeight <= this._styles._max) {
+ // Keep this._styles._max increasing
return;
}
@@ -1251,47 +1501,53 @@
};
GridStack.prototype._updateContainerHeight = function() {
- if (this.grid._updateCounter) {
+ if (this.engine._batchMode) {
return;
}
- var height = this.grid.getGridHeight();
- this.container.attr("data-gs-current-height", height);
+ var row = this.engine.getRow();
+ if (row < this.opts.minRow) {
+ row = this.opts.minRow;
+ }
+ // check for css min height. Each row is cellHeight + verticalMargin, until last one which has no margin below
+ var cssMinHeight = parseInt(this.$el.css("min-height"));
+ if (cssMinHeight > 0) {
+ var verticalMargin = this.opts.verticalMargin;
+ var minRow = Math.round(
+ (cssMinHeight + verticalMargin) / (this.cellHeight() + verticalMargin)
+ );
+ if (row < minRow) {
+ row = minRow;
+ }
+ }
+ this.$el.attr("data-gs-current-row", row);
if (!this.opts.cellHeight) {
return;
}
if (!this.opts.verticalMargin) {
- this.container.css(
+ this.$el.css(
"height",
- height * this.opts.cellHeight + this.opts.cellHeightUnit
+ row * this.opts.cellHeight + this.opts.cellHeightUnit
);
} else if (this.opts.cellHeightUnit === this.opts.verticalMarginUnit) {
- this.container.css(
+ this.$el.css(
"height",
- height * (this.opts.cellHeight + this.opts.verticalMargin) -
+ row * (this.opts.cellHeight + this.opts.verticalMargin) -
this.opts.verticalMargin +
this.opts.cellHeightUnit
);
} else {
- this.container.css(
+ this.$el.css(
"height",
"calc(" +
- (height * this.opts.cellHeight + this.opts.cellHeightUnit) +
+ (row * this.opts.cellHeight + this.opts.cellHeightUnit) +
" + " +
- (height * (this.opts.verticalMargin - 1) +
+ (row * (this.opts.verticalMargin - 1) +
this.opts.verticalMarginUnit) +
")"
);
}
};
- GridStack.prototype._isOneColumnMode = function() {
- return (
- (window.innerWidth ||
- document.documentElement.clientWidth ||
- document.body.clientWidth) <= this.opts.minWidth
- );
- };
-
GridStack.prototype._setupRemovingTimeout = function(el) {
var self = this;
var node = $(el).data("_gridstack_node");
@@ -1321,25 +1577,26 @@
var self = this;
var cellWidth;
- var cellHeight;
+ var cellFullHeight; // internal cellHeight + v-margin
var dragOrResize = function(event, ui) {
var x = Math.round(ui.position.left / cellWidth);
- var y = Math.floor((ui.position.top + cellHeight / 2) / cellHeight);
+ var y = Math.floor(
+ (ui.position.top + cellFullHeight / 2) / cellFullHeight
+ );
var width;
var height;
- if (event.type != "drag") {
- width = Math.round(ui.size.width / cellWidth);
- height = Math.round(ui.size.height / cellHeight);
- }
-
- if (event.type == "drag") {
+ if (event.type === "drag") {
+ var distance = ui.position.top - node._prevYPix;
+ node._prevYPix = ui.position.top;
+ Utils.updateScrollPosition(el[0], ui, distance);
if (
+ el.data("inTrashZone") ||
x < 0 ||
- x >= self.grid.width ||
+ x >= self.engine.column ||
y < 0 ||
- (!self.grid.float && y > self.grid.getGridHeight())
+ (!self.engine.float && y > self.engine.getRow())
) {
if (!node._temporaryRemoved) {
if (self.opts.removable === true) {
@@ -1351,39 +1608,42 @@
self.placeholder.detach();
self.placeholder.hide();
- self.grid.removeNode(node);
+ self.engine.removeNode(node);
self._updateContainerHeight();
node._temporaryRemoved = true;
+ } else {
+ return;
}
} else {
self._clearRemovingTimeout(el);
if (node._temporaryRemoved) {
- self.grid.addNode(node);
+ self.engine.addNode(node);
self.placeholder
.attr("data-gs-x", x)
.attr("data-gs-y", y)
.attr("data-gs-width", width)
.attr("data-gs-height", height)
.show();
- self.container.append(self.placeholder);
- node.el = self.placeholder;
+ self.$el.append(self.placeholder);
+ node.el = self.placeholder.get(0);
node._temporaryRemoved = false;
}
}
- } else if (event.type == "resize") {
- if (x < 0) {
- return;
- }
+ } else if (event.type === "resize") {
+ if (x < 0) return;
+ width = Math.round(ui.size.width / cellWidth);
+ height = Math.round(
+ (ui.size.height + self.verticalMargin()) / cellFullHeight
+ );
}
// width and height are undefined if not resizing
- var lastTriedWidth =
- typeof width !== "undefined" ? width : node.lastTriedWidth;
+ var lastTriedWidth = width !== undefined ? width : node.lastTriedWidth;
var lastTriedHeight =
- typeof height !== "undefined" ? height : node.lastTriedHeight;
+ height !== undefined ? height : node.lastTriedHeight;
if (
- !self.grid.canMoveNode(node, x, y, width, height) ||
+ !self.engine.canMoveNode(node, x, y, width, height) ||
(node.lastTriedX === x &&
node.lastTriedY === y &&
node.lastTriedWidth === lastTriedWidth &&
@@ -1395,32 +1655,39 @@
node.lastTriedY = y;
node.lastTriedWidth = width;
node.lastTriedHeight = height;
- self.grid.moveNode(node, x, y, width, height);
+ self.engine.moveNode(node, x, y, width, height);
self._updateContainerHeight();
+
+ if (event.type === "resize") {
+ $(event.target).trigger("gsresize", node);
+ }
};
var onStartMoving = function(event, ui) {
- self.container.append(self.placeholder);
+ self.$el.append(self.placeholder);
var o = $(this);
- self.grid.cleanNodes();
- self.grid.beginUpdate(node);
+ self.engine.cleanNodes();
+ self.engine.beginUpdate(node);
cellWidth = self.cellWidth();
- var strictCellHeight = Math.ceil(
- o.outerHeight() / o.attr("data-gs-height")
- );
- cellHeight =
- self.container.height() /
- parseInt(self.container.attr("data-gs-current-height"));
+ var strictCellHeight = self.cellHeight(); // heigh without v-margin
+ // compute height with v-margin (Note: we add 1 margin as last row is missing it)
+ cellFullHeight =
+ (self.$el.height() + self.verticalMargin()) /
+ parseInt(self.$el.attr("data-gs-current-row"));
self.placeholder
.attr("data-gs-x", o.attr("data-gs-x"))
.attr("data-gs-y", o.attr("data-gs-y"))
.attr("data-gs-width", o.attr("data-gs-width"))
.attr("data-gs-height", o.attr("data-gs-height"))
.show();
- node.el = self.placeholder;
+ node.el = self.placeholder.get(0);
node._beforeDragX = node.x;
node._beforeDragY = node.y;
+ node._prevYPix = ui.position.top;
+ var minHeight = node.minHeight || 1;
+ var verticalMargin = self.opts.verticalMargin;
+ // mineHeight - Each row is cellHeight + verticalMargin, until last one which has no margin below
self.dd.resizable(
el,
"option",
@@ -1431,10 +1698,10 @@
el,
"option",
"minHeight",
- strictCellHeight * (node.minHeight || 1)
+ strictCellHeight * minHeight + (minHeight - 1) * verticalMargin
);
- if (event.type == "resizestart") {
+ if (event.type === "resizestart") {
o.find(".grid-stack-item").trigger("resizestart");
}
};
@@ -1445,13 +1712,13 @@
return;
}
- var forceNotify = false;
+ // var forceNotify = false; what is the point of calling 'change' event with no data, when the 'removed' event is already called ?
self.placeholder.detach();
- node.el = o;
+ node.el = o.get(0);
self.placeholder.hide();
if (node._isAboutToRemove) {
- forceNotify = true;
+ // forceNotify = true;
var gridToNotify = el.data("_gridstack_node")._grid;
gridToNotify._triggerRemoveEvent();
el.removeData("_gridstack_node");
@@ -1459,39 +1726,38 @@
} else {
self._clearRemovingTimeout(el);
if (!node._temporaryRemoved) {
+ Utils.removePositioningStyles(o);
o.attr("data-gs-x", node.x)
.attr("data-gs-y", node.y)
.attr("data-gs-width", node.width)
- .attr("data-gs-height", node.height)
- .removeAttr("style");
+ .attr("data-gs-height", node.height);
} else {
+ Utils.removePositioningStyles(o);
o.attr("data-gs-x", node._beforeDragX)
.attr("data-gs-y", node._beforeDragY)
.attr("data-gs-width", node.width)
- .attr("data-gs-height", node.height)
- .removeAttr("style");
+ .attr("data-gs-height", node.height);
node.x = node._beforeDragX;
node.y = node._beforeDragY;
- self.grid.addNode(node);
+ node._temporaryRemoved = false;
+ self.engine.addNode(node);
}
}
self._updateContainerHeight();
- self._triggerChangeEvent(forceNotify);
+ self._triggerChangeEvent(/*forceNotify*/);
- self.grid.endUpdate();
+ self.engine.endUpdate();
var nestedGrids = o.find(".grid-stack");
- if (nestedGrids.length && event.type == "resizestop") {
+ if (nestedGrids.length && event.type === "resizestop") {
nestedGrids.each(function(index, el) {
- $(el)
- .data("gridstack")
- .onResizeHandler();
+ el.gridstack.onResizeHandler();
});
o.find(".grid-stack-item").trigger("resizestop");
o.find(".grid-stack-item").trigger("gsresizestop");
}
- if (event.type == "resizestop") {
- self.container.trigger("gsresizestop", o);
+ if (event.type === "resizestop") {
+ self.$el.trigger("gsresizestop", o);
}
};
@@ -1507,68 +1773,113 @@
resize: dragOrResize
});
- if (
- node.noMove ||
- (this._isOneColumnMode() && !self.opts.disableOneColumnMode) ||
- this.opts.disableDrag
- ) {
+ if (node.noMove || this.opts.disableDrag || this.opts.staticGrid) {
this.dd.draggable(el, "disable");
}
- if (
- node.noResize ||
- (this._isOneColumnMode() && !self.opts.disableOneColumnMode) ||
- this.opts.disableResize
- ) {
+ if (node.noResize || this.opts.disableResize || this.opts.staticGrid) {
this.dd.resizable(el, "disable");
}
- el.attr("data-gs-locked", node.locked ? "yes" : null);
+ this._writeAttr(el, node);
};
GridStack.prototype._prepareElement = function(el, triggerAddEvent) {
- triggerAddEvent =
- typeof triggerAddEvent != "undefined" ? triggerAddEvent : false;
+ triggerAddEvent = triggerAddEvent !== undefined ? triggerAddEvent : false;
var self = this;
el = $(el);
el.addClass(this.opts.itemClass);
- var node = self.grid.addNode(
- {
- x: el.attr("data-gs-x"),
- y: el.attr("data-gs-y"),
- width: el.attr("data-gs-width"),
- height: el.attr("data-gs-height"),
- maxWidth: el.attr("data-gs-max-width"),
- minWidth: el.attr("data-gs-min-width"),
- maxHeight: el.attr("data-gs-max-height"),
- minHeight: el.attr("data-gs-min-height"),
- autoPosition: Utils.toBool(el.attr("data-gs-auto-position")),
- noResize: Utils.toBool(el.attr("data-gs-no-resize")),
- noMove: Utils.toBool(el.attr("data-gs-no-move")),
- locked: Utils.toBool(el.attr("data-gs-locked")),
- el: el,
- id: el.attr("data-gs-id"),
- _grid: self
- },
- triggerAddEvent
- );
+ var node = this._readAttr(el, { el: el.get(0), _grid: self });
+ node = self.engine.addNode(node, triggerAddEvent);
el.data("_gridstack_node", node);
this._prepareElementsByNode(el, node);
};
+ /** call to write any default attributes back to element */
+ GridStack.prototype._writeAttr = function(el, node) {
+ if (!node) {
+ return;
+ }
+ el = $(el);
+ // Note: passing null removes the attr in jquery
+ if (node.x !== undefined) {
+ el.attr("data-gs-x", node.x);
+ }
+ if (node.y !== undefined) {
+ el.attr("data-gs-y", node.y);
+ }
+ if (node.width !== undefined) {
+ el.attr("data-gs-width", node.width);
+ }
+ if (node.height !== undefined) {
+ el.attr("data-gs-height", node.height);
+ }
+ if (node.autoPosition !== undefined) {
+ el.attr("data-gs-auto-position", node.autoPosition ? true : null);
+ }
+ if (node.minWidth !== undefined) {
+ el.attr("data-gs-min-width", node.minWidth);
+ }
+ if (node.maxWidth !== undefined) {
+ el.attr("data-gs-max-width", node.maxWidth);
+ }
+ if (node.minHeight !== undefined) {
+ el.attr("data-gs-min-height", node.minHeight);
+ }
+ if (node.maxHeight !== undefined) {
+ el.attr("data-gs-max-height", node.maxHeight);
+ }
+ if (node.noResize !== undefined) {
+ el.attr("data-gs-no-resize", node.noResize ? true : null);
+ }
+ if (node.noMove !== undefined) {
+ el.attr("data-gs-no-move", node.noMove ? true : null);
+ }
+ if (node.locked !== undefined) {
+ el.attr("data-gs-locked", node.locked ? true : null);
+ }
+ if (node.resizeHandles !== undefined) {
+ el.attr("data-gs-resize-handles", node.resizeHandles);
+ }
+ if (node.id !== undefined) {
+ el.attr("data-gs-id", node.id);
+ }
+ };
+
+ /** call to read any default attributes back to element */
+ GridStack.prototype._readAttr = function(el, node) {
+ el = $(el);
+ node = node || {};
+ node.x = el.attr("data-gs-x");
+ node.y = el.attr("data-gs-y");
+ node.width = el.attr("data-gs-width");
+ node.height = el.attr("data-gs-height");
+ node.autoPosition = Utils.toBool(el.attr("data-gs-auto-position"));
+ node.maxWidth = el.attr("data-gs-max-width");
+ node.minWidth = el.attr("data-gs-min-width");
+ node.maxHeight = el.attr("data-gs-max-height");
+ node.minHeight = el.attr("data-gs-min-height");
+ node.noResize = Utils.toBool(el.attr("data-gs-no-resize"));
+ node.noMove = Utils.toBool(el.attr("data-gs-no-move"));
+ node.locked = Utils.toBool(el.attr("data-gs-locked"));
+ node.resizeHandles = el.attr("data-gs-resize-handles");
+ node.id = el.attr("data-gs-id");
+ return node;
+ };
+
GridStack.prototype.setAnimation = function(enable) {
if (enable) {
- this.container.addClass("grid-stack-animate");
+ this.$el.addClass("grid-stack-animate");
} else {
- this.container.removeClass("grid-stack-animate");
+ this.$el.removeClass("grid-stack-animate");
}
};
GridStack.prototype.addWidget = function(
el,
- x,
+ opt,
y,
width,
height,
@@ -1579,54 +1890,48 @@
maxHeight,
id
) {
- el = $(el);
- if (typeof x != "undefined") {
- el.attr("data-gs-x", x);
+ // new way of calling with an object - make sure all items have been properly initialized
+ if (opt === undefined || typeof opt === "object") {
+ // Tempting to initialize the passed in opt with default and valid values, but this break knockout demos
+ // as the actual value are filled in when _prepareElement() calls el.attr('data-gs-xyz) before adding the node.
+ // opt = this.engine._prepareNode(opt);
+ } else {
+ // old legacy way of calling with items spelled out - call us back with single object instead (so we can properly initialized values)
+ return this.addWidget(el, {
+ x: opt,
+ y: y,
+ width: width,
+ height: height,
+ autoPosition: autoPosition,
+ minWidth: minWidth,
+ maxWidth: maxWidth,
+ minHeight: minHeight,
+ maxHeight: maxHeight,
+ id: id
+ });
}
- if (typeof y != "undefined") {
- el.attr("data-gs-y", y);
- }
- if (typeof width != "undefined") {
- el.attr("data-gs-width", width);
- }
- if (typeof height != "undefined") {
- el.attr("data-gs-height", height);
- }
- if (typeof autoPosition != "undefined") {
- el.attr("data-gs-auto-position", autoPosition ? "yes" : null);
- }
- if (typeof minWidth != "undefined") {
- el.attr("data-gs-min-width", minWidth);
- }
- if (typeof maxWidth != "undefined") {
- el.attr("data-gs-max-width", maxWidth);
- }
- if (typeof minHeight != "undefined") {
- el.attr("data-gs-min-height", minHeight);
- }
- if (typeof maxHeight != "undefined") {
- el.attr("data-gs-max-height", maxHeight);
- }
- if (typeof id != "undefined") {
- el.attr("data-gs-id", id);
- }
- this.container.append(el);
- this._prepareElement(el, true);
- this._triggerAddEvent();
- this._updateContainerHeight();
- this._triggerChangeEvent(true);
- return el;
+ el = $(el);
+ if (opt) {
+ // see knockout above
+ // make sure we load any DOM attributes that are not specified in passed in options (which override)
+ var domAttr = this._readAttr(el);
+ Utils.defaults(opt, domAttr);
+ this.engine._prepareNode(opt);
+ }
+ this._writeAttr(el, opt);
+ this.$el.append(el);
+ return this.makeWidget(el);
};
GridStack.prototype.makeWidget = function(el) {
el = $(el);
this._prepareElement(el, true);
- this._triggerAddEvent();
this._updateContainerHeight();
- this._triggerChangeEvent(true);
+ this._triggerAddEvent();
+ this._triggerChangeEvent(true); // trigger any other changes
- return el;
+ return el.get(0);
};
GridStack.prototype.willItFit = function(x, y, width, height, autoPosition) {
@@ -1637,52 +1942,50 @@
height: height,
autoPosition: autoPosition
};
- return this.grid.canBePlacedWithRespectToHeight(node);
+ return this.engine.canBePlacedWithRespectToHeight(node);
};
GridStack.prototype.removeWidget = function(el, detachNode) {
- detachNode = typeof detachNode === "undefined" ? true : detachNode;
el = $(el);
var node = el.data("_gridstack_node");
-
- // For Meteor support: https://github.com/troolee/gridstack.js/pull/272
+ // For Meteor support: https://github.com/gridstack/gridstack.js/pull/272
if (!node) {
- node = this.grid.getNodeDataByDOMEl(el);
+ node = this.engine.getNodeDataByDOMEl(el.get(0));
}
-
- this.grid.removeNode(node, detachNode);
+ if (!node || node.el.parentElement !== this.el) return; // not our child!
+ // remove our DOM data (circular link) and drag&drop permanently
el.removeData("_gridstack_node");
- this._updateContainerHeight();
- if (detachNode) {
- el.remove();
- }
- this._triggerChangeEvent(true);
+ this.dd.draggable(el, "destroy").resizable(el, "destroy");
+
+ this.engine.removeNode(node, detachNode);
this._triggerRemoveEvent();
+ this._triggerChangeEvent(true); // trigger any other changes
};
GridStack.prototype.removeAll = function(detachNode) {
- _.each(
- this.grid.nodes,
- _.bind(function(node) {
- this.removeWidget(node.el, detachNode);
- }, this)
- );
- this.grid.nodes = [];
- this._updateContainerHeight();
+ // always remove our DOM data (circular link) before list gets emptied and drag&drop permanently
+ this.engine.nodes.forEach(function(node) {
+ var el = $(node.el);
+ el.removeData("_gridstack_node");
+ this.dd.draggable(el, "destroy").resizable(el, "destroy");
+ }, this);
+
+ this.engine.removeAll(detachNode);
+ this._triggerRemoveEvent();
};
GridStack.prototype.destroy = function(detachGrid) {
$(window).off("resize", this.onResizeHandler);
- this.disable();
- if (typeof detachGrid != "undefined" && !detachGrid) {
+ if (detachGrid === false) {
this.removeAll(false);
- this.container.removeData("gridstack");
+ this.$el.removeClass(this.opts._class);
+ delete this.$el.get(0).gridstack;
} else {
- this.container.remove();
+ this.$el.remove();
}
Utils.removeStylesheet(this._stylesId);
- if (this.grid) {
- this.grid = null;
+ if (this.engine) {
+ this.engine = null;
}
};
@@ -1692,15 +1995,11 @@
el.each(function(index, el) {
el = $(el);
var node = el.data("_gridstack_node");
- if (typeof node == "undefined" || node === null) {
+ if (!node) {
return;
}
-
node.noResize = !(val || false);
- if (
- node.noResize ||
- (self._isOneColumnMode() && !self.opts.disableOneColumnMode)
- ) {
+ if (node.noResize) {
self.dd.resizable(el, "disable");
} else {
self.dd.resizable(el, "enable");
@@ -1715,15 +2014,11 @@
el.each(function(index, el) {
el = $(el);
var node = el.data("_gridstack_node");
- if (typeof node == "undefined" || node === null) {
+ if (!node) {
return;
}
-
node.noMove = !(val || false);
- if (
- node.noMove ||
- (self._isOneColumnMode() && !self.opts.disableOneColumnMode)
- ) {
+ if (node.noMove) {
self.dd.draggable(el, "disable");
el.removeClass("ui-draggable-handle");
} else {
@@ -1735,32 +2030,29 @@
};
GridStack.prototype.enableMove = function(doEnable, includeNewWidgets) {
- this.movable(this.container.children("." + this.opts.itemClass), doEnable);
+ this.movable(this.$el.children("." + this.opts.itemClass), doEnable);
if (includeNewWidgets) {
this.opts.disableDrag = !doEnable;
}
};
GridStack.prototype.enableResize = function(doEnable, includeNewWidgets) {
- this.resizable(
- this.container.children("." + this.opts.itemClass),
- doEnable
- );
+ this.resizable(this.$el.children("." + this.opts.itemClass), doEnable);
if (includeNewWidgets) {
this.opts.disableResize = !doEnable;
}
};
GridStack.prototype.disable = function() {
- this.movable(this.container.children("." + this.opts.itemClass), false);
- this.resizable(this.container.children("." + this.opts.itemClass), false);
- this.container.trigger("disable");
+ this.movable(this.$el.children("." + this.opts.itemClass), false);
+ this.resizable(this.$el.children("." + this.opts.itemClass), false);
+ this.$el.trigger("disable");
};
GridStack.prototype.enable = function() {
- this.movable(this.container.children("." + this.opts.itemClass), true);
- this.resizable(this.container.children("." + this.opts.itemClass), true);
- this.container.trigger("enable");
+ this.movable(this.$el.children("." + this.opts.itemClass), true);
+ this.resizable(this.$el.children("." + this.opts.itemClass), true);
+ this.$el.trigger("enable");
};
GridStack.prototype.locked = function(el, val) {
@@ -1768,10 +2060,9 @@
el.each(function(index, el) {
el = $(el);
var node = el.data("_gridstack_node");
- if (typeof node == "undefined" || node === null) {
+ if (!node) {
return;
}
-
node.locked = val || false;
el.attr("data-gs-locked", node.locked ? "yes" : null);
});
@@ -1783,10 +2074,9 @@
el.each(function(index, el) {
el = $(el);
var node = el.data("_gridstack_node");
- if (typeof node === "undefined" || node === null) {
+ if (!node) {
return;
}
-
if (!isNaN(val)) {
node.maxHeight = val || false;
el.attr("data-gs-max-height", val);
@@ -1800,10 +2090,9 @@
el.each(function(index, el) {
el = $(el);
var node = el.data("_gridstack_node");
- if (typeof node === "undefined" || node === null) {
+ if (!node) {
return;
}
-
if (!isNaN(val)) {
node.minHeight = val || false;
el.attr("data-gs-min-height", val);
@@ -1817,10 +2106,9 @@
el.each(function(index, el) {
el = $(el);
var node = el.data("_gridstack_node");
- if (typeof node === "undefined" || node === null) {
+ if (!node) {
return;
}
-
if (!isNaN(val)) {
node.maxWidth = val || false;
el.attr("data-gs-max-width", val);
@@ -1834,10 +2122,9 @@
el.each(function(index, el) {
el = $(el);
var node = el.data("_gridstack_node");
- if (typeof node === "undefined" || node === null) {
+ if (!node) {
return;
}
-
if (!isNaN(val)) {
node.minWidth = val || false;
el.attr("data-gs-min-width", val);
@@ -1849,58 +2136,74 @@
GridStack.prototype._updateElement = function(el, callback) {
el = $(el).first();
var node = el.data("_gridstack_node");
- if (typeof node == "undefined" || node === null) {
+ if (!node) {
return;
}
-
var self = this;
- self.grid.cleanNodes();
- self.grid.beginUpdate(node);
+ self.engine.cleanNodes();
+ self.engine.beginUpdate(node);
callback.call(this, el, node);
self._updateContainerHeight();
self._triggerChangeEvent();
- self.grid.endUpdate();
+ self.engine.endUpdate();
};
GridStack.prototype.resize = function(el, width, height) {
this._updateElement(el, function(el, node) {
- width =
- width !== null && typeof width != "undefined" ? width : node.width;
- height =
- height !== null && typeof height != "undefined" ? height : node.height;
+ width = width !== null && width !== undefined ? width : node.width;
+ height = height !== null && height !== undefined ? height : node.height;
- this.grid.moveNode(node, node.x, node.y, width, height);
+ this.engine.moveNode(node, node.x, node.y, width, height);
});
};
GridStack.prototype.move = function(el, x, y) {
this._updateElement(el, function(el, node) {
- x = x !== null && typeof x != "undefined" ? x : node.x;
- y = y !== null && typeof y != "undefined" ? y : node.y;
+ x = x !== null && x !== undefined ? x : node.x;
+ y = y !== null && y !== undefined ? y : node.y;
- this.grid.moveNode(node, x, y, node.width, node.height);
+ this.engine.moveNode(node, x, y, node.width, node.height);
});
};
GridStack.prototype.update = function(el, x, y, width, height) {
this._updateElement(el, function(el, node) {
- x = x !== null && typeof x != "undefined" ? x : node.x;
- y = y !== null && typeof y != "undefined" ? y : node.y;
- width =
- width !== null && typeof width != "undefined" ? width : node.width;
- height =
- height !== null && typeof height != "undefined" ? height : node.height;
+ x = x !== null && x !== undefined ? x : node.x;
+ y = y !== null && y !== undefined ? y : node.y;
+ width = width !== null && width !== undefined ? width : node.width;
+ height = height !== null && height !== undefined ? height : node.height;
- this.grid.moveNode(node, x, y, width, height);
+ this.engine.moveNode(node, x, y, width, height);
});
};
+ /**
+ * relayout grid items to reclaim any empty space
+ */
+ GridStack.prototype.compact = function() {
+ if (this.engine.nodes.length === 0) {
+ return;
+ }
+ this.batchUpdate();
+ this.engine._sortNodes();
+ var nodes = this.engine.nodes;
+ this.engine.nodes = []; // pretend we have no nodes to conflict layout to start with...
+ nodes.forEach(function(node) {
+ if (!node.noMove && !node.locked) {
+ node.autoPosition = true;
+ }
+ this.engine.addNode(node, false); // 'false' for add event trigger
+ node._dirty = true; // force attr update
+ }, this);
+ this.commit();
+ };
+
GridStack.prototype.verticalMargin = function(val, noUpdate) {
- if (typeof val == "undefined") {
+ if (val === undefined) {
return this.opts.verticalMargin;
}
@@ -1908,7 +2211,7 @@
if (
this.opts.verticalMarginUnit === heightData.unit &&
- this.opts.height === heightData.height
+ this.opts.maxRow === heightData.height
) {
return;
}
@@ -1920,19 +2223,27 @@
}
};
+ /** set/get the current cell height value */
GridStack.prototype.cellHeight = function(val, noUpdate) {
- if (typeof val == "undefined") {
- if (this.opts.cellHeight) {
+ // getter - returns the opts stored height else compute it...
+ if (val === undefined) {
+ if (this.opts.cellHeight && this.opts.cellHeight !== "auto") {
return this.opts.cellHeight;
}
- var o = this.container.children("." + this.opts.itemClass).first();
- return Math.ceil(o.outerHeight() / o.attr("data-gs-height"));
+ // compute the height taking margin into account (each row has margin other than last one)
+ var o = this.$el.children("." + this.opts.itemClass).first();
+ var height = o.attr("data-gs-height");
+ var verticalMargin = this.opts.verticalMargin;
+ return Math.round(
+ (o.outerHeight() - (height - 1) * verticalMargin) / height
+ );
}
- var heightData = Utils.parseHeight(val);
+ // setter - updates the cellHeight value if they changed
+ var heightData = Utils.parseHeight(val);
if (
- this.opts.cellHeightUnit === heightData.heightUnit &&
- this.opts.height === heightData.height
+ this.opts.cellHeightUnit === heightData.unit &&
+ this.opts.cellHeight === heightData.height
) {
return;
}
@@ -1945,21 +2256,21 @@
};
GridStack.prototype.cellWidth = function() {
- return Math.round(this.container.outerWidth() / this.opts.width);
+ // TODO: take margin into account ($horizontal_padding in .scss) to make cellHeight='auto' square ? (see 810-many-columns.html)
+ return Math.round(this.$el.outerWidth() / this.opts.column);
};
GridStack.prototype.getCellFromPixel = function(position, useOffset) {
var containerPos =
- typeof useOffset != "undefined" && useOffset
- ? this.container.offset()
- : this.container.position();
+ useOffset !== undefined && useOffset
+ ? this.$el.offset()
+ : this.$el.position();
var relativeLeft = position.left - containerPos.left;
var relativeTop = position.top - containerPos.top;
- var columnWidth = Math.floor(this.container.width() / this.opts.width);
+ var columnWidth = Math.floor(this.$el.width() / this.opts.column);
var rowHeight = Math.floor(
- this.container.height() /
- parseInt(this.container.attr("data-gs-current-height"))
+ this.$el.height() / parseInt(this.$el.attr("data-gs-current-row"))
);
return {
@@ -1969,16 +2280,18 @@
};
GridStack.prototype.batchUpdate = function() {
- this.grid.batchUpdate();
+ this.engine.batchUpdate();
};
GridStack.prototype.commit = function() {
- this.grid.commit();
- this._updateContainerHeight();
+ this.engine.commit();
+ this._triggerRemoveEvent();
+ this._triggerAddEvent();
+ this._triggerChangeEvent();
};
GridStack.prototype.isAreaEmpty = function(x, y, width, height) {
- return this.grid.isAreaEmpty(x, y, width, height);
+ return this.engine.isAreaEmpty(x, y, width, height);
};
GridStack.prototype.setStatic = function(staticValue) {
@@ -1992,244 +2305,353 @@
var staticClassName = "grid-stack-static";
if (this.opts.staticGrid === true) {
- this.container.addClass(staticClassName);
+ this.$el.addClass(staticClassName);
} else {
- this.container.removeClass(staticClassName);
+ this.$el.removeClass(staticClassName);
}
};
- GridStack.prototype._updateNodeWidths = function(oldWidth, newWidth) {
- this.grid._sortNodes();
- this.grid.batchUpdate();
- var node = {};
- for (var i = 0; i < this.grid.nodes.length; i++) {
- node = this.grid.nodes[i];
- this.update(
- node.el,
- Math.round((node.x * newWidth) / oldWidth),
- undefined,
- Math.round((node.width * newWidth) / oldWidth),
- undefined
- );
- }
- this.grid.commit();
- };
-
- GridStack.prototype.setGridWidth = function(gridWidth, doNotPropagate) {
- this.container.removeClass("grid-stack-" + this.opts.width);
- if (doNotPropagate !== true) {
- this._updateNodeWidths(this.opts.width, gridWidth);
- }
- this.opts.width = gridWidth;
- this.grid.width = gridWidth;
- this.container.addClass("grid-stack-" + gridWidth);
- };
-
- // jscs:disable requireCamelCaseOrUpperCaseIdentifiers
- GridStackEngine.prototype.batch_update = obsolete(
- GridStackEngine.prototype.batchUpdate
- );
- GridStackEngine.prototype._fix_collisions = obsolete(
- GridStackEngine.prototype._fixCollisions,
- "_fix_collisions",
- "_fixCollisions"
- );
- GridStackEngine.prototype.is_area_empty = obsolete(
- GridStackEngine.prototype.isAreaEmpty,
- "is_area_empty",
- "isAreaEmpty"
- );
- GridStackEngine.prototype._sort_nodes = obsolete(
- GridStackEngine.prototype._sortNodes,
- "_sort_nodes",
- "_sortNodes"
- );
- GridStackEngine.prototype._pack_nodes = obsolete(
- GridStackEngine.prototype._packNodes,
- "_pack_nodes",
- "_packNodes"
- );
- GridStackEngine.prototype._prepare_node = obsolete(
- GridStackEngine.prototype._prepareNode,
- "_prepare_node",
- "_prepareNode"
- );
- GridStackEngine.prototype.clean_nodes = obsolete(
- GridStackEngine.prototype.cleanNodes,
- "clean_nodes",
- "cleanNodes"
- );
- GridStackEngine.prototype.get_dirty_nodes = obsolete(
- GridStackEngine.prototype.getDirtyNodes,
- "get_dirty_nodes",
- "getDirtyNodes"
- );
- GridStackEngine.prototype.add_node = obsolete(
- GridStackEngine.prototype.addNode,
- "add_node",
- "addNode, "
- );
- GridStackEngine.prototype.remove_node = obsolete(
- GridStackEngine.prototype.removeNode,
- "remove_node",
- "removeNode"
- );
- GridStackEngine.prototype.can_move_node = obsolete(
- GridStackEngine.prototype.canMoveNode,
- "can_move_node",
- "canMoveNode"
- );
- GridStackEngine.prototype.move_node = obsolete(
- GridStackEngine.prototype.moveNode,
- "move_node",
- "moveNode"
- );
- GridStackEngine.prototype.get_grid_height = obsolete(
- GridStackEngine.prototype.getGridHeight,
- "get_grid_height",
- "getGridHeight"
- );
- GridStackEngine.prototype.begin_update = obsolete(
- GridStackEngine.prototype.beginUpdate,
- "begin_update",
- "beginUpdate"
- );
- GridStackEngine.prototype.end_update = obsolete(
- GridStackEngine.prototype.endUpdate,
- "end_update",
- "endUpdate"
- );
- GridStackEngine.prototype.can_be_placed_with_respect_to_height = obsolete(
- GridStackEngine.prototype.canBePlacedWithRespectToHeight,
- "can_be_placed_with_respect_to_height",
- "canBePlacedWithRespectToHeight"
- );
- GridStack.prototype._trigger_change_event = obsolete(
- GridStack.prototype._triggerChangeEvent,
- "_trigger_change_event",
- "_triggerChangeEvent"
- );
- GridStack.prototype._init_styles = obsolete(
- GridStack.prototype._initStyles,
- "_init_styles",
- "_initStyles"
- );
- GridStack.prototype._update_styles = obsolete(
- GridStack.prototype._updateStyles,
- "_update_styles",
- "_updateStyles"
- );
- GridStack.prototype._update_container_height = obsolete(
- GridStack.prototype._updateContainerHeight,
- "_update_container_height",
- "_updateContainerHeight"
- );
- GridStack.prototype._is_one_column_mode = obsolete(
- GridStack.prototype._isOneColumnMode,
- "_is_one_column_mode",
- "_isOneColumnMode"
- );
- GridStack.prototype._prepare_element = obsolete(
- GridStack.prototype._prepareElement,
- "_prepare_element",
- "_prepareElement"
- );
- GridStack.prototype.set_animation = obsolete(
- GridStack.prototype.setAnimation,
- "set_animation",
- "setAnimation"
- );
- GridStack.prototype.add_widget = obsolete(
- GridStack.prototype.addWidget,
- "add_widget",
- "addWidget"
- );
- GridStack.prototype.make_widget = obsolete(
- GridStack.prototype.makeWidget,
- "make_widget",
- "makeWidget"
- );
- GridStack.prototype.will_it_fit = obsolete(
- GridStack.prototype.willItFit,
- "will_it_fit",
- "willItFit"
- );
- GridStack.prototype.remove_widget = obsolete(
- GridStack.prototype.removeWidget,
- "remove_widget",
- "removeWidget"
- );
- GridStack.prototype.remove_all = obsolete(
- GridStack.prototype.removeAll,
- "remove_all",
- "removeAll"
- );
- GridStack.prototype.min_height = obsolete(
- GridStack.prototype.minHeight,
- "min_height",
- "minHeight"
- );
- GridStack.prototype.min_width = obsolete(
- GridStack.prototype.minWidth,
- "min_width",
- "minWidth"
- );
- GridStack.prototype._update_element = obsolete(
- GridStack.prototype._updateElement,
- "_update_element",
- "_updateElement"
- );
- GridStack.prototype.cell_height = obsolete(
- GridStack.prototype.cellHeight,
- "cell_height",
- "cellHeight"
- );
- GridStack.prototype.cell_width = obsolete(
- GridStack.prototype.cellWidth,
- "cell_width",
- "cellWidth"
- );
- GridStack.prototype.get_cell_from_pixel = obsolete(
- GridStack.prototype.getCellFromPixel,
- "get_cell_from_pixel",
- "getCellFromPixel"
- );
- GridStack.prototype.batch_update = obsolete(
- GridStack.prototype.batchUpdate,
- "batch_update",
- "batchUpdate"
- );
- GridStack.prototype.is_area_empty = obsolete(
- GridStack.prototype.isAreaEmpty,
- "is_area_empty",
- "isAreaEmpty"
- );
- GridStack.prototype.set_static = obsolete(
- GridStack.prototype.setStatic,
- "set_static",
- "setStatic"
- );
- GridStack.prototype._set_static_class = obsolete(
- GridStack.prototype._setStaticClass,
- "_set_static_class",
- "_setStaticClass"
- );
- // jscs:enable requireCamelCaseOrUpperCaseIdentifiers
-
- scope.GridStackUI = GridStack;
-
- scope.GridStackUI.Utils = Utils;
- scope.GridStackUI.Engine = GridStackEngine;
- scope.GridStackUI.GridStackDragDropPlugin = GridStackDragDropPlugin;
-
- $.fn.gridstack = function(opts) {
- return this.each(function() {
- var o = $(this);
- if (!o.data("gridstack")) {
- o.data("gridstack", new GridStack(this, opts));
+ /** called whenever a node is added or moved - updates the cached layouts */
+ GridStackEngine.prototype._layoutsNodesChange = function(nodes) {
+ if (!this._layouts || this._ignoreLayoutsNodeChange) return;
+ // remove smaller layouts - we will re-generate those on the fly... larger ones need to update
+ this._layouts.forEach(function(layout, column) {
+ if (!layout || column === this.column) return;
+ if (column < this.column) {
+ this._layouts[column] = undefined;
+ } else {
+ // we save the original x,y,w (h isn't cached) to see what actually changed to propagate better.
+ // Note: we don't need to check against out of bound scaling/moving as that will be done when using those cache values.
+ nodes.forEach(function(node) {
+ var n = layout.find(function(l) {
+ return l._id === node._id;
+ });
+ if (!n) return; // no cache for new nodes. Will use those values.
+ var ratio = column / this.column;
+ // Y changed, push down same amount
+ // TODO: detect doing item 'swaps' will help instead of move (especially in 1 column mode)
+ if (node.y !== node._origY) {
+ n.y += node.y - node._origY;
+ }
+ // X changed, scale from new position
+ if (node.x !== node._origX) {
+ n.x = Math.round(node.x * ratio);
+ }
+ // width changed, scale from new width
+ if (node.width !== node._origW) {
+ n.width = Math.round(node.width * ratio);
+ }
+ // ...height always carries over from cache
+ }, this);
}
+ }, this);
+ };
+
+ /**
+ * Called to scale the widget width & position up/down based on the column change.
+ * Note we store previous layouts (especially original ones) to make it possible to go
+ * from say 12 -> 1 -> 12 and get back to where we were.
+ *
+ * oldColumn: previous number of columns
+ * column: new column number
+ * nodes?: different sorted list (ex: DOM order) instead of current list
+ */
+ GridStackEngine.prototype._updateNodeWidths = function(
+ oldColumn,
+ column,
+ nodes
+ ) {
+ if (!this.nodes.length || oldColumn === column) {
+ return;
+ }
+
+ // cache the current layout in case they want to go back (like 12 -> 1 -> 12) as it requires original data
+ var copy = [this.nodes.length];
+ this.nodes.forEach(function(n, i) {
+ copy[i] = { x: n.x, y: n.y, width: n.width, _id: n._id };
+ }); // only thing we change is x,y,w and id to find it back
+ this._layouts = this._layouts || []; // use array to find larger quick
+ this._layouts[oldColumn] = copy;
+
+ // if we're going to 1 column and using DOM order rather than default sorting, then generate that layout
+ if (column === 1 && nodes && nodes.length) {
+ var top = 0;
+ nodes.forEach(function(n) {
+ n.x = 0;
+ n.width = 1;
+ n.y = Math.max(n.y, top);
+ top = n.y + n.height;
+ });
+ } else {
+ nodes = Utils.sort(this.nodes, -1, oldColumn); // current column reverse sorting so we can insert last to front (limit collision)
+ }
+
+ // see if we have cached previous layout.
+ var cacheNodes = this._layouts[column] || [];
+ // if not AND we are going up in size start with the largest layout as down-scaling is more accurate
+ var lastIndex = this._layouts.length - 1;
+ if (cacheNodes.length === 0 && column > oldColumn && column < lastIndex) {
+ cacheNodes = this._layouts[lastIndex] || [];
+ if (cacheNodes.length) {
+ // pretend we came from that larger column by assigning those values as starting point
+ oldColumn = lastIndex;
+ cacheNodes.forEach(function(cacheNode) {
+ var j = nodes.findIndex(function(n) {
+ return n && n._id === cacheNode._id;
+ });
+ if (j !== -1) {
+ // still current, use cache info positions
+ nodes[j].x = cacheNode.x;
+ nodes[j].y = cacheNode.y;
+ nodes[j].width = cacheNode.width;
+ }
+ });
+ cacheNodes = []; // we still don't have new column cached data... will generate from larger one.
+ }
+ }
+
+ // if we found cache re-use those nodes that are still current
+ var newNodes = [];
+ cacheNodes.forEach(function(cacheNode) {
+ var j = nodes.findIndex(function(n) {
+ return n && n._id === cacheNode._id;
+ });
+ if (j !== -1) {
+ // still current, use cache info positions
+ nodes[j].x = cacheNode.x;
+ nodes[j].y = cacheNode.y;
+ nodes[j].width = cacheNode.width;
+ newNodes.push(nodes[j]);
+ nodes[j] = null; // erase it so we know what's left
+ }
+ });
+ // ...and add any extra non-cached ones
+ var ratio = column / oldColumn;
+ nodes.forEach(function(node) {
+ if (!node) return;
+ node.x = column === 1 ? 0 : Math.round(node.x * ratio);
+ node.width =
+ column === 1 || oldColumn === 1
+ ? 1
+ : Math.round(node.width * ratio) || 1;
+ newNodes.push(node);
+ });
+
+ // finally relayout them in reverse order (to get correct placement)
+ newNodes = Utils.sort(newNodes, -1, column);
+ this._ignoreLayoutsNodeChange = true;
+ this.batchUpdate();
+ this.nodes = []; // pretend we have no nodes to start with (we use same structures) to simplify layout
+ newNodes.forEach(function(node) {
+ this.addNode(node, false); // 'false' for add event trigger
+ node._dirty = true; // force attr update
+ }, this);
+ this.commit();
+ delete this._ignoreLayoutsNodeChange;
+ };
+
+ /** called to save initial position/size */
+ GridStackEngine.prototype._saveInitial = function() {
+ this.nodes.forEach(function(n) {
+ n._origX = n.x;
+ n._origY = n.y;
+ n._origW = n.width;
+ n._origH = n.height;
+ delete n._dirty;
});
};
- return scope.GridStackUI;
+ /**
+ * set/get number of columns in the grid. Will attempt to update existing widgets
+ * to conform to new number of columns. Requires `gridstack-extra.css` or `gridstack-extra.min.css` for [2-11],
+ * else you will need to generate correct CSS (see https://github.com/gridstack/gridstack.js#change-grid-columns)
+ * @param column - Integer > 0 (default 12).
+ * @param doNotPropagate if true existing widgets will not be updated (optional)
+ */
+ GridStack.prototype.column = function(column, doNotPropagate) {
+ // getter - returns the opts stored mode
+ if (column === undefined) {
+ return this.opts.column;
+ }
+ // setter
+ if (this.opts.column === column) {
+ return;
+ }
+ var oldColumn = this.opts.column;
+
+ // if we go into 1 column mode (which happens if we're sized less than minWidth unless disableOneColumnMode is on)
+ // then remember the original columns so we can restore.
+ if (column === 1) {
+ this._prevColumn = oldColumn;
+ } else {
+ delete this._prevColumn;
+ }
+
+ this.$el.removeClass("grid-stack-" + oldColumn);
+ this.$el.addClass("grid-stack-" + column);
+ this.opts.column = this.engine.column = column;
+
+ if (doNotPropagate === true) {
+ return;
+ }
+
+ // update the items now - see if the dom order nodes should be passed instead (else default to current list)
+ var domNodes;
+ if (this.opts.oneColumnModeDomSort && column === 1) {
+ domNodes = [];
+ this.$el.children("." + this.opts.itemClass).each(function(index, el) {
+ var node = $(el).data("_gridstack_node");
+ if (node) {
+ domNodes.push(node);
+ }
+ });
+ if (!domNodes.length) {
+ domNodes = undefined;
+ }
+ }
+ this.engine._updateNodeWidths(oldColumn, column, domNodes);
+
+ // and trigger our event last...
+ this.engine._ignoreLayoutsNodeChange = true;
+ this._triggerChangeEvent();
+ delete this.engine._ignoreLayoutsNodeChange;
+ };
+
+ GridStack.prototype.float = function(val) {
+ // getter - returns the opts stored mode
+ if (val === undefined) {
+ return this.opts.float || false;
+ }
+ // setter - updates the mode and relayout if gravity is back on
+ if (this.opts.float === val) {
+ return;
+ }
+ this.opts.float = this.engine.float = val || false;
+ if (!val) {
+ this.engine._packNodes();
+ this.engine._notify();
+ this._triggerChangeEvent();
+ }
+ };
+
+ GridStack.prototype.getRow = function() {
+ return this.engine.getRow();
+ };
+
+ /** Event handler that extracts our CustomEvent data out automatically for receiving custom
+ * notifications (see doc for supported events)
+ */
+ GridStack.prototype.on = function(eventName, callback) {
+ // check for array of names being passed instead
+ if (eventName.indexOf(" ") !== -1) {
+ var names = eventName.split(" ");
+ names.forEach(function(name) {
+ this.on(name, callback);
+ }, this);
+ return;
+ }
+
+ if (
+ eventName === "change" ||
+ eventName === "added" ||
+ eventName === "removed"
+ ) {
+ // native CustomEvent handlers - cash the generic handlers so we can remove
+ this._gsEventHandler = this._gsEventHandler || {};
+ this._gsEventHandler[eventName] = function(event) {
+ callback(event, event.detail);
+ };
+ this.el.addEventListener(eventName, this._gsEventHandler[eventName]);
+ } else {
+ // still JQuery events
+ this.$el.on(eventName, callback);
+ }
+ };
+
+ /** unsubscribe from the 'on' event */
+ GridStack.prototype.off = function(eventName) {
+ // check for array of names being passed instead
+ if (eventName.indexOf(" ") !== -1) {
+ var names = eventName.split(" ");
+ names.forEach(function(name) {
+ this.off(name, callback);
+ }, this);
+ return;
+ }
+
+ if (
+ eventName === "change" ||
+ eventName === "added" ||
+ eventName === "removed"
+ ) {
+ // remove native CustomEvent handlers
+ if (this._gsEventHandler && this._gsEventHandler[eventName]) {
+ this.el.removeEventListener(eventName, this._gsEventHandler[eventName]);
+ delete this._gsEventHandler[eventName];
+ }
+ } else {
+ // still JQuery events
+ this.$el.off(eventName);
+ }
+ };
+
+ // legacy method renames
+ GridStack.prototype.setGridWidth = obsolete(
+ GridStack.prototype.column,
+ "setGridWidth",
+ "column",
+ "v0.5.3"
+ );
+ GridStack.prototype.setColumn = obsolete(
+ GridStack.prototype.column,
+ "setColumn",
+ "column",
+ "v0.6.4"
+ );
+ GridStackEngine.prototype.getGridHeight = obsolete(
+ GridStackEngine.prototype.getRow,
+ "getGridHeight",
+ "getRow",
+ "v1.0.0"
+ );
+
+ scope.GridStack = GridStack;
+ scope.GridStack.Utils = Utils;
+ scope.GridStack.Engine = GridStackEngine;
+ scope.GridStack.DragDropPlugin = GridStackDragDropPlugin;
+
+ /**
+ * initializing the HTML element, or selector string, into a grid will return the grid. Calling it again will
+ * simply return the existing instance (ignore any passed options).
+ */
+ GridStack.init = function(opts, elOrString) {
+ if (!elOrString) {
+ elOrString = ".grid-stack";
+ }
+ var el = $(elOrString).get(0);
+ if (!el) return;
+ if (!el.gridstack) {
+ el.gridstack = new GridStack(el, Utils.clone(opts));
+ }
+ return el.gridstack;
+ };
+
+ /**
+ * Will initialize a list of elements (given a selector) and return an array of grids.
+ */
+ GridStack.initAll = function(opts, selector) {
+ if (!selector) {
+ selector = ".grid-stack";
+ }
+ var grids = [];
+ $(selector).each(function(index, el) {
+ if (!el.gridstack) {
+ el.gridstack = new GridStack(el, Utils.clone(opts));
+ }
+ grids.push(el.gridstack);
+ });
+ return grids;
+ };
+
+ return scope.GridStack;
});
diff --git a/pandora_console/include/javascript/multiselect_filtered.js b/pandora_console/include/javascript/multiselect_filtered.js
index 27135c6843..7976158740 100644
--- a/pandora_console/include/javascript/multiselect_filtered.js
+++ b/pandora_console/include/javascript/multiselect_filtered.js
@@ -113,7 +113,9 @@ function reloadContent(id, url, options, side, noneStr) {
data.side = side;
data.group_recursion = $("#checkbox-id-group-recursion-" + current).prop(
"checked"
- );
+ )
+ ? 1
+ : 0;
data.group_id = $("#id-group-" + current).val();
$.ajax({
@@ -139,8 +141,8 @@ function reloadContent(id, url, options, side, noneStr) {
for (var [value, label] of items) {
if (
- $("#" + opposite + " option[value=" + value + "]").length == 0 &&
- $("#tmp-" + current + " option[value=" + value + "]").length == 0
+ $("#" + opposite + " option[value='" + value + "']").length == 0 &&
+ $("#tmp-" + current + " option[value='" + value + "']").length == 0
) {
// Does not exist in opposite box nor is filtered.
$("#" + current).append(new Option(label, value));
diff --git a/pandora_console/include/javascript/openlayers.pandora.js b/pandora_console/include/javascript/openlayers.pandora.js
index bc4a7b99bf..8d8002756a 100755
--- a/pandora_console/include/javascript/openlayers.pandora.js
+++ b/pandora_console/include/javascript/openlayers.pandora.js
@@ -1,6 +1,6 @@
// Pandora FMS - http://pandorafms.com
// ==================================================
-// Copyright (c) 2005-2009 Artica Soluciones Tecnologicas
+// Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
// Please see http://pandorafms.org for full contribution list
// This program is free software; you can redistribute it and/or
diff --git a/pandora_console/include/javascript/pandora_dashboards.js b/pandora_console/include/javascript/pandora_dashboards.js
index e50204b8e5..d5003d104f 100644
--- a/pandora_console/include/javascript/pandora_dashboards.js
+++ b/pandora_console/include/javascript/pandora_dashboards.js
@@ -1,4 +1,4 @@
-/* globals $ load_modal TreeController, forced_title_callback, createVisualConsole, tinyMCE*/
+/* globals $, GridStack, load_modal, TreeController, forced_title_callback, createVisualConsole, tinyMCE*/
// eslint-disable-next-line no-unused-vars
function show_option_dialog(settings) {
load_modal({
@@ -56,8 +56,7 @@ function showGroup() {
// eslint-disable-next-line no-unused-vars
function initialiceLayout(data) {
- var $grid = $(".grid-stack");
- $grid.gridstack({
+ var grid = GridStack.init({
float: true,
column: 12,
alwaysShowResizeHandle: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
@@ -71,9 +70,7 @@ function initialiceLayout(data) {
draggable: false
});
- var grid = $grid.data("gridstack");
-
- var positionGrid = $grid[0].getBoundingClientRect();
+ var positionGrid = 0; //grid[0].getBoundingClientRect();
// var gridHeight = positionGrid.height;
var gridWidth = positionGrid.width;
@@ -198,8 +195,8 @@ function initialiceLayout(data) {
addSpinner(element);
// Width and height.
- var newWidth = elem.attr("data-gs-width");
- var newHeight = elem.attr("data-gs-height");
+ var newWidth = $(elem).attr("data-gs-width");
+ var newHeight = $(elem).attr("data-gs-height");
$.ajax({
method: "post",
@@ -237,7 +234,7 @@ function initialiceLayout(data) {
var parentElement = $("#widget-" + id).parent();
grid.enableMove(parentElement, true);
grid.enableResize(parentElement, true);
- grid.grid.float = false;
+ grid.float(false);
}
},
error: function(error) {
@@ -451,7 +448,7 @@ function initialiceLayout(data) {
if ($("#checkbox-edit-mode").is(":checked")) {
grid.movable(".grid-stack-item", true);
grid.resizable(".grid-stack-item", true);
- grid.grid.float = false;
+ grid.float(false);
$(".header-options").show();
$(".add-widget").show();
$(".new-widget-message").hide();
@@ -460,7 +457,7 @@ function initialiceLayout(data) {
} else {
grid.movable(".grid-stack-item", false);
grid.resizable(".grid-stack-item", false);
- grid.grid.float = true;
+ grid.float(true);
$(".header-options").hide();
$(".add-widget").hide();
$(".new-widget-message").show();
diff --git a/pandora_console/include/javascript/pandora_snmp_browser.js b/pandora_console/include/javascript/pandora_snmp_browser.js
index 961619b80b..e2d8d9f792 100644
--- a/pandora_console/include/javascript/pandora_snmp_browser.js
+++ b/pandora_console/include/javascript/pandora_snmp_browser.js
@@ -25,6 +25,7 @@ function snmpBrowse() {
var snmp3_auth_pass = $("#password-snmp3_browser_auth_pass").val();
var snmp3_privacy_method = $("#snmp3_browser_privacy_method").val();
var snmp3_privacy_pass = $("#password-snmp3_browser_privacy_pass").val();
+ var server_to_exec = $("#server_to_exec").val();
var ajax_url = $("#hidden-ajax_url").val();
// Prepare the AJAX call
@@ -41,6 +42,7 @@ function snmpBrowse() {
params["snmp3_browser_auth_pass"] = snmp3_auth_pass;
params["snmp3_browser_privacy_method"] = snmp3_privacy_method;
params["snmp3_browser_privacy_pass"] = snmp3_privacy_pass;
+ params["server_to_exec"] = server_to_exec;
params["action"] = "snmptree";
params["page"] = "include/ajax/snmp_browser.ajax";
@@ -541,7 +543,7 @@ function setOID() {
}
/**
- * Create module on selected module_target (agent, networlk component or policy).
+ * Create module on selected module_target (agent, network component or policy).
*
* @param string module_target Target to create module.
* @param return_values Return snmp values.
diff --git a/pandora_console/include/javascript/pandora_ui.js b/pandora_console/include/javascript/pandora_ui.js
index 15b7f83217..35d46f79f0 100644
--- a/pandora_console/include/javascript/pandora_ui.js
+++ b/pandora_console/include/javascript/pandora_ui.js
@@ -249,22 +249,24 @@ function load_modal(settings) {
});
} else {
settings.form.forEach(function(element) {
- $("#" + element + " :input").each(function() {
- // TODO VALIDATE ALL INPUTS.
- if (this.type == "file") {
- if ($(this).prop("files")[0]) {
- formdata.append(this.name, $(this).prop("files")[0]);
- }
- } else {
- if ($(this).attr("type") == "checkbox") {
- if (this.checked) {
- formdata.append(this.name, "on");
+ $("#" + element + " :input, #" + element + " textarea").each(
+ function() {
+ // TODO VALIDATE ALL INPUTS.
+ if (this.type == "file") {
+ if ($(this).prop("files")[0]) {
+ formdata.append(this.name, $(this).prop("files")[0]);
}
} else {
- formdata.append(this.name, $(this).val());
+ if ($(this).attr("type") == "checkbox") {
+ if (this.checked) {
+ formdata.append(this.name, "on");
+ }
+ } else {
+ formdata.append(this.name, $(this).val());
+ }
}
}
- });
+ );
});
}
@@ -494,3 +496,81 @@ function generalShowMsg(data, idMsg) {
]
});
}
+
+function infoMessage(data, idMsg) {
+ var title = data.title;
+ var err_messge = data.text;
+
+ if (idMsg == null) {
+ idMsg = uniqId();
+ }
+
+ if ($("#" + idMsg).length === 0) {
+ $("body").append('');
+ $("#" + idMsg).empty();
+ }
+
+ $("#err_msg").empty();
+ $("#err_msg").html("\n\n" + err_messge);
+
+ $("#" + idMsg)
+ .dialog({
+ height: 250,
+ width: 528,
+ opacity: 1,
+ modal: true,
+ position: {
+ my: "center",
+ at: "center",
+ of: window,
+ collision: "fit"
+ },
+ title: data.title,
+ buttons: [
+ {
+ class:
+ "ui-widget ui-state-default ui-corner-all ui-button-text-only sub ok submit-next",
+ text: "Retry",
+ click: function(e) {
+ handleConnection();
+ }
+ },
+ {
+ class:
+ "ui-widget ui-state-default ui-corner-all ui-button-text-only sub ok submit-cancel",
+ text: "Close",
+ click: function() {
+ $(this).dialog("close");
+ }
+ }
+ ],
+
+ open: function(event, ui) {
+ $(".ui-widget-overlay").addClass("error-modal-opened");
+ },
+ close: function(event, ui) {
+ $(".ui-widget-overlay").removeClass("error-modal-opened");
+ }
+ })
+ .show();
+}
+
+function reveal_password(name) {
+ var passwordElement = $("#password-" + name);
+ var revealElement = $("#reveal_password_" + name);
+ var imagesPath = "";
+
+ if ($("#hidden-metaconsole_activated").val() == 1) {
+ imagesPath = "../../images/";
+ } else {
+ imagesPath = "images/";
+ }
+
+ if (passwordElement.attr("type") == "password") {
+ passwordElement.attr("type", "text");
+ revealElement.attr("src", imagesPath + "eye_hide.png");
+ } else {
+ passwordElement.attr("type", "password");
+ revealElement.attr("src", imagesPath + "eye_show.png");
+ }
+}
diff --git a/pandora_console/include/javascript/tree/TreeController.js b/pandora_console/include/javascript/tree/TreeController.js
index 1aeb7ad799..17f0539848 100644
--- a/pandora_console/include/javascript/tree/TreeController.js
+++ b/pandora_console/include/javascript/tree/TreeController.js
@@ -1,6 +1,6 @@
// Pandora FMS - http://pandorafms.com
// ==================================================
-// Copyright (c) 2005-2010 Artica Soluciones Tecnologicas
+// Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
// Please see http://pandorafms.org for full contribution list
// This program is free software; you can redistribute it and/or
diff --git a/pandora_console/include/lib/Agent.php b/pandora_console/include/lib/Agent.php
index f7a39bdab6..f5535e72d2 100644
--- a/pandora_console/include/lib/Agent.php
+++ b/pandora_console/include/lib/Agent.php
@@ -15,7 +15,7 @@
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
- * Copyright (c) 2005-2019 Artica Soluciones Tecnologicas
+ * Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
* Please see http://pandorafms.org for full contribution list
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -104,13 +104,22 @@ class Agent extends Entity
/**
* Return last value (status) of the agent.
*
+ * @param boolean $force Force recalculation.
+ *
* @return integer Status of the agent.
*/
- public function lastStatus()
+ public function lastStatus(bool $force=false)
{
+ if ($force === true) {
+ return \agents_get_status(
+ $this->id_agente()
+ );
+ }
+
return \agents_get_status_from_counts(
$this->toArray()
);
+
}
diff --git a/pandora_console/include/lib/Dashboard/Manager.php b/pandora_console/include/lib/Dashboard/Manager.php
index 07e253a2d8..eebfc3233c 100644
--- a/pandora_console/include/lib/Dashboard/Manager.php
+++ b/pandora_console/include/lib/Dashboard/Manager.php
@@ -702,8 +702,8 @@ class Manager
FROM tdashboard td
LEFT JOIN twidget_dashboard twd
ON td.id = twd.id_dashboard
- WHERE (td.id_group IN (%s) AND td.id_user = '') OR
- td.id_user = '%s' %s
+ WHERE ((td.id_group IN (%s) AND td.id_user = '') OR
+ td.id_user = '%s') %s
GROUP BY td.id
ORDER BY name%s",
$string_groups,
diff --git a/pandora_console/include/lib/Dashboard/Widgets/agent_module.php b/pandora_console/include/lib/Dashboard/Widgets/agent_module.php
index 9913b28aaf..6bb1bf4e37 100644
--- a/pandora_console/include/lib/Dashboard/Widgets/agent_module.php
+++ b/pandora_console/include/lib/Dashboard/Widgets/agent_module.php
@@ -14,7 +14,7 @@
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
- * Copyright (c) 2005-2019 Artica Soluciones Tecnologicas
+ * Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
* Please see http://pandorafms.org for full contribution list
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -27,6 +27,8 @@
*/
namespace PandoraFMS\Dashboard;
+use PandoraFMS\Agent;
+use PandoraFMS\Module;
/**
* Agent module Widgets.
@@ -324,7 +326,7 @@ class AgentModuleWidget extends Widget
}
foreach ($agents as $agent) {
- if (!users_access_to_agent($agent['id_agente'])) {
+ if (users_access_to_agent($agent['id_agente']) === false) {
continue;
}
@@ -343,8 +345,10 @@ class AgentModuleWidget extends Widget
foreach ($modules_by_name as $module) {
$row['modules'][$module['name']] = null;
foreach ($module['id'] as $module_id) {
- if (array_key_exists($module_id, $agent_modules)) {
- $row['modules'][$module['name']] = modules_get_agentmodule_status($module_id);
+ if (array_key_exists($module_id, $agent_modules) === true) {
+ $row['modules'][$module['name']] = modules_get_agentmodule_status(
+ $module_id
+ );
break;
}
}
@@ -361,12 +365,16 @@ class AgentModuleWidget extends Widget
* Draw table Agent/Module.
*
* @param array $visualData Data for draw.
+ * @param array $allModules Data for th draw.
*
* @return string Html output.
*/
- private function generateViewAgentModule(array $visualData):string
- {
- $table_data = '';
+ private function generateViewAgentModule(
+ array $visualData,
+ array $allModules
+ ):string {
+ $style = 'display:flex; width:100%; height:100%; margin: 10px;';
+ $table_data = '
';
$table_data .= '
';
if (empty($visualData) === false) {
@@ -374,20 +382,7 @@ class AgentModuleWidget extends Widget
$array_names = [];
- foreach ($visualData as $data) {
- foreach ($data['modules'] as $module_name => $module) {
- if ($module === null
- || in_array($module_name, $array_names)
- ) {
- continue;
- } else {
- $array_names[] = $module_name;
- }
- }
- }
-
- natcasesort($array_names);
- foreach ($array_names as $module_name) {
+ foreach ($allModules as $module_name) {
$file_name = ui_print_truncate_text(
$module_name,
'module_small',
@@ -444,14 +439,17 @@ class AgentModuleWidget extends Widget
foreach ($row['modules'] as $module_name => $module) {
if ($module === null) {
- if (in_array($module_name, $array_names)) {
- $table_data .= "";
+ if (in_array($module_name, $allModules) === true) {
+ $style = 'background-color: transparent;';
+ $table_data .= " | ";
$table_data .= ' | ';
} else {
continue;
}
} else {
- $table_data .= "";
+ $style = 'text-align: center;';
+ $style .= ' background-color: transparent;';
+ $table_data .= " | ";
switch ($module) {
case AGENT_STATUS_NORMAL:
$table_data .= \ui_print_status_image(
@@ -592,70 +590,49 @@ class AgentModuleWidget extends Widget
return $output;
}
- if (isset($this->values['mAgents']) === true
- && empty($this->values['mAgents']) === false
- ) {
- $sql = sprintf(
- 'SELECT id_agente,nombre,alias
- FROM tagente
- WHERE id_agente IN (%s)
- ORDER BY id_agente',
- $this->values['mAgents']
- );
- $agents = db_get_all_rows_sql($sql);
- if ($agents === false) {
- $agents = [];
+ // Estract info all modules selected.
+ $target_modules = explode(',', $this->values['mModules']);
+ $all_modules = Module::search(
+ ['id_agente_modulo' => $target_modules]
+ );
+ $reduceAllModules = array_reduce(
+ $all_modules,
+ function ($carry, $item) {
+ $carry[$item->name()] = null;
+ return $carry;
}
+ );
- $modules = false;
- if (isset($this->values['mModules']) === true
- && empty($this->values['mModules']) === false
- ) {
- $sql = sprintf(
- 'SELECT nombre
- FROM tagente_modulo
- WHERE id_agente_modulo IN (%s)',
- $this->values['mModules']
+ \ksort($reduceAllModules);
+
+ $visualData = [];
+ // Estract info agents selected.
+ $target_agents = explode(',', $this->values['mAgents']);
+ foreach ($target_agents as $agent_id) {
+ try {
+ $agent = new Agent($agent_id);
+ $visualData[$agent_id]['agent_status'] = $agent->lastStatus();
+ $visualData[$agent_id]['agent_name'] = $agent->name();
+ $visualData[$agent_id]['agent_alias'] = $agent->alias();
+
+ $modules = $agent->searchModules(
+ ['id_agente_modulo' => $target_modules]
);
- $arrayNames = db_get_all_rows_sql($sql);
- $names = array_reduce(
- $arrayNames,
- function ($carry, $item) {
- $carry[] = $item['nombre'];
- return $carry;
- }
- );
-
- $sql = sprintf(
- 'SELECT id_agente_modulo,nombre
- FROM tagente_modulo
- WHERE id_agente IN (%s)
- AND nombre IN ("%s")
- AND delete_pending = 0
- ORDER BY nombre',
- $this->values['mAgents'],
- implode('","', $names)
- );
-
- $modules = index_array(
- db_get_all_rows_sql($sql),
- 'id_agente_modulo',
- 'nombre'
- );
+ $visualData[$agent_id]['modules'] = $reduceAllModules;
+ foreach ($modules as $module) {
+ $visualData[$agent_id]['modules'][$module->name()] = $module->getStatus()->estado();
+ }
+ } catch (Exception $e) {
+ echo 'Error: '.$e->getMessage();
}
-
- if ($modules === false) {
- $modules = [];
- }
- } else {
- $agents = [];
- $modules = [];
}
- $visualData = $this->generateDataAgentModule($agents, $modules);
-
- $output = $this->generateViewAgentModule($visualData);
+ $allModules = array_keys($reduceAllModules);
+ $output = $this->generateViewAgentModule(
+ $visualData,
+ $allModules
+ );
return $output;
}
diff --git a/pandora_console/include/lib/Dashboard/Widgets/alerts_fired.php b/pandora_console/include/lib/Dashboard/Widgets/alerts_fired.php
index 4aadb73dae..2a248d7306 100755
--- a/pandora_console/include/lib/Dashboard/Widgets/alerts_fired.php
+++ b/pandora_console/include/lib/Dashboard/Widgets/alerts_fired.php
@@ -14,7 +14,7 @@
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
- * Copyright (c) 2005-2019 Artica Soluciones Tecnologicas
+ * Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
* Please see http://pandorafms.org for full contribution list
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/pandora_console/include/lib/Dashboard/Widgets/clock.php b/pandora_console/include/lib/Dashboard/Widgets/clock.php
index 8ad514e023..5d90f0f863 100644
--- a/pandora_console/include/lib/Dashboard/Widgets/clock.php
+++ b/pandora_console/include/lib/Dashboard/Widgets/clock.php
@@ -14,7 +14,7 @@
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
- * Copyright (c) 2005-2019 Artica Soluciones Tecnologicas
+ * Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
* Please see http://pandorafms.org for full contribution list
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/pandora_console/include/lib/Dashboard/Widgets/custom_graph.php b/pandora_console/include/lib/Dashboard/Widgets/custom_graph.php
index b35ce233a1..7ab6e7c0fe 100644
--- a/pandora_console/include/lib/Dashboard/Widgets/custom_graph.php
+++ b/pandora_console/include/lib/Dashboard/Widgets/custom_graph.php
@@ -14,7 +14,7 @@
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
- * Copyright (c) 2005-2019 Artica Soluciones Tecnologicas
+ * Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
* Please see http://pandorafms.org for full contribution list
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/pandora_console/include/lib/Dashboard/Widgets/events_list.php b/pandora_console/include/lib/Dashboard/Widgets/events_list.php
index 8c896aa75f..ad19a48d43 100644
--- a/pandora_console/include/lib/Dashboard/Widgets/events_list.php
+++ b/pandora_console/include/lib/Dashboard/Widgets/events_list.php
@@ -14,7 +14,7 @@
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
- * Copyright (c) 2005-2019 Artica Soluciones Tecnologicas
+ * Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
* Please see http://pandorafms.org for full contribution list
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/pandora_console/include/lib/Dashboard/Widgets/example.php b/pandora_console/include/lib/Dashboard/Widgets/example.php
index 8c0664464c..2c163214d8 100644
--- a/pandora_console/include/lib/Dashboard/Widgets/example.php
+++ b/pandora_console/include/lib/Dashboard/Widgets/example.php
@@ -14,7 +14,7 @@
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
- * Copyright (c) 2005-2019 Artica Soluciones Tecnologicas
+ * Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
* Please see http://pandorafms.org for full contribution list
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/pandora_console/include/lib/Dashboard/Widgets/graph_module_histogram.php b/pandora_console/include/lib/Dashboard/Widgets/graph_module_histogram.php
index 948b20acc7..9a052ee68a 100644
--- a/pandora_console/include/lib/Dashboard/Widgets/graph_module_histogram.php
+++ b/pandora_console/include/lib/Dashboard/Widgets/graph_module_histogram.php
@@ -14,7 +14,7 @@
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
- * Copyright (c) 2005-2019 Artica Soluciones Tecnologicas
+ * Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
* Please see http://pandorafms.org for full contribution list
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/pandora_console/include/lib/Dashboard/Widgets/groups_status.php b/pandora_console/include/lib/Dashboard/Widgets/groups_status.php
index 5b7fa16395..8ebe0ff93f 100755
--- a/pandora_console/include/lib/Dashboard/Widgets/groups_status.php
+++ b/pandora_console/include/lib/Dashboard/Widgets/groups_status.php
@@ -14,7 +14,7 @@
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
- * Copyright (c) 2005-2019 Artica Soluciones Tecnologicas
+ * Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
* Please see http://pandorafms.org for full contribution list
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/pandora_console/include/lib/Dashboard/Widgets/maps_made_by_user.php b/pandora_console/include/lib/Dashboard/Widgets/maps_made_by_user.php
index f480c45389..e449df4b82 100644
--- a/pandora_console/include/lib/Dashboard/Widgets/maps_made_by_user.php
+++ b/pandora_console/include/lib/Dashboard/Widgets/maps_made_by_user.php
@@ -14,7 +14,7 @@
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
- * Copyright (c) 2005-2019 Artica Soluciones Tecnologicas
+ * Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
* Please see http://pandorafms.org for full contribution list
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -368,26 +368,27 @@ class MapsMadeByUser extends Widget
// of the visual consoles.
$output .= ' |