(function() { var MODULE_LOAD_URL = "/standalone/modules"; var global = (function() { return this; })(); if (!global && typeof window != "undefined") global = window; // can happen in strict mode var commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg; var cjsRequireRegExp = /require\s*\(\s*["']([^'"\s]+)["']\s*\)/g; function getInlineDeps(fn) { var deps = []; if (fn.length) { fn.toString().replace(commentRegExp, "") .replace(cjsRequireRegExp, function (match, dep, index, str) { var i = index; while (str.charCodeAt(i -= 1) <= 32) {} if (str.charAt(i) !== ".") deps.push(dep); }); deps = ["require", "exports", "module"].concat(deps); } return deps; } var define = function(name, deps, callback) { if (typeof name !== "string") { callback = deps; deps = name; name = null; } if (deps && !Array.isArray(deps)) { callback = deps; deps = null; } if (nextModule) { if (!name || name == nextModule.name) { name = nextModule.name; deps = deps || nextModule.deps; nextModule = null; } } if (!name) return defQueue.push([deps, callback]); if (define.loaded[name]) return; if (!deps && typeof callback == "function") deps = getInlineDeps(callback); define.loaded[name] = { id: name, deps: normalizeNames(name, deps || []), factory: callback, exports: {}, packaged: true }; if (define.loading[name]) delete define.loading[name]; if (define.lastModule) define.pending.push(name); else define.lastModule = name; }; var defQueue = []; var nextModule; var addToLoadQueue = function(missing, deps, callback, errback) { var toLoad = missing.length; var map = {}; define.queue.push({ deps: deps, map: map, toLoad: toLoad, callback: callback, errback: errback }); for (var i = 0; i < missing.length; ++i) { var p = missing[i]; map[p] = 1; if (!define.loading[p]) { require.load(p); define.loading[p] = 1; } } }; var processLoadQueue = function(err, id) { var changed = false; if (err) { if (!id) id = err.id; define.errors[id] = err; define.queue.forEach(function(r) { if (r.map[id]) { r.toLoad = -1; if (r.errback) r.errback(err); } }); if (define.lastModule == id) define.lastModule = null; define.pending = define.pending.filter(function(p) { return p != id; }); changed = true; } else if (id && !defQueue.length && !define.loaded[id]) { defQueue = [config.shim && config.shim[id] || [[], null]]; } if (defQueue.length) { if (defQueue.length > 1) throw new Error("more than one module in defqueue"); define(id, defQueue[0][0], defQueue[0][1]); defQueue.length = 0; } var pending = define.pending; define.queue.forEach(function(r) { pending.forEach(function(id) { if (r.map[id]) r.toLoad--; }); if (r.map[define.lastModule]) r.toLoad--; if (!r.toLoad) { changed = true; _require("", r.deps, r.callback, r.errback); } }); define.lastModule = null; if (pending.length) define.pending = []; if (changed) { define.queue = define.queue.filter(function(r) { return r.toLoad > 0; }); } }; define.amd = {}; define.queue = []; define.loaded = {}; define.errors = {}; define.loading = {}; define.pending = []; define.modules = { require: 1, exports: 1, module: 1 }; define.fetchedUrls = {}; var activateModule = function(name) { var module = define.loaded[name]; var exports = module.exports; if (typeof module.factory !== "function") { exports = module.factory; } else { var req = function(path, callback) { return _require(name, path, callback); }; req.toUrl = function(namePlusExt, _1, _2, skipBalancers) { return require.toUrl(normalizeName(name, namePlusExt), null, null, skipBalancers); }; req.config = require.config; var missing = checkMissing(module.deps); if (missing.length) return missing; module.define = define; var specialModules = { require: req, exports: exports, module: module, }; define.modules[name] = exports; var args = module.deps.slice(0, module.factory.length); var returnValue = args.length ? module.factory.apply(module, args.map(function(name) { return specialModules[name] || lookup(name); })) : module.factory(req, exports, module); exports = returnValue == undefined ? module.exports : returnValue; } delete define.loaded[name]; define.modules[name] = exports; }; var checkMissing = function(deps, seen, missing) { missing = missing || {}; seen = seen || {}; for (var i = 0; i < deps.length; ++i) { var depName = deps[i]; if (!define.modules[depName]) { var dep = define.loaded[depName]; if (!dep) missing[depName] = 1; else if (!missing[depName] && !seen[depName]) { seen[depName] = 1; checkMissing(dep.deps, seen, missing); } } } return Object.keys(missing); }; var lookup = function(moduleName) { var mod = define.modules[moduleName]; if (mod === undefined && define.loaded[moduleName]) { activateModule(moduleName); mod = define.modules[moduleName]; } return mod; }; var _require = function(parentId, moduleName, callback, errback) { if (typeof moduleName === "string") { var depName = normalizeName(parentId, moduleName); var module = lookup(depName); if (module !== undefined) { if (typeof callback == "function") callback(module); return module; } else if (typeof importScripts != "undefined") { addToLoadQueue([depName], [depName]); return lookup(depName); } } else if (Array.isArray(moduleName)) { var deps = normalizeNames(parentId, moduleName); var missing = checkMissing(deps); if (!missing.length) { var args = deps.map(lookup); return callback && callback.apply(null, args); } else { return addToLoadQueue(missing, deps, callback, errback); } } }; var normalizeName = function(parentId, moduleName) { if (moduleName.indexOf("!") !== -1) { var chunks = moduleName.split("!"); return normalizeName(parentId, chunks[0]) + "!" + normalizeName(parentId, chunks[1]); } if (moduleName.charAt(0) == ".") { var base = parentId.split("/").slice(0, -1).join("/"); moduleName = (base || parentId) + "/" + moduleName; while (moduleName.indexOf(".") !== -1 && previous != moduleName) { var previous = moduleName; moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, ""); } } return moduleName; }; var normalizeNames = function(parentId, moduleNames) { return moduleNames.map(function(name) { return normalizeName(parentId, name); }); }; var require = function(module, callback, errback) { return _require("", module, callback, errback); }; var config = require.config = function(cfg) { if (cfg.baseUrl) config.baseUrl = cfg.baseUrl.replace(/\/*$/, "/"); if (cfg.host) host = cfg.host; if (Array.isArray(cfg.packages)) { cfg.packages.forEach(function(pkg) { if (typeof pkg === "string") pkg = { name: pkg }; config.packages[pkg.name] = { name: pkg.name, location: (pkg.location || pkg.name).replace(/\/*$/, "/"), main: (pkg.main || "main").replace(/\.js$/, "").replace(/^\.\//, "") }; }); } else if (cfg.packages) { config.packages = cfg.packages; } cfg.paths && Object.keys(cfg.paths).forEach(function(p) { config.paths[p] = cfg.paths[p]; }); if (cfg.useCache && global.caches && (location.protocol === "https:" || location.hostname == "localhost")) { config.useCache = true; checkCache(); } if (cfg.transform) config.transform = cfg.transform; if (cfg.baseUrlLoadBalancers) config.baseUrlLoadBalancers = cfg.baseUrlLoadBalancers; if (cfg.MODULE_LOAD_URL) require.MODULE_LOAD_URL = cfg.MODULE_LOAD_URL; }; require.resetConfig = function() { config.packages = Object.create(null); config.paths = Object.create(null); config.baseUrl = ""; config.useCache = false; config.transform = ""; }; require.getConfig = function() { var script = document.querySelector("script[src*=mini_require]"); return { packages: config.packages, paths: config.paths, baseUrl: config.baseUrl, useCache: config.useCache, transform: config.transform, host: host, requireSourceUrl: script && script.src, MODULE_LOAD_URL: require.MODULE_LOAD_URL, }; }; require.resetConfig(); define.undef = require.undef = function(module, recursive) { module = normalizeName("", module); if (recursive) { var root = (module + "/").replace(/\/+$/, "/"); undefAll(root, define.errors); undefAll(root, define.loaded); undefAll(root, define.modules); undefAll(root, define.loading); } else { undefOne(module, require.toUrl(module, ".js")); } }; function undefOne(module, path) { delete define.errors[module]; delete define.loaded[module]; delete define.modules[module]; delete define.loading[module]; delete define.fetchedUrls[path]; } function undefAll(module, hash) { Object.keys(hash).forEach(function(key) { var i = key.indexOf("!") + 1; if (key.lastIndexOf(module, 0) == 0) undefOne(key, require.toUrl(key, ".js")); if (i) { var plugin = key.slice(0, i - 1); var resource = key.slice(i); if (resource.lastIndexOf(module, 0) == 0 || plugin.lastIndexOf(module, 0) == 0) { undefOne(key, require.toUrl(key, "")); undefOne(resource, require.toUrl(resource, "")); } } }); } require.MODULE_LOAD_URL = MODULE_LOAD_URL; require.toUrl = function(moduleName, ext, skipExt, skipBalancers) { var absRe = /^([\w\+\.\-]+:|\/)/; var index = moduleName.indexOf("!"); if (index !== -1 || !ext || /^\//.test(moduleName)) ext = ""; var paths = config.paths; var pkgs = config.packages; var testPath = moduleName, tail = ""; while (testPath) { if (paths[testPath]) { moduleName = paths[testPath] + tail; break; } if (pkgs[testPath]) { moduleName = pkgs[testPath].location + (tail || pkgs[testPath].main); break; } var i = testPath.lastIndexOf("/"); if (i === -1) break; tail = testPath.substr(i) + tail; testPath = testPath.slice(0, i); } if (skipExt) return testPath; var url = ext == ".js" && moduleName.slice(-3) == ext ? moduleName : moduleName + ext; if (!absRe.test(url)) { if (ext == ".js" && require.config.transform) url = ("~/" + require.config.transform + "/" + url).replace("//", "/"); url = (config.baseUrl || require.MODULE_LOAD_URL + "/") + url; } if (url[0] === "/" && config.baseUrlLoadBalancers && !skipBalancers && !config.useCache) { var n = Math.abs(hashCode(url)) % config.baseUrlLoadBalancers.length; url = config.baseUrlLoadBalancers[n] + url; } if (url[0] == "/") url = host + url; return url; }; function hashCode(string) { var result = 0, i, chr, len; if (string.length == 0) return result; for (i = 0, len = string.length; i < len; i++) { chr = string.charCodeAt(i); result = ((result << 5) - result) + chr; result |= 0; // Convert to 32bit integer } return result; } var loadScriptWithTag = function(path, id, callback) { if (typeof importScripts == "function") { nextModule = { name: id, deps: null }; if (path[0] == "/") path = host + path; importScripts(path); return callback(null, id); } var head = document.head || document.documentElement; var s = document.createElement("script"); s.src = path; s.charset = "utf-8"; s.async = true; if (path.lastIndexOf(require.MODULE_LOAD_URL, 0) == 0 && path[0] != "/") s.crossOrigin = true; s.onload = s.onreadystatechange = function(_, isAbort) { if (isAbort || !s.readyState || s.readyState == "loaded" || s.readyState == "complete") { s.remove && s.remove(); s = s.onload = s.onreadystatechange = null; if (!isAbort) callback(null, id); } }; s.onerror = function(e) { processLoadQueue({ message: "Error loading script " + id + ":" + path, id: id, path: path }); }; head.appendChild(s); }; function loadText(path, cb) { var xhr = new window.XMLHttpRequest(); xhr.open("GET", path, true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); xhr.onload = function(e) { if (xhr.status > 399 && xhr.status < 600) return cb(xhr); cb(null, xhr.responseText, xhr); }; xhr.onabort = xhr.onerror = function(e) { cb(e); }; xhr.send(""); } var host = location.protocol + "//" + location.hostname + (location.port ? ":" + location.port : ""); var loadScript = function(path, id, callback) { if (!config.useCache) return loadScriptWithTag(path, id, callback); if (!/^https?:/.test(path)) path = host + path; var cb = function(e, val, deps) { if (e) return processLoadQueue({ id: id, path: path }); nextModule = { name: id, deps: deps }; window.eval(val + "\n//# sourceURL=" + path); callback(null, id); return define.loaded[id]; }; loadCached(path, cb); }; var loadCached = function(path, cb) { if (!config.useCache) return loadText(path, cb); function loadNew() { loadText(path, function(e, val, xhr) { var m = cb(e, val); if (!e) { var ETAG = xhr.getResponseHeader("ETAG"); if (!ETAG) return; var res = new Response(val); res.headers.set("ETAG", ETAG); var req = new Request(path); req.headers.set("ETAG", ETAG); if (m && m.deps) res.headers.set("deps", m.deps.join(",")); ideCache.put(req, res).catch(function() { ideCache.delete(path); }); } }); } if (!ideCache && !ideCachePromiss) { checkCache(); } if (ideCachePromiss) { return ideCachePromiss.then(function(i) { if (i) ideCache = i; loadCached(path, cb); }); } ideCache.match(path).then(function(e) { if (!e) return loadNew(); return e.text().then(function(val) { var deps = e.headers.get("deps"); if (typeof deps == "string") deps = deps ? deps.split(",") : []; cb(null, val, deps); }); }).catch(function() { loadNew(); ideCache.delete(path); }); }; var ideCache; var ideCachePromiss; function checkCache() { var baseUrl; ideCachePromiss = config.useCache && window.caches.open("ide").catch(function(e) { console.error(e); config.useCache = ideCachePromiss = ideCache = null; }).then(function(ideCache_) { ideCache = ideCache_; return ideCache ? ideCache.keys() : []; }).then(function(keys) { baseUrl = config.baseUrl; if (baseUrl[0] == "/") baseUrl = host + baseUrl; var val = keys.map(function(r) { var url = r.url; if (url.startsWith(baseUrl)) url = url.slice(baseUrl.length); else if (/^\w+:/.test(url)) return ""; return r.headers.get("etag") + " " + url; }).join("\n") + "\n"; if (val.length <= 1) { ideCachePromiss = null; return ideCache; } return new Promise(function(resolve) { var checked = 0; var buffer = ""; var toDelete = []; post(baseUrl + "__check__", val, function(t) { var e = t.slice(checked); checked = t.length; var parts = (buffer + e).split("\n"); buffer = parts.pop(); for (var i = 0; i < parts.length; i++) { if (parts[i]) { var del = ideCache.delete(baseUrl + parts[i]); toDelete.push(del); if (require.config.transform) { del = ideCache.delete(baseUrl + ("~/" + require.config.transform) + parts[i]); toDelete.push(del); } } } }, function(e, t) { ideCachePromiss = null; Promise.all(toDelete).then(function() { resolve(ideCache); }); setTimeout(function() { setTimeout(function() { config.useCache = false; }, 5000); }, 5000); }); }); }); return ideCachePromiss; } require.clearCache = function(callback) { ideCachePromiss = window.caches.open("ide").then(function(ideCache_) { ideCache = ideCache_; return ideCache.keys(); }).then(function(keys) { var toDelete = keys.map(function(i) { ideCache.delete(i); }); Promise.all(toDelete).then(function() { callback && callback(); }, function(e) { callback && callback(e); }); }); }; function post(path, val, progress, cb) { var xhr = new window.XMLHttpRequest(); xhr.open("POST", path, true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); xhr.onload = function(e) { if (xhr.status > 399 && xhr.status < 600) return cb(xhr); cb(null, xhr.responseText, xhr); }; xhr.onreadystatechange = function(e) { progress(xhr.responseText, xhr); }; xhr.onabort = xhr.onerror = function(e) { cb(e); }; xhr.send(val); } require.load = function(module) { var i = module.indexOf("!") + 1; if (i) { var plugin = module.substring(0, i); module = module.substr(i); if (typeof require[plugin] == "function") { require[plugin](module, processLoadQueue); } else if (config.baseUrl) { if (require[plugin]) return require[plugin][plugin + module] = 1; require[plugin] = Object.create(null); require[plugin][plugin + module] = 1; require([plugin.slice(0, -1)], function(p) { var pending = require[plugin]; definePlugin(plugin, p); Object.keys(pending).forEach(function(p) { delete define.loading[p]; }); require(Object.keys(pending)); }); } else { console.error("require plugin " + plugin + "missing"); } } else { var url = require.toUrl(module, ".js"); if (define.fetchedUrls[url] & 1) return false; define.fetchedUrls[url] |= 1; loadScript(url, module, processLoadQueue); } }; function definePlugin(plugin, p) { require[plugin] = function(moduleName, processLoadQueue) { p.load(moduleName, require, function(value) { define(plugin + moduleName, [], function() { return value; }); processLoadQueue(); }); }; } require["vfs!"] = function(module, callback) { var url = require.MODULE_LOAD_URL + "/~node/" + module; if (define.fetchedUrls[url] & 4) return false; define.fetchedUrls[url] |= 4; define("vfs!" + module, [], { srcUrl: url, path: module }); callback(); }; require["text!"] = function(module, callback) { var url = require.toUrl(module); if (define.fetchedUrls[url] & 2) return false; define.fetchedUrls[url] |= 2; var cb = function(e, val) { if (e) console.error("Couldn't load module " + module, e); define("text!" + module, [], val); callback(); }; loadCached(url, cb); }; require["ace/requirejs/text!"] = function(module, callback) { var url = require.toUrl(module); if (define.fetchedUrls[url] & 2) return false; define.fetchedUrls[url] |= 2; var cb = function(e, val) { if (e) console.error("Couldn't load module " + module, e); define("ace/requirejs/text!" + module, [], val); callback(); }; loadCached(url, cb); }; if (!global.define || !global.define.packaged) { define.original = global.define; global.define = define; global.define.packaged = true; } if (!global.require || !global.require.packaged) { global.require = require; global.require.packaged = true; } if (!global.requirejs) global.requirejs = require; global.miniRequire = require; })(); define("events",[], function(require, exports, module) { var EventEmitter = module.exports = function() {}; EventEmitter.EventEmitter = EventEmitter; var toString = Object.prototype.toString; var isArray = Array.isArray || function(obj) { return toString.call(obj) === '[object Array]'; }; // var defaultMaxListeners = 10; EventEmitter.prototype.setMaxListeners = function(n) { if (!this._events) this._events = {}; this._events.maxListeners = n; }; EventEmitter.prototype.emit = function(type) { if (!this._events) return; var handler = this._events[type]; if (!handler) return; var returnValue; if (typeof handler == 'function') { switch (arguments.length) { case 1: return handler.call(this); case 2: return handler.call(this, arguments[1]); case 3: return handler.call(this, arguments[1], arguments[2]); default: var args = Array.prototype.slice.call(arguments, 1); returnValue = handler.apply(this, args); } } else if (isArray(handler)) { var args = Array.prototype.slice.call(arguments, 1); var listeners = handler.slice(), temp; for (var i = 0, l = listeners.length; i < l; i++) { temp = listeners[i].apply(this, args); if (temp !== undefined) returnValue = temp; } } return returnValue; }; EventEmitter.prototype.addListener = function(type, listener, plugin) { if ('function' !== typeof listener) { throw new Error('addListener only takes instances of Function'); } if (!this._events) this._events = {}; var eventList = this._events[type]; if (!eventList) { this._events[type] = listener; } else if (isArray(eventList)) { if (!eventList.warned) { var m; if (this._events.maxListeners !== undefined) { m = this._events.maxListeners; } else { m = defaultMaxListeners; } if (m && m > 0 && eventList.length > m) { eventList.warned = true; console.error('warning: possible EventEmitter memory ' + 'leak detected. " + eventList.length + " listeners of type "' + type + '" added. ' + 'Use emitter.setMaxListeners() to increase limit.' ); console.trace(); } } eventList.push(listener); } else { this._events[type] = [eventList, listener]; } if (type != "newListener") this.emit('newListener', type, listener); plugin && plugin.addEvent(this, type, listener); return this; }; EventEmitter.prototype.on = EventEmitter.prototype.addListener; EventEmitter.prototype.once = function(type, listener, plugin) { var self = this; var wrapped = function() { self.removeListener(type, listener); return listener.apply(self, arguments); }; wrapped.listener = listener; self.on(type, wrapped, plugin); return this; }; EventEmitter.prototype.removeListener = function(type, listener) { if ('function' !== typeof listener) { throw new Error('removeListener only takes instances of Function'); } if (!this._events || !this._events[type]) return this; var list = this._events[type]; if (isArray(list)) { if (!list.some(function(l, i) { if ((l.listener || l) == listener) { list.splice(i, 1); return true; } })) return this; if (list.length === 0) delete this._events[type]; } else if ((this._events[type].listener || this._events[type]) === listener) { delete this._events[type]; } if (type != "removeListener") this.emit('removeListener', type, listener); return this; }; EventEmitter.prototype.off = EventEmitter.prototype.removeListener; EventEmitter.prototype.removeAllListeners = function(type) { if (type && this._events && this._events[type]) this._events[type] = null; return this; }; EventEmitter.prototype.listeners = function(type) { if (!this._events) this._events = {}; if (!this._events[type]) this._events[type] = []; if (!isArray(this._events[type])) { this._events[type] = [this._events[type]]; } return this._events[type]; }; }); define("path",[], function(require, exports, module) { // // // function normalizeArray(parts, allowAboveRoot) { var up = 0; for (var i = parts.length - 1; i >= 0; i--) { var last = parts[i]; if (last === '.') { parts.splice(i, 1); } else if (last === '..') { parts.splice(i, 1); up++; } else if (up) { parts.splice(i, 1); up--; } } if (allowAboveRoot) { for (; up--; up) { parts.unshift('..'); } } return parts; } var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; var splitPath = function(filename) { return splitPathRe.exec(filename).slice(1); }; exports.resolve = function() { var resolvedPath = '', resolvedAbsolute = false; for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { var path = (i >= 0) ? arguments[i] : '/'; if (typeof path !== 'string') { throw new TypeError('Arguments to path.resolve must be strings'); } else if (!path) { continue; } resolvedPath = path + '/' + resolvedPath; resolvedAbsolute = path.charAt(0) === '/'; } resolvedPath = normalizeArray(resolvedPath.split('/').filter(function(p) { return !!p; }), !resolvedAbsolute).join('/'); return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; }; exports.normalize = function(path) { var isAbsolute = exports.isAbsolute(path), trailingSlash = path.substr(-1) === '/'; path = normalizeArray(path.split('/').filter(function(p) { return !!p; }), !isAbsolute).join('/'); if (!path && !isAbsolute) { path = '.'; } if (path && trailingSlash) { path += '/'; } return (isAbsolute ? '/' : '') + path; }; exports.isAbsolute = function(path) { return path.charAt(0) === '/'; }; exports.join = function() { var paths = Array.prototype.slice.call(arguments, 0); return exports.normalize(paths.filter(function(p, index) { if (typeof p !== 'string') { throw new TypeError('Arguments to path.join must be strings'); } return p; }).join('/')); }; exports.relative = function(from, to) { from = exports.resolve(from).substr(1); to = exports.resolve(to).substr(1); function trim(arr) { var start = 0; for (; start < arr.length; start++) { if (arr[start] !== '') break; } var end = arr.length - 1; for (; end >= 0; end--) { if (arr[end] !== '') break; } if (start > end) return []; return arr.slice(start, end - start + 1); } var fromParts = trim(from.split('/')); var toParts = trim(to.split('/')); var length = Math.min(fromParts.length, toParts.length); var samePartsLength = length; for (var i = 0; i < length; i++) { if (fromParts[i] !== toParts[i]) { samePartsLength = i; break; } } var outputParts = []; for (var i = samePartsLength; i < fromParts.length; i++) { outputParts.push('..'); } outputParts = outputParts.concat(toParts.slice(samePartsLength)); return outputParts.join('/'); }; exports.dirname = function(path) { var result = splitPath(path), root = result[0], dir = result[1]; if (!root && !dir) { return '.'; } if (dir) { dir = dir.substr(0, dir.length - 1); } return root + dir; }; exports.basename = function(path, ext) { var f = splitPath(path)[2]; if (ext && f.substr(-1 * ext.length) === ext) { f = f.substr(0, f.length - ext.length); } return f; }; exports.extname = function(path) { return splitPath(path)[3]; }; exports._makeLong = function(path) { return path; }; }); define("lib/architect/architect",[], function(require, exports, module) { var $build_deps$ = {require: require, exports: exports, module: module}; exports = undefined; module = undefined; function define(name, deps, m) { if (typeof name == "function") { m = name; deps = ["require", "exports", "module"]; name = $build_deps$.module.id } if (typeof name !== "string") { m = deps; deps = name; name = $build_deps$.module.id } if (!m) { m = deps; deps = []; } var ret = typeof m == "function" ? m.apply($build_deps$.module, deps.map(function(n){return $build_deps$[n] || require(n)})) : m if (ret != undefined) $build_deps$.module.exports = ret; if (name != $build_deps$.module.id && $build_deps$.module.define) { $build_deps$.module.define(name, [], function() { return $build_deps$.module.exports }); } } define.amd = true; ( // Module boilerplate to support node.js and AMD. (typeof module !== "undefined" && function (m) { module.exports = m(require('events')); }) || (typeof define === "function" && function (m) { define(["events"], m); }) )(function (events) { "use strict"; var EventEmitter = events.EventEmitter; var exports = {}; var DEBUG = typeof location != "undefined" && location.href.match(/debug=[123]/) ? true : false; if (typeof module === "object") (function () { var dirname = require('path').dirname; var Module = require("module"); exports.loadConfig = loadConfig; exports.resolveConfig = resolveConfig; function loadConfig(configPath, callback) { var config = require(configPath); var base = dirname(configPath); return resolveConfig(config, base, callback); } function resolveConfig(config, base, callback) { if (!callback) return resolveConfigSync(config, base); try { var result = resolveConfigSync(config, base); } catch (e) { var err = e; } process.nextTick(function() { callback(err, result); }); } function resolveConfigSync(config, base) { config.forEach(function (plugin, index) { if (typeof plugin === "string") { plugin = config[index] = { packagePath: plugin }; } if (plugin.hasOwnProperty("packagePath") && !plugin.hasOwnProperty("setup")) { var defaults = resolveModuleSync(base, plugin.packagePath); Object.keys(defaults).forEach(function (key) { if (!plugin.hasOwnProperty(key)) { plugin[key] = defaults[key]; } }); plugin.packagePath = defaults.packagePath; plugin.setup = require(plugin.packagePath); } }); return config; } function resolveModuleSync(base, modulePath) { var packagePath; try { packagePath = resolvePackageSync(base, modulePath + "/package.json"); } catch (err) { if (err.code !== "ENOENT" && err.code !== 'MODULE_NOT_FOUND') throw err; } var metadata = packagePath && require(packagePath).plugin || {}; if (packagePath) { modulePath = dirname(packagePath); } else { modulePath = resolvePackageSync(base, modulePath); } var module = require(modulePath); metadata.provides = metadata.provides || module.provides || []; metadata.consumes = metadata.consumes || module.consumes || []; metadata.packagePath = modulePath; return metadata; } function resolvePackageSync(base, packagePath) { return Module._resolveFilename(packagePath, { paths: Module._nodeModulePaths(base), filename: base + "/package.json", id: base + "/package.json", }); } }()); else (function () { exports.loadConfig = loadConfig; exports.resolveConfig = resolveConfig; function loadConfig(path, callback) { require([path], function (config) { resolveConfig(config, callback); }); } function resolveConfig(config, base, callback, errback) { if (typeof base == "function") return resolveConfig(config, "", arguments[1], arguments[2]); var paths = [], pluginIndexes = {}; config.forEach(function (plugin, index) { if (typeof plugin === "string") { plugin = config[index] = { packagePath: plugin }; } if (plugin.hasOwnProperty("packagePath") && !plugin.hasOwnProperty("setup")) { paths.push((base || "") + plugin.packagePath); pluginIndexes[plugin.packagePath] = index; } }); require(paths, function () { var args = arguments; var err = []; paths.forEach(function (name, i) { var module = args[i]; var plugin = config[pluginIndexes[name]]; if (!module || !plugin) return err.push(name); plugin.setup = module; plugin.provides = module.provides || []; plugin.consumes = module.consumes || []; }); if (err.length) return callback(new Error("Missing plugins: " + err)); callback(null, config); }, errback || function(err) { callback(err); }); } }()); exports.createApp = createApp; exports.Architect = Architect; function checkConfig(config, lookup) { config.forEach(function (plugin) { if (plugin.checked) { return; } if (!plugin.hasOwnProperty("setup")) { throw new Error("Plugin is missing the setup function " + JSON.stringify(plugin)); } if (!plugin.hasOwnProperty("provides")) { throw new Error("Plugin is missing the provides array " + JSON.stringify(plugin)); } if (!plugin.hasOwnProperty("consumes")) { throw new Error("Plugin is missing the consumes array " + JSON.stringify(plugin)); } }); return checkCycles(config, lookup); } function checkCycles(config, lookup) { var plugins = []; config.forEach(function(pluginConfig, index) { plugins.push({ packagePath: pluginConfig.packagePath, provides: pluginConfig.provides.concat(), consumes: pluginConfig.consumes.concat(), i: index }); }); var resolved = { hub: true, app: true }; var changed = true; var sorted = []; while(plugins.length && changed) { changed = false; plugins.concat().forEach(function(plugin) { var consumes = plugin.consumes.concat(); var resolvedAll = true; for (var i=0; i&2\n exit 1\n fi\nfi\n\nsource $ENV/bin/activate\nPYTHON=\"$ENV/bin/python\"\n\nCOMMAND=${COMMAND/\\$PYTHON/$PYTHON}\nCOMMAND=${COMMAND/\\$ENV/$ENV}\neval \"$COMMAND\""); define("plugins/c9.ide.language.codeintel/codeintel",[], function(require, exports, module) { main.consumes = [ "Plugin", "language", "jsonalyzer", "settings", "preferences", "c9", "dialog.question" ]; main.provides = ["language.codeintel"]; return main; function main(options, imports, register) { var Plugin = imports.Plugin; var language = imports.language; var c9 = imports.c9; var preferences = imports.preferences; var settings = imports.settings; var question = imports["dialog.question"]; var preinstalled = options.preinstalled; var plugin = new Plugin("Ajax.org", main.consumes); var server = require("text!./server/codeintel_server.py") .replace(/ {4}/g, " ").replace(/'/g, "'\\''"); var launchCommand = require("text!./server/launch_command.sh") .replace(/ {2,}/g, " "); var showedInstaller = false; var CATALOGS = [ { "lang": "PHP", "name": "PECL", "description": "A collection of PHP Extensions" }, { "lang": "PHP", "name": "Drupal", "description": "A full-featured PHP content management/discussion engine" }, { "lang": "Ruby", "name": "Rails", "description": "Rails" }, ]; plugin.on("load", function() { language.registerLanguageHandler("plugins/c9.ide.language.codeintel/worker/codeintel_worker", onLoadHandler, plugin); language.registerLanguageHandler("plugins/c9.ide.language.codeintel/worker/php_completer", onLoadHandler, plugin); language.registerLanguageHandler("plugins/c9.ide.language.codeintel/worker/css_less_completer", onLoadHandler, plugin); preferences.add({ "Project": { "PHP Support": { position: 1200, "Enable PHP code completion": { position: 410, type: "checkbox", path: "project/php/@completion", }, "PHP Completion Include Paths": { position: 420, type: "textbox", width: 300, path: "project/php/@path", }, "Format Code on Save": { position: 430, type: "checkbox", path: "project/php/@formatOnSave", }, "Custom Code Formatter": { position: 440, type: "textbox", path: "project/php/@formatter", } } } }, plugin); settings.on("read", function(e) { settings.setDefaults("project/php", [ ["path", options.paths.php], ["completion", true], ]); }, plugin); }); function onLoadHandler(err, handler) { if (err) return console.error(err); settings.on("project/php", sendSettings); handler.on("not_installed", onNotInstalled); sendSettings(); function sendSettings() { handler.emit("setup", { server: server, launchCommand: launchCommand, hosted: !options.testing && c9.hosted, enabled: settings.get("project/php/@completion"), paths: { php: makeAbsolutePaths(settings.get("project/php/@path")), }, }); } function makeAbsolutePaths(pathSetting) { return pathSetting.split(":").map(function(path) { if (["/", "~", "\\"].indexOf(path[0]) > -1 || path[1] === ":") return path; return c9.workspaceDir + "/" + path; }).join(":"); } } function onNotInstalled(e) { if (preinstalled || showedInstaller || e.language === "css" || settings.getBool("project/codeintel/@dismiss_installer")) return; showedInstaller = true; question.show( "Code Intelligence", "Code completion is available for the language you are currently working with.", "To install it on your own host, please follow our installation guide. Would you like to open the guide now?", onYes, onNo, { showDontAsk: true, yes: "Open installation guide", no: "Not now", } ); function onYes() { if (question.dontAsk) settings.set("project/codeintel/@dismiss_installer", true); window.open("https://github.com/c9/c9.ide.language.codeintel/blob/master/README.md", "_blank"); } function onNo() { if (question.dontAsk) settings.set("project/codeintel/@dismiss_installer", true); } } plugin.on("unload", function() { }); register(null, { "language.codeintel": plugin }); } }); define("plugins/c9.ide.format/formatters/custom",[], function(require, exports, module) { main.consumes = [ "Plugin", "settings", "save", "collab", "tabManager", "dialog.error", "format" ]; main.provides = ["format.custom"]; return main; function main(options, imports, register) { var settings = imports.settings; var tabs = imports.tabManager; var save = imports.save; var format = imports.format; var collab = imports.collab; var showError = imports["dialog.error"].show; var Plugin = imports.Plugin; var plugin = new Plugin("Ajax.org", main.consumes); var ERROR_NOT_FOUND = 127; var fromFormatCommand; function load() { collab.on("beforeSave", function(e) { var mode = getMode(e.docId); var enabled = settings.getBool("project/" + mode + "/@formatOnSave"); if (!enabled && !fromFormatCommand) return; if (mode === "javascript" && settings.getBool("project/javascript/@use_jsbeautify")) return; // use built-in JS Beautify instead var formatter = settings.get("project/" + mode + "/@formatter"); if (!formatter) return showError("No code formatter set for " + mode + ": please check your project settings"); e.postProcessor = { command: "bash", args: ["-c", formatter] }; }, plugin); collab.on("postProcessorError", function(e) { var mode = getMode(e.docId) || "language"; if (e.code !== ERROR_NOT_FOUND) return console.error("Error running formatter for " + mode + ": " + (e.stderr || e.code)); var formatter = (settings.get("project/" + mode + "/@formatter") || "formatter").replace(/(.*?) .*/, "$1"); showError("Error running code formatter for " + mode + ": " + formatter + " not found, please check your project settings"); }); format.on("format", function(e) { if (!settings.get("project/" + e.mode + "/@formatter")) return; if (e.mode === "javascript" && settings.getBool("project/javascript/@use_jsbeautify")) return; // use built-in JS Beautify instead fromFormatCommand = true; save.save(tabs.focussedTab); fromFormatCommand = false; return true; }, plugin); } function getMode(docId) { var tab = tabs.findTab(docId); if (!tab || !tab.editor || !tab.editor.ace) return; return tab.editor.ace.session.syntax; } plugin.on("load", function() { load(); }); plugin.on("unload", function() { fromFormatCommand = false; }); plugin.freezePublicAPI({}); register(null, { "format.custom": plugin }); } }); define("text!plugins/c9.ide.collab/chat/chat.html",[],"\n
\n
\n"); define("text!plugins/c9.ide.collab/chat/chat.css",[],""); define("timeago",[], function(require, exports, module) { function timeago(timestamp) { if (timestamp instanceof Date) { return inWords(timestamp); } else if (typeof timestamp === "string") { return inWords(parse(timestamp)); } else if (typeof timestamp === "number") { return inWords(new Date(timestamp)); } else { return timeagoElement(timestamp); } } var settings = { refreshMillis: 60000, allowFuture: false, strings: { prefixAgo: null, prefixFromNow: null, suffixAgo: "ago", suffixFromNow: "from now", seconds: "less than a minute", minute: "about a minute", minutes: "%d minutes", hour: "about an hour", hours: "about %d hours", day: "a day", days: "%d days", month: "about a month", months: "%d months", year: "about a year", years: "%d years", wordSeparator: " ", numbers: [] } }; function distanceInWords(distanceMillis) { var $l = settings.strings; var prefix = $l.prefixAgo; var suffix = $l.suffixAgo; if (settings.allowFuture) { if (distanceMillis < 0) { prefix = $l.prefixFromNow; suffix = $l.suffixFromNow; } } var seconds = Math.abs(distanceMillis) / 1000; var minutes = seconds / 60; var hours = minutes / 60; var days = hours / 24; var years = days / 365; function substitute(stringOrFunction, number) { var string = typeof stringOrFunction === "function" ? stringOrFunction(number, distanceMillis) : stringOrFunction; var value = ($l.numbers && $l.numbers[number]) || number; return string.replace(/%d/i, value); } var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) || seconds < 90 && substitute($l.minute, 1) || minutes < 45 && substitute($l.minutes, Math.round(minutes)) || minutes < 90 && substitute($l.hour, 1) || hours < 24 && substitute($l.hours, Math.round(hours)) || hours < 42 && substitute($l.day, 1) || days < 30 && substitute($l.days, Math.round(days)) || days < 45 && substitute($l.month, 1) || days < 365 && substitute($l.months, Math.round(days / 30)) || years < 1.5 && substitute($l.year, 1) || substitute($l.years, Math.round(years)); var separator = $l.wordSeparator || ""; if ($l.wordSeparator === undefined) { separator = " "; } return [prefix, words, suffix].filter(function(s) { return s; }) .map(function(s) { return s.trim(); }) .join(separator); } function parse(iso8601) { var s = iso8601.trim(); s = s.replace(/\.\d+/, ""); // remove milliseconds s = s.replace(/-/, "/").replace(/-/, "/"); s = s.replace(/T/, " ").replace(/Z/, " UTC"); s = s.replace(/([\+\-]\d\d)\:?(\d\d)/, " $1$2"); // -04:00 -> -0400 return new Date(s); } function datetime(elem) { var iso8601 = isTime(elem) ? elem.getAttribute("datetime") : elem.getAttribute("title"); return parse(iso8601); } function isTime(elem) { return elem.tagName.toLowerCase() === "time"; } function timeagoElement(elem) { refresh(elem); if (settings.refreshMillis > 0) setInterval(refresh.bind(null, elem), settings.refreshMillis); } function refresh(elem) { var datetime = prepareDateTime(elem); if (!isNaN(datetime)) elem.textContent = inWords(datetime); } function prepareDateTime(elem) { var timeagoAttr = elem.getAttribute("timeago"); if (timeagoAttr) return new Date(timeagoAttr); var data = datetime(elem); elem.setAttribute("timeago", data); var text = elem.textContent.trim(); if (text.length > 0 && !(isTime(elem) && elem.title)) elem.title = text; return data; } function inWords(date) { return distanceInWords(distance(date)); } function distance(date) { return (new Date().getTime() - date.getTime()); } document.createElement("abbr"); document.createElement("time"); module.exports = timeago; }); define("plugins/c9.ide.collab/chat/emojis",[], function(require, exports, module) {module.exports = { "map": { "e00a": [":iphone:"], "e00b": [":fax:"], "e00c": [":computer:"], "e00d": [":punch:"], "e00e": [":+1:"], "e00f": [":point_up:"], "e001": [":boy:"], "e01a": [":horse:"], "e01b": [":car:"], "e01c": [":sailboat:"], "e01d": [":plane:"], "e01e": [":train:"], "e01f": [":bullettrain_front:"], "e002": [":girl:"], "e02a": [":clock7:"], "e02b": [":clock8:"], "e02c": [":clock9:"], "e02d": [":clock10:"], "e02e": [":clock11:"], "e02f": [":clock12:"], "e003": [":lips:"], "e03a": [":fuelpump:"], "e03b": [":mount_fuji:"], "e03c": [":microphone:"], "e03d": [":movie_camera:"], "e03e": [":musical_note:"], "e03f": [":key:"], "e004": [":man:"], "e04a": [":sun:"], "e04b": [":umbrella:"], "e04c": [":moon:"], "e04d": [":sunrise_over_mountains:"], "e04e": [":angel:"], "e04f": [":cat:"], "e005": [":woman:"], "e05a": [":hankey:", ":poop:", ":shit:"], "e006": [":shirt:"], "e007": [":shoe:"], "e008": [":camera:"], "e009": [":phone:"], "e010": [":fist:"], "e10a": [":octopus:"], "e10b": [":pig:"], "e10c": [":alien:"], "e10d": [":rocket:"], "e10e": [":crown:"], "e10f": [":bulb:"], "e011": [":v:"], "e11a": [":imp:"], "e11b": [":ghost:"], "e11c": [":skull:"], "e11d": [":fire:"], "e11e": [":briefcase:"], "e11f": [":seat:"], "e012": [":hand:"], "e12a": [":baby_symbol:"], "e12b": [":space_invader:"], "e12c": [":part_alternation_mark:"], "e12d": [":mahjong:"], "e12e": [":vs:"], "e12f": [":moneybag:"], "e013": [":ski:"], "e13b": [":syringe:"], "e13c": [":zzz:"], "e13d": [":zap:"], "e13e": [":high_heel:"], "e13f": [":bath:"], "e014": [":golf:"], "e14a": [":chart:"], "e14b": [":satellite:"], "e14c": [":muscle:"], "e14d": [":bank:"], "e14e": [":traffic_light:"], "e14f": [":parking:"], "e015": [":tennis:"], "e15a": [":taxi:"], "e016": [":baseball:"], "e017": [":surfer:"], "e018": [":soccer:", ":football:"], "e019": [":fish:"], "e020": [":question:"], "e20a": [":wheelchair:"], "e20b": [":signal_strength:"], "e20c": [":hearts:"], "e20d": [":diamonds:"], "e20e": [":spades:"], "e20f": [":clubs:"], "e021": [":exclamation:"], "e21a": [":green_circle:"], "e21b": [":purple_circle:"], "e21c": [":1:"], "e21d": [":2:"], "e21e": [":3:"], "e21f": [":4:"], "e022": [":heart:"], "e22a": [":u6e80:"], "e22b": [":u7a7a:"], "e22c": [":u6307:"], "e22d": [":u55b6:"], "e22e": [":point_up:"], "e22f": [":point_down:"], "e023": [":broken_heart:"], "e23a": [":arrow_forward:"], "e23b": [":arrow_backward:"], "e23c": [":fast_forward:"], "e23d": [":rewind:"], "e23e": [":six_pointed_star:"], "e23f": [":aries:"], "e024": [":clock1:"], "e24a": [":pisces:"], "e24b": [":ophiuchus:"], "e24c": [":top:"], "e24d": [":ok:"], "e24e": [":copyright:"], "e24f": [":registered:"], "e025": [":clock2:"], "e026": [":clock3:"], "e027": [":clock4:"], "e028": [":clock5:"], "e029": [":clock6:"], "e030": [":cherry_blossom:"], "e30a": [":headphones:"], "e30b": [":sake:"], "e30c": [":beers:"], "e30d": [":congratulations:"], "e30e": [":smoking:"], "e30f": [":pill:"], "e031": [":trident:"], "e31a": [":sandal:"], "e31b": [":boot:"], "e31c": [":lipstick:"], "e31d": [":nail_care:"], "e31e": [":massage:"], "e31f": [":haircut:"], "e032": [":rose:"], "e32a": [":blue_heart:"], "e32b": [":green_heart:"], "e32c": [":yellow_heart:"], "e32d": [":purple_heart:"], "e32e": [":sparkles:"], "e32f": [":star:"], "e033": [":christmas_tree:"], "e33a": [":icecream:"], "e33b": [":fries:"], "e33c": [":dango:"], "e33d": [":rice_cracker:"], "e33e": [":rice:"], "e33f": [":spaghetti:"], "e034": [":ring:"], "e34a": [":eggplant:"], "e34b": [":birthday:"], "e34c": [":bento:"], "e34d": [":stew:"], "e035": [":gem:"], "e036": [":house:"], "e037": [":church:"], "e038": [":office:"], "e039": [":station:"], "e040": [":saxophone:"], "e40a": [":pensive:"], "e40b": [":fearful:"], "e40c": [":mask:"], "e40d": [":flushed:"], "e40e": [":unamused:"], "e40f": [":cold_sweat:"], "e041": [":guitar:"], "e41a": [":nose:"], "e41b": [":ear:"], "e41c": [":lips:"], "e41d": [":pray:"], "e41e": [":wave:"], "e41f": [":clap:"], "e042": [":trumpet:"], "e42a": [":basketball:"], "e42b": [":rugby:"], "e42c": [":8ball:"], "e42d": [":swimmer:"], "e42e": [":blue_car:"], "e42f": [":truck:"], "e043": [":fork_and_knife:"], "e43a": [":school_satchel:"], "e43b": [":flags:"], "e43c": [":closed_umbrella:"], "e43d": [":wedding:"], "e43e": [":ocean:"], "e43f": [":shaved_ice:"], "e044": [":cocktail:"], "e44a": [":city_sunset:"], "e44b": [":stars:"], "e44c": [":rainbow:"], "e045": [":coffee:"], "e046": [":cake:"], "e047": [":beer:"], "e048": [":snowman:"], "e049": [":cloud:"], "e050": [":tiger:"], "e50a": [":109:"], "e50b": [":jp:"], "e50c": [":us:"], "e50d": [":fr:"], "e50e": [":de:"], "e50f": [":it:"], "e051": [":bear:"], "e51a": [":baby:"], "e51b": [":construction_worker:"], "e51c": [":princess:"], "e51d": [":statue_of_liberty:"], "e51e": [":guardsman:"], "e51f": [":dancer:"], "e052": [":dog:"], "e52a": [":wolf:"], "e52b": [":cow:"], "e52c": [":rabbit:"], "e52d": [":snake:"], "e52e": [":chicken:"], "e52f": [":boar:"], "e053": [":mouse:"], "e054": [":whale:"], "e055": [":penguin:"], "e056": [":blush:"], "e057": [":smile:"], "e058": [":disappointed:"], "e059": [":angry:"], "e101": [":mailbox:"], "e102": [":postbox:"], "e103": [":email:"], "e104": [":calling:"], "e105": [":wink2:"], "e106": [":heart_eyes:"], "e107": [":scream:"], "e108": [":sweat:"], "e109": [":monkey_face:"], "e110": [":four_leaf_clover:"], "e111": [":couplekiss:"], "e112": [":gift:"], "e113": [":gun:"], "e114": [":mag:"], "e115": [":runner:"], "e116": [":hammer:"], "e117": [":fireworks:"], "e118": [":maple_leaf:"], "e119": [":fallen_leaf:"], "e120": [":hamburger:"], "e121": [":fountain:"], "e122": [":tent:"], "e123": [":hotsprings:"], "e124": [":ferris_wheel:"], "e125": [":ticket:"], "e126": [":cd:"], "e127": [":dvd:"], "e128": [":radio:"], "e129": [":vhs:"], "e130": [":dart:"], "e131": [":trophy:"], "e132": [":checkered_flag:"], "e133": [":777:"], "e134": [":racehorse:"], "e135": [":speedboat:"], "e136": [":bike:"], "e137": [":construction:"], "e138": [":mens:"], "e139": [":womens:"], "e140": [":toilet:"], "e141": [":speaker:"], "e412": [":joy:"], "e143": [":crossed_flags:"], "e144": [":lock:"], "e145": [":unlock:"], "e146": [":city_sunset:"], "e147": [":egg:"], "e148": [":book:"], "e149": [":currency_exchange:"], "e150": [":busstop:"], "e151": [":restroom:"], "e152": [":cop:"], "e153": [":post_office:"], "e154": [":atm:"], "e155": [":hospital:"], "e156": [":convenience_store:"], "e157": [":school:"], "e158": [":hotel:"], "e159": [":bus:"], "e201": [":walking:"], "e202": [":ship:"], "e203": [":koko:"], "e204": [":heart_decoration:"], "e205": [":eight_pointed_black_star:"], "e206": [":eight_spoked_asterisk:"], "e207": [":underage:"], "e208": [":no_smoking:"], "e209": [":beginner:"], "e210": [":hash:"], "e211": [":loop:"], "e212": [":new:"], "e213": [":up:"], "e214": [":cool:"], "e215": [":u6709:"], "e216": [":u7121:"], "e217": [":u6708:"], "e218": [":u7533:"], "e219": [":red_circle:"], "e220": [":5:"], "e221": [":6:"], "e222": [":7:"], "e223": [":8:"], "e224": [":9:"], "e225": [":0:"], "e226": [":-:"], "e227": [":u5272:"], "e228": [":sa:"], "e229": [":id:"], "e230": [":point_left:"], "e231": [":point_right:"], "e232": [":arrow_up:"], "e233": [":arrow_down:"], "e234": [":arrow_right:"], "e235": [":arrow_left:"], "e236": [":arrow_upper_right:"], "e237": [":arrow_upper_left:"], "e238": [":arrow_lower_right:"], "e239": [":arrow_lower_left:"], "e240": [":taurus:"], "e241": [":gemini:"], "e242": [":cancer:"], "e243": [":leo:"], "e244": [":virgo:"], "e245": [":libra:"], "e246": [":scorpius:"], "e247": [":sagittarius:"], "e248": [":capricorn:"], "e249": [":aquarius:"], "e250": [":vibration_mode:"], "e251": [":mobile_phone_off:"], "e252": [":warning:"], "e253": [":information_desk_person:"], "e301": [":pencil:"], "e302": [":necktie:"], "e303": [":hibiscus:"], "e304": [":tulip:"], "e305": [":sunflower:"], "e306": [":bouquet:"], "e307": [":palm_tree:"], "e308": [":cactus:"], "e309": [":wc:"], "e310": [":balloon:"], "e311": [":bomb:"], "e312": [":tada:"], "e313": [":scissors:"], "e314": [":ribbon:"], "e315": [":secret:"], "e316": [":minidisc:"], "e317": [":mega:"], "e318": [":womans_hat:"], "e319": [":dress:"], "e320": [":barber:"], "e321": [":kimono:"], "e322": [":bikini:"], "e323": [":handbag:"], "e324": [":clapper:"], "e325": [":bell:"], "e326": [":notes:"], "e327": [":heart_sparkle:"], "e328": [":heart_pink:"], "e329": [":cupid:"], "e330": [":dash:"], "e331": [":sweat_drops:"], "e332": [":o:"], "e333": [":x:"], "e334": [":anger:"], "e335": [":star:"], "e336": [":question:"], "e337": [":exclamation:"], "e338": [":tea:"], "e339": [":bread:"], "e340": [":ramen:"], "e341": [":curry:"], "e342": [":rice_ball:"], "e343": [":oden:"], "e344": [":sushi:"], "e345": [":apple:"], "e346": [":tangerine:"], "e347": [":strawberry:"], "e348": [":watermelon:"], "e349": [":tomato:"], "e401": [":relieved:"], "e402": [":smirk:"], "e403": [":pensive:"], "e404": [":grin:"], "e405": [":wink:"], "e406": [":persevere:"], "e407": [":confounded:"], "e408": [":sleepy:"], "e409": [":tongue:"], "e410": [":astonished:"], "e411": [":sob:"], "e413": [":cry:"], "e414": [":relaxed:"], "e415": [":smile:"], "e416": [":rage:"], "e417": [":kissing_face:"], "e418": [":kissing_heart:"], "e419": [":eyes:"], "e420": [":ok_hand:"], "e421": [":-1:"], "e422": [":open_hands:"], "e423": [":no_good:"], "e424": [":ok_woman:"], "e425": [":couple_with_heart:"], "e426": [":bow:"], "e427": [":raised_hands:"], "e428": [":couple:"], "e429": [":dancers:"], "e430": [":fire_engine:"], "e431": [":ambulance:"], "e432": [":police_car:"], "e433": [":roller_coaster:"], "e434": [":metro:"], "e435": [":bullettrain_side:"], "e436": [":bamboo:"], "e437": [":gift_heart:"], "e438": [":dolls:"], "e439": [":suit:"], "e440": [":sparkler:"], "e441": [":clamshell:"], "e442": [":wind_chime:"], "e443": [":cyclone:"], "e444": [":ear_of_rice:"], "e445": [":jack_o_lantern:"], "e446": [":rice_scene:"], "e447": [":leaves:"], "e448": [":santa:"], "e449": [":sunrise:"], "e501": [":love_hotel:"], "e502": [":art:"], "e503": [":tophat:"], "e504": [":department_store:"], "e505": [":japanese_castle:"], "e506": [":european_castle:"], "e507": [":cinema:"], "e508": [":factory:"], "e509": [":tokyo_tower:"], "e510": [":gb:"], "e511": [":es:"], "e512": [":ru:"], "e513": [":cn:"], "e514": [":kr:"], "e515": [":person_with_blond_hair:"], "e516": [":man_with_gua_pi_mao:"], "e517": [":man_with_turban:"], "e518": [":older_man:"], "e519": [":older_woman:"], "e520": [":dolphin:"], "e521": [":bird:"], "e522": [":tropical_fish:"], "e523": [":baby_chick:"], "e524": [":hamster:"], "e525": [":bug:"], "e526": [":elephant:"], "e527": [":koala:"], "e528": [":monkey:"], "e529": [":sheep:"], "e530": [":camel:"], "e531": [":frog:"], "e532": [":a:"], "e533": [":b:"], "e534": [":ab:"], "e535": [":o2:"], "e536": [":feet:"], "e537": [":tm:"], "e770": [":stuck_out_tongue_closed_eyes:"], "e771": [":stuck_out_tongue:"], "e991": [":ruben:"], "e992": [":fabian:"], "e993": [":jos:"], "e994": [":mostafa:"], "e995": [":lennart:"], "e996": [":ivar:"], "e997": [":bas:"], "e998": [":luca:"], "e999": [":harutyun:"]}, "reverse": { ":iphone:": "e00a", ":fax:": "e00b", ":computer:": "e00c", ":punch:": "e00d", ":+1:": "e00e", ":point_up:": "e22e", ":boy:": "e001", ":horse:": "e01a", ":car:": "e01b", ":sailboat:": "e01c", ":plane:": "e01d", ":train:": "e01e", ":bullettrain_front:": "e01f", ":girl:": "e002", ":clock7:": "e02a", ":clock8:": "e02b", ":clock9:": "e02c", ":clock10:": "e02d", ":clock11:": "e02e", ":clock12:": "e02f", ":lips:": "e41c", ":fuelpump:": "e03a", ":mount_fuji:": "e03b", ":microphone:": "e03c", ":movie_camera:": "e03d", ":musical_note:": "e03e", ":key:": "e03f", ":man:": "e004", ":sun:": "e04a", ":umbrella:": "e04b", ":moon:": "e04c", ":sunrise_over_mountains:": "e04d", ":angel:": "e04e", ":cat:": "e04f", ":woman:": "e005", ":hankey:": "e05a", ":poop:": "e05a", ":shit:": "e05a", ":shirt:": "e006", ":shoe:": "e007", ":camera:": "e008", ":phone:": "e009", ":fist:": "e010", ":octopus:": "e10a", ":pig:": "e10b", ":alien:": "e10c", ":rocket:": "e10d", ":crown:": "e10e", ":bulb:": "e10f", ":v:": "e011", ":imp:": "e11a", ":ghost:": "e11b", ":skull:": "e11c", ":fire:": "e11d", ":briefcase:": "e11e", ":seat:": "e11f", ":hand:": "e012", ":tv:": "e12a", ":space_invader:": "e12b", ":part_alternation_mark:": "e12c", ":mahjong:": "e12d", ":vs:": "e12e", ":moneybag:": "e12f", ":ski:": "e013", ":baby_symbol:": "e12a", ":syringe:": "e13b", ":zzz:": "e13c", ":zap:": "e13d", ":high_heel:": "e13e", ":bath:": "e13f", ":golf:": "e014", ":chart:": "e14a", ":satellite:": "e14b", ":muscle:": "e14c", ":bank:": "e14d", ":traffic_light:": "e14e", ":parking:": "e14f", ":tennis:": "e015", ":taxi:": "e15a", ":baseball:": "e016", ":surfer:": "e017", ":soccer:": "e018", ":football:": "e018", ":fish:": "e019", ":question:": "e336", ":wheelchair:": "e20a", ":signal_strength:": "e20b", ":hearts:": "e20c", ":diamonds:": "e20d", ":spades:": "e20e", ":clubs:": "e20f", ":exclamation:": "e337", ":green_circle:": "e21a", ":purple_circle:": "e21b", ":1:": "e21c", ":2:": "e21d", ":3:": "e21e", ":4:": "e21f", ":heart:": "e022", ":u6e80:": "e22a", ":u7a7a:": "e22b", ":u6307:": "e22c", ":u55b6:": "e22d", ":point_down:": "e22f", ":broken_heart:": "e023", ":arrow_forward:": "e23a", ":arrow_backward:": "e23b", ":fast_forward:": "e23c", ":rewind:": "e23d", ":six_pointed_star:": "e23e", ":aries:": "e23f", ":clock1:": "e024", ":pisces:": "e24a", ":ophiuchus:": "e24b", ":top:": "e24c", ":ok:": "e24d", ":copyright:": "e24e", ":registered:": "e24f", ":clock2:": "e025", ":clock3:": "e026", ":clock4:": "e027", ":clock5:": "e028", ":clock6:": "e029", ":cherry_blossom:": "e030", ":headphones:": "e30a", ":sake:": "e30b", ":beers:": "e30c", ":congratulations:": "e30d", ":smoking:": "e30e", ":pill:": "e30f", ":trident:": "e031", ":sandal:": "e31a", ":boot:": "e31b", ":lipstick:": "e31c", ":nail_care:": "e31d", ":massage:": "e31e", ":haircut:": "e31f", ":rose:": "e032", ":blue_heart:": "e32a", ":green_heart:": "e32b", ":yellow_heart:": "e32c", ":purple_heart:": "e32d", ":sparkles:": "e32e", ":star:": "e335", ":christmas_tree:": "e033", ":icecream:": "e33a", ":fries:": "e33b", ":dango:": "e33c", ":rice_cracker:": "e33d", ":rice:": "e33e", ":spaghetti:": "e33f", ":ring:": "e034", ":eggplant:": "e34a", ":birthday:": "e34b", ":bento:": "e34c", ":stew:": "e34d", ":gem:": "e035", ":house:": "e036", ":church:": "e037", ":office:": "e038", ":station:": "e039", ":saxophone:": "e040", ":pensive:": "e403", ":fearful:": "e40b", ":mask:": "e40c", ":flushed:": "e40d", ":unamused:": "e40e", ":cold_sweat:": "e40f", ":guitar:": "e041", ":nose:": "e41a", ":ear:": "e41b", ":pray:": "e41d", ":wave:": "e41e", ":clap:": "e41f", ":trumpet:": "e042", ":basketball:": "e42a", ":rugby:": "e42b", ":8ball:": "e42c", ":swimmer:": "e42d", ":blue_car:": "e42e", ":truck:": "e42f", ":fork_and_knife:": "e043", ":school_satchel:": "e43a", ":flags:": "e43b", ":closed_umbrella:": "e43c", ":wedding:": "e43d", ":ocean:": "e43e", ":shaved_ice:": "e43f", ":cocktail:": "e044", ":city_sunset:": "e146", ":stars:": "e44b", ":rainbow:": "e44c", ":coffee:": "e045", ":cake:": "e046", ":beer:": "e047", ":snowman:": "e048", ":cloud:": "e049", ":tiger:": "e050", ":109:": "e50a", ":jp:": "e50b", ":us:": "e50c", ":fr:": "e50d", ":de:": "e50e", ":it:": "e50f", ":bear:": "e051", ":baby:": "e51a", ":construction_worker:": "e51b", ":princess:": "e51c", ":statue_of_liberty:": "e51d", ":guardsman:": "e51e", ":dancer:": "e51f", ":dog:": "e052", ":wolf:": "e52a", ":cow:": "e52b", ":rabbit:": "e52c", ":snake:": "e52d", ":chicken:": "e52e", ":boar:": "e52f", ":mouse:": "e053", ":whale:": "e054", ":penguin:": "e055", ":blush:": "e056", ":smile:": "e415", ":disappointed:": "e058", ":angry:": "e059", ":mailbox:": "e101", ":postbox:": "e102", ":email:": "e103", ":calling:": "e104", ":wink2:": "e105", ":heart_eyes:": "e106", ":scream:": "e107", ":sweat:": "e108", ":monkey_face:": "e109", ":four_leaf_clover:": "e110", ":couplekiss:": "e111", ":gift:": "e112", ":gun:": "e113", ":mag:": "e114", ":runner:": "e115", ":hammer:": "e116", ":fireworks:": "e117", ":maple_leaf:": "e118", ":fallen_leaf:": "e119", ":hamburger:": "e120", ":fountain:": "e121", ":tent:": "e122", ":hotsprings:": "e123", ":ferris_wheel:": "e124", ":ticket:": "e125", ":cd:": "e126", ":dvd:": "e127", ":radio:": "e128", ":vhs:": "e129", ":dart:": "e130", ":trophy:": "e131", ":checkered_flag:": "e132", ":777:": "e133", ":racehorse:": "e134", ":speedboat:": "e135", ":bike:": "e136", ":construction:": "e137", ":mens:": "e138", ":womens:": "e139", ":toilet:": "e140", ":speaker:": "e141", ":loudspeaker:": "e412", ":crossed_flags:": "e143", ":lock:": "e144", ":unlock:": "e145", ":egg:": "e147", ":book:": "e148", ":currency_exchange:": "e149", ":busstop:": "e150", ":restroom:": "e151", ":cop:": "e152", ":post_office:": "e153", ":atm:": "e154", ":hospital:": "e155", ":convenience_store:": "e156", ":school:": "e157", ":hotel:": "e158", ":bus:": "e159", ":walking:": "e201", ":ship:": "e202", ":koko:": "e203", ":heart_decoration:": "e204", ":eight_pointed_black_star:": "e205", ":eight_spoked_asterisk:": "e206", ":underage:": "e207", ":no_smoking:": "e208", ":beginner:": "e209", ":hash:": "e210", ":loop:": "e211", ":new:": "e212", ":up:": "e213", ":cool:": "e214", ":u6709:": "e215", ":u7121:": "e216", ":u6708:": "e217", ":u7533:": "e218", ":red_circle:": "e219", ":5:": "e220", ":6:": "e221", ":7:": "e222", ":8:": "e223", ":9:": "e224", ":0:": "e225", ":-:": "e226", ":u5272:": "e227", ":sa:": "e228", ":id:": "e229", ":point_left:": "e230", ":point_right:": "e231", ":arrow_up:": "e232", ":arrow_down:": "e233", ":arrow_right:": "e234", ":arrow_left:": "e235", ":arrow_upper_right:": "e236", ":arrow_upper_left:": "e237", ":arrow_lower_right:": "e238", ":arrow_lower_left:": "e239", ":taurus:": "e240", ":gemini:": "e241", ":cancer:": "e242", ":leo:": "e243", ":virgo:": "e244", ":libra:": "e245", ":scorpius:": "e246", ":sagittarius:": "e247", ":capricorn:": "e248", ":aquarius:": "e249", ":vibration_mode:": "e250", ":mobile_phone_off:": "e251", ":warning:": "e252", ":information_desk_person:": "e253", ":pencil:": "e301", ":necktie:": "e302", ":hibiscus:": "e303", ":tulip:": "e304", ":sunflower:": "e305", ":bouquet:": "e306", ":palm_tree:": "e307", ":cactus:": "e308", ":wc:": "e309", ":balloon:": "e310", ":bomb:": "e311", ":tada:": "e312", ":scissors:": "e313", ":ribbon:": "e314", ":secret:": "e315", ":minidisc:": "e316", ":mega:": "e317", ":womans_hat:": "e318", ":dress:": "e319", ":barber:": "e320", ":kimono:": "e321", ":bikini:": "e322", ":handbag:": "e323", ":clapper:": "e324", ":bell:": "e325", ":notes:": "e326", ":heart_sparkle:": "e327", ":heart_pink:": "e328", ":cupid:": "e329", ":dash:": "e330", ":sweat_drops:": "e331", ":o:": "e332", ":x:": "e333", ":anger:": "e334", ":tea:": "e338", ":bread:": "e339", ":ramen:": "e340", ":curry:": "e341", ":rice_ball:": "e342", ":oden:": "e343", ":sushi:": "e344", ":apple:": "e345", ":tangerine:": "e346", ":strawberry:": "e347", ":watermelon:": "e348", ":tomato:": "e349", ":relieved:": "e401", ":smirk:": "e402", ":grin:": "e404", ":wink:": "e405", ":persevere:": "e406", ":confounded:": "e407", ":sleepy:": "e408", ":tongue:": "e409", ":astonished:": "e410", ":sob:": "e411", ":joy:": "e412", ":cry:": "e413", ":relaxed:": "e414", ":rage:": "e416", ":kissing_face:": "e417", ":kissing_heart:": "e418", ":eyes:": "e419", ":ok_hand:": "e420", ":-1:": "e421", ":open_hands:": "e422", ":no_good:": "e423", ":ok_woman:": "e424", ":couple_with_heart:": "e425", ":bow:": "e426", ":raised_hands:": "e427", ":couple:": "e428", ":dancers:": "e429", ":fire_engine:": "e430", ":ambulance:": "e431", ":police_car:": "e432", ":roller_coaster:": "e433", ":metro:": "e434", ":bullettrain_side:": "e435", ":bamboo:": "e436", ":gift_heart:": "e437", ":dolls:": "e438", ":suit:": "e439", ":sparkler:": "e440", ":clamshell:": "e441", ":wind_chime:": "e442", ":cyclone:": "e443", ":ear_of_rice:": "e444", ":jack_o_lantern:": "e445", ":rice_scene:": "e446", ":leaves:": "e447", ":santa:": "e448", ":sunrise:": "e449", ":love_hotel:": "e501", ":art:": "e502", ":tophat:": "e503", ":department_store:": "e504", ":japanese_castle:": "e505", ":european_castle:": "e506", ":cinema:": "e507", ":factory:": "e508", ":tokyo_tower:": "e509", ":gb:": "e510", ":es:": "e511", ":ru:": "e512", ":cn:": "e513", ":kr:": "e514", ":person_with_blond_hair:": "e515", ":man_with_gua_pi_mao:": "e516", ":man_with_turban:": "e517", ":older_man:": "e518", ":older_woman:": "e519", ":dolphin:": "e520", ":bird:": "e521", ":tropical_fish:": "e522", ":baby_chick:": "e523", ":hamster:": "e524", ":bug:": "e525", ":elephant:": "e526", ":koala:": "e527", ":monkey:": "e528", ":sheep:": "e529", ":camel:": "e530", ":frog:": "e531", ":a:": "e532", ":b:": "e533", ":ab:": "e534", ":o2:": "e535", ":feet:": "e536", ":tm:": "e537", ":stuck_out_tongue_closed_eyes:": "e770", ":stuck_out_tongue:": "e771", ":ruben:": "e991", ":fabian:": "e992", ":jos:": "e993", ":mostafa:": "e994", ":lennart:": "e995", ":ivar:": "e996", ":bas:": "e997", ":luca:": "e998", ":harutyun:": "e999" }};}); define("plugins/c9.ide.collab/chat/my_emoji",[], function(require, exports, module) { "use strict"; var Emojis = require("./emojis"); exports.emoji = function(text, staticPrefix) { return text.replace(/([\ue001-\ue999])/g, function(str, p1) { return p1.charCodeAt(0).toString(16).toUpperCase().replace( /^([\da-f]+)$/i, "\"emoji\"" ); }); }; exports.toEmojiUnicode = function(text) { function toUnicode(str, p1) { return Emojis.reverse[p1] ? eval('"\\u' + Emojis.reverse[p1] + '"') : str; } text = text.replace(/(:[\w_\-\+]*:)/g, toUnicode); specialEmojis.forEach(function (emot) { text = text.replace(emot[0], toUnicode(emot[1], emot[1])); }); return text; }; var specialEmojis = [ [/:-*\)/g, ':blush:'], [/:-*o/gi, ':scream:'], [/(:|;)-*\]/g, ':smirk:'], [/(:|;)-*d/gi, ':smile:'], [/xd/gi, ':stuck_out_tongue_closed_eyes:'], [/:-*p/gi, ':stuck_out_tongue:'], [/:-*(\[|@)/g, ':rage:'], [/:-*\(/g, ':disappointed:'], [/:-*\*/g, ':kissing_heart:'], [/;-*\)/g, ':wink:'], [/:-*s/gi, ':confounded:'], [/:-*\|/g, ':flushed:'], [/:-*\$/g, ':relaxed:'], [/:-*x/gi, ':mask:'], [/<3/g, ':heart:'], [/<\/3/g, ':broken_heart:'], [/:('|’)-*\(/g, ':sob:'] ]; }); define("plugins/c9.ide.collab/chat/chat",[], function(require, exports, module) { "use strict"; main.consumes = [ "CollabPanel", "ui", "panels", "collab.util", "collab.workspace", "collab", "Menu", "MenuItem" ]; main.provides = ["chat"]; return main; function main(options, imports, register) { var CollabPanel = imports.CollabPanel; var ui = imports.ui; var panels = imports.panels; var util = imports["collab.util"]; var workspace = imports["collab.workspace"]; var collab = imports.collab; var Menu = imports.Menu; var MenuItem = imports.MenuItem; var html = require("text!./chat.html"); var css = require("text!./chat.css"); var timeago = require("timeago"); var staticPrefix = options.staticPrefix; var toDeleteMessage; var ROLE_NONE = "n"; var ROLE_VISITOR = "v"; var ROLE_COLLABORATOR = "c"; var ROLE_ADMIN = "a"; var plugin = new CollabPanel("Ajax.org", main.consumes, { name: "chat", index: 200, caption: "Group Chat", textselect: true, style: "flex:1;" }); var emoji = require("./my_emoji"); var chatInput, chatText, mnuCtxTreeEl, parent; var chatThrob, chatCounter, chatNotif; function $(id) { return document.getElementById(id); } var loaded = false; function load() { if (loaded) return; loaded = true; collab.on("chatMessage", onChatMessage); collab.on("chatClear", onChatClear); } var drawn = false; function draw(options) { if (drawn) return; drawn = true; drawNonPanelElements(); parent = options.aml; var parentExt = parent.$int; parentExt.className += " chatContainer"; chatText = parentExt.appendChild(document.createElement("div")); chatText.setAttribute("class", "chatText"); chatInput = new apf.codebox({ htmlNode: parentExt, skin: "codebox", "initial-message": "Enter your message here", focusselect: "true" }); chatInput.$ext.classList.remove("ace_searchbox"); chatInput.ace.setOptions({ wrap: "free", indentedSoftWrap: false, maxLines: 5, minLines: 2, fontFamily: "inherit" }); chatInput.ace.session.$setFontMetrics(chatInput.ace.renderer.$fontMetrics); plugin.addElement(chatInput); function onWorkspaceSync() { var accessInfo = workspace.accessInfo; if (accessInfo.private && (!accessInfo.member || accessInfo.pending)) return console.warn("Don't have read access - You can't use chat"); var chatHistory = workspace.chatHistory || []; chatHistory.forEach(addMessage); scrollDown(); chatCounter.textContent = chatHistory.length; } chatInput.ace.commands.addCommands([ { bindKey: "ESC", exec: function() { if (chatInput.getValue()) chatInput.setValue(""); else collab.hide(); } }, { bindKey: "Enter", exec: send } ]); function listenWorkspaceSync() { workspace.off("sync", onWorkspaceSync); workspace.on("sync", onWorkspaceSync); } if (panels.isActive("collab")) listenWorkspaceSync(); collab.on("show", function() { chatInput.focus(); listenWorkspaceSync(); }); collab.on("hide", function() { workspace.off("sync", onWorkspaceSync); }); var deleteMsgItem = new MenuItem({ caption: "Delete Message", match: "rw", onclick: clearChatMessage, disabled: true }); var clearHistoryItem = new MenuItem({ caption: "Clear history", match: "rw", onclick: clearChatHistory, disabled: true }); var mnuCtxTree = new Menu({ id: "mnuChat", items: [ deleteMsgItem, clearHistoryItem ] }, plugin); mnuCtxTreeEl = mnuCtxTree.aml; parent.setAttribute("contextmenu", mnuCtxTreeEl); mnuCtxTree.on("show", function() { setTimeout(function() { var hasReadWrite = workspace.fs === "rw"; var collabConnected = collab.connected; clearHistoryItem.disabled = !hasReadWrite || !collabConnected || !chatText.firstChild; toDeleteMessage = findMessageToDelete(hasReadWrite); deleteMsgItem.disabled = !toDeleteMessage || !collabConnected; }, 10); }); parent.on("resize", function() { if (isOpen()) { pending.forEach(addMessage); pending = []; updateCaption(); } }); } function findMessageToDelete(hasReadWrite) { var menuRect = mnuCtxTreeEl.$int.getBoundingClientRect(); var msg; [].slice.apply(chatText.getElementsByTagName("p")).forEach(function(msgP) { var rect = msgP.getBoundingClientRect(); if (rect.left < menuRect.left && (rect.left + rect.width) > menuRect.left && rect.top < menuRect.top && (rect.top + rect.height) > menuRect.top && (hasReadWrite || msgP.userId == workspace.myUserId)) msg = msgP; }); return msg; } function clearChatMessage() { if (!toDeleteMessage || !toDeleteMessage.id) return console.error("[OT] Chat: no message found to delete!"); var msgId = toDeleteMessage.id.match(/ot_chat_(\d+)/)[1]; collab.send("CLEAR_CHAT", { id: msgId }); } function clearChatHistory() { collab.send("CLEAR_CHAT", { clear: true }); } var seenMsgs = {}; var pending = []; var throbTimeout; function scrollDown() { chatText.scrollTop = chatText.scrollHeight; } function isOpen() { return panels.isActive("collab") && parent.state[0] != "m"; } function send() { var text = chatInput.getValue().trim(); if (!text) return; text = emoji.toEmojiUnicode(text); collab.send("CHAT_MESSAGE", { text: text }); chatInput.setValue(""); } function getAuthorName(userId) { if (userId == workspace.myUserId) return "You"; var user = workspace.users[userId]; return util.escapeHTML(user.fullname); } function getAuthorColor(userId) { var color = workspace.colorPool[userId]; return util.formatColor(color); } function formatMessageText(text) { text = util.escapeHtmlWithClickableLinks(text.trim(), "_blank"); text = text.replace(/\n/g, "
"); text = emoji.emoji(text, staticPrefix); return text; } function onChatMessage(msg) { drawNonPanelElements(); workspace.addChatMessage(msg); if (isOpen()) { addMessage(msg); } else { pending.push(msg); updateCaption(); var throbText = "" + getAuthorName(msg.userId) + " "; var text = formatMessageText(msg.text); var notif = msg.notification; if (notif) { throbText += text + " " + notif.linkText; } else { throbText += ": " + text; } chatThrob.innerHTML = throbText; chatThrob.style.display = "block"; clearTimeout(throbTimeout); throbTimeout = setTimeout(function () { chatThrob.style.display = "none"; }, 5000); } if (msg.increment) { var count = Number(chatCounter.textContent); chatCounter.textContent = count + 1; } var inputFocussed = chatInput && chatInput.ace.isFocused(); if (!inputFocussed) chatNotif.play(); } function onChatClear(data) { if (data.clear) { while (chatText.firstChild) chatText.removeChild(chatText.firstChild); seenMsgs = {}; // sql truncate table would lead to same msg ids workspace.chatHistory = []; } else if (data.id) { var msgHtml = $("ot_chat_" + data.id); msgHtml && msgHtml.parentNode.removeChild(msgHtml); } } function addMessage(msg) { if (seenMsgs[msg.id]) return; seenMsgs[msg.id] = true; var msgDate = new Date(msg.timestamp); var text = formatMessageText(msg.text); var authorName = getAuthorName(msg.userId); var authorColor = getAuthorColor(msg.userId); var authorNameEl = document.createElement("a"); authorNameEl.href = "javascript:void(0)"; authorNameEl.className = "authorName"; authorNameEl.innerHTML = "" + authorName + ""; var html = document.createElement("p"); html.id = "ot_chat_" + msg.id; html.userId = msg.userId; if (msg.userId == workspace.myUserId) html.className = "you"; var borderEl = document.createElement("span"); html.appendChild(borderEl); borderEl.className = "chatBorder"; borderEl.style.borderLeftColor = authorColor; html.appendChild(authorNameEl); var textEl = document.createElement("span"); textEl.className = "chatmessage"; textEl.innerHTML = text + "
"; html.appendChild(textEl); var timeEl = document.createElement("span"); timeEl.className = "chattime"; timeEl.title = msgDate.toISOString(); timeEl.innerHTML = msgDate; timeago(timeEl); html.appendChild(timeEl); chatText.appendChild(html); scrollDown(); } function updateCaption() { var caption = "Group Chat"; if (pending.length) caption += "(" + pending.length + ")"; if (parent) parent.setAttribute("caption", caption); } var nonPanelDrawn = false; function drawNonPanelElements () { if (nonPanelDrawn) return; nonPanelDrawn = true; ui.insertHtml(null, html, plugin); ui.insertCss(css, staticPrefix, plugin); chatThrob = $("chatThrob"); chatCounter = $("chatCounter"); chatNotif = $("chatNotif"); chatNotif.src = staticPrefix + "/sounds/chat_notif.mp3"; chatThrob.addEventListener("click", function () { chatThrob.style.display = "none"; plugin.show(); }); } plugin.on("load", function() { load(); plugin.once("draw", draw); }); plugin.on("enable", function() { }); plugin.on("disable", function() { }); plugin.on("unload", function() { loaded = false; drawn = nonPanelDrawn = false; }); plugin.freezePublicAPI({ }); register(null, { chat: plugin }); } }); define("text!plugins/c9.ide.collab/members/members.css",[],""); define("plugins/c9.ide.collab/members/members",[], function(require, exports, module) { "use strict"; main.consumes = ["CollabPanel", "ui", "MembersPanel", "collab", "panels"]; main.provides = ["members"]; return main; function main(options, imports, register) { var CollabPanel = imports.CollabPanel; var collab = imports.collab; var MembersPanel = imports.MembersPanel; var ui = imports.ui; var panels = imports.panels; var css = require("text!./members.css"); var membersPanel; var plugin = new CollabPanel("Ajax.org", main.consumes, { name: "members", index: 100, caption: "Workspace Members" }); var loaded = false; function load() { if (loaded) return; loaded = true; ui.insertCss(css, null, plugin); membersPanel = new MembersPanel("Ajax.org", main.consumes, { showTabs: true, autoSize: true }); plugin.on("resize", membersPanel.resize.bind(membersPanel)); collab.on("show", membersPanel.show.bind(membersPanel)); collab.on("hide", membersPanel.hide.bind(membersPanel)); } var drawn = false; function draw(e) { if (drawn) return; drawn = true; membersPanel.draw(e); if (panels.isActive("collab")) membersPanel.show(); } plugin.on("load", function() { load(); plugin.once("draw", draw); }); plugin.on("enable", function() { }); plugin.on("disable", function() { }); plugin.on("unload", function() { loaded = false; drawn = false; }); plugin.freezePublicAPI({ }); register(null, { members: plugin }); } }); define("text!plugins/c9.ide.collab/share/share.xml",[],"\n \n \n
\n \n \n
\n Public\n
\n \n \n
\n Public\n
\n \n \n
\n Public\n
\n
\n \n \n \n Don't allow members to save their tab state\n\n
\n \n \n\n \n
R
RW
\n
\n\n Invite\n Notify people via email\n
\n\n Done\n \n
\n"); define("text!plugins/c9.ide.collab/share/share.css",[],""); define("plugins/c9.ide.collab/share/share",[], function(require, module, exports) { main.consumes = [ "Plugin", "c9", "commands", "menus", "ui", "layout", "dialog.alert", "MembersPanel", "info", "collab.workspace", "Menu", "MenuItem", "clipboard", "settings", "api", "dialog.question" ]; main.provides = ["dialog.share"]; return main; function main(options, imports, register) { var Plugin = imports.Plugin; var c9 = imports.c9; var MembersPanel = imports.MembersPanel; var commands = imports.commands; var settings = imports.settings; var menus = imports.menus; var clipboard = imports.clipboard; var ui = imports.ui; var api = imports.api; var alert = imports["dialog.alert"].show; var layout = imports.layout; var workspace = imports["collab.workspace"]; var question = imports["dialog.question"]; var Menu = imports.Menu; var MenuItem = imports.MenuItem; var markup = require("text!./share.xml"); var css = require("text!./share.css"); var plugin = new Plugin("Ajax.org", main.consumes); var emit = plugin.getEmitter(); var dialog, btnInvite, btnDone, txtUsername, membersParent, accessButton; var membersPanel, shareLinkEditor, shareLinkApp, shareLinkPreview; var publicApp, publicPreview, publicEditor, cbNotify; var loaded = false; function load() { if (loaded) return; loaded = true; if (!c9.isAdmin) return; commands.addCommand({ name: "sharedialog", hint: "Share the workspace", group: "General", exec: show }, plugin); var btn = new ui.button({ "skin": "c9-menu-btn", "caption": "Share", "class": "c9-share", "tooltip": "Share this workspace", "command": "sharedialog" }); menus.addItemByPath("Window/~", new ui.divider(), 35, plugin); menus.addItemByPath("Window/Share...", new ui.item({ command: "sharedialog" }), 36, plugin); ui.insertByIndex(layout.findParent({ name: "preferences" }), btn, 875, plugin); settings.on("read", function() { settings.setDefaults("project/share", [ ["preview", false], ["app", false], ["useOwnerSettings", false], ]); }, plugin); } var drawn = false; function draw() { if (drawn) return; drawn = true; ui.insertCss(css, plugin); ui.insertMarkup(null, markup, plugin); commands.addCommand({ name: plugin.name, bindKey: { mac: "ESC", win: "ESC" }, group: "ignore", isAvailable: function() { return dialog.visible; }, exec: function() { dialog.dispatchEvent("keydown", { keyCode: 27 }); } }, plugin); dialog = plugin.getElement("window"); btnInvite = plugin.getElement("btnInvite"); btnDone = plugin.getElement("btnDone"); cbNotify = plugin.getElement("cbNotify"); txtUsername = plugin.getElement("txtUsername"); shareLinkEditor = plugin.getElement("shareLinkEditor").$int; shareLinkApp = plugin.getElement("shareLinkApp").$int; shareLinkPreview = plugin.getElement("shareLinkPreview").$int; membersParent = plugin.getElement("members"); publicApp = plugin.getElement("publicApp"); publicPreview = plugin.getElement("publicPreview"); publicEditor = plugin.getElement("publicEditor"); accessButton = plugin.getElement("access").$int; if (options.silent) { cbNotify.uncheck(); cbNotify.$ext.style.visibility = "hidden"; } var mnuLink = new Menu({ zindex: 500000, items: [ new MenuItem({ caption: "Open", onclick: function() { window.open(mnuLink.meta.linkText); } }), new MenuItem({ caption: "Copy", onclick: function() { clipboard.copy(false, mnuLink.meta.linkText); } }) ] }, plugin); var port = (options.local ? ":" + (c9.port || "8080") : ""); if (!options.local) { var l = location; shareLinkEditor.textContent = l.protocol + "//" + l.host + l.pathname; } else { shareLinkEditor.textContent = "https://ide.c9.io/" + c9.workspaceId; } shareLinkApp.textContent = (c9.hostname ? "https://" + c9.hostname : "http://localhost") + port; shareLinkPreview.textContent = options.previewUrl; [shareLinkEditor, shareLinkApp, shareLinkPreview].forEach(function(div) { div.addEventListener("click", function(e) { mnuLink.meta.linkText = this.textContent; mnuLink.show(e.clientX + 1, e.clientY); }); div.addEventListener("contextmenu", function(e) { var sel = window.getSelection(); var r = new Range(); r.selectNode(e.currentTarget); sel.removeAllRanges(); sel.addRange(r); }); }); accessButton.addEventListener("click", function () { var className = accessButton.classList; var actionArr = className.contains("rw") ? ["rw", "r"] : ["r", "rw"]; className.remove(actionArr[0]); className.add(actionArr[1]); }); var words = { "visibility": ["this workspace"], "app": ["the running application"], "preview": ["the preview of workspace files"] }; function updateAccess(field, value, cb, callback) { var to = value ? "public" : "private"; question.show( "Change Access To " + to.uCaseFirst(), (field == "visibility" ? (value ? "Make this workspace available to the whole world?" : "Close this workspace to everyone but the listed users?") : (value ? "Make " + words[field][0] + " available to anyone with the url?" : "Close " + words[field][0] + " to everyone but the listed users?")), (value ? "Are you sure you want to make this change? Anyone with " + "the url will have read-only access to " + words[field] + ". " + "Only users that you authorize have write access." : "Are you sure you want to make this change? Only users " + "with read-only or read-write access will be able to " + "access " + words[field] + "."), function() { // Yes cb.disable(); var key = field == "visibility" ? field : field + "Access"; var body = {}; body[key] = to; api.project.patch("", { body: body, contentType: "application/json" }, function(err) { cb.enable(); if (callback) callback(err); if (err) { cb[value ? "uncheck" : "check"](); if (err.message == "Administrator rights required!") { alert("Forbidden", "You are not allowed to change this setting.", "Only the owner of this workspace can change " + "this setting. Please contact the owner " + "about this."); } else if (err.code == 402) { alert("Maximum Private Workspaces Reached", "It seems you have reached the maximum number " + "of workspaces under your account", "Please go to the dashboard or contact support " + "to increase the number of private workspaces."); } else { alert("Failed updating public status", "The server returned an error", err.message || ""); } } }); }, function() { // No cb[value ? "uncheck" : "check"](); } ); } publicEditor.on("afterchange", function(e) { updateAccess("visibility", e.value, publicEditor, function(err) { syncPermissions(); }); }); publicApp.on("afterchange", function(e) { updateAccess("app", e.value, publicApp); }); publicPreview.on("afterchange", function(e) { updateAccess("preview", e.value, publicPreview); }); btnDone.on("click", hide); btnInvite.on("click", inviteUser); txtUsername.on("keydown", function(e) { if (e.keyCode == 13) { inviteUser(); e.returnValue = false; return false; } else if (e.keyCode === 27) { hide(); } }); membersPanel = new MembersPanel("Ajax.org", main.consumes, {}); membersPanel.draw({ aml: membersParent }); syncPermissions(); emit.sticky("draw"); } function syncPermissions() { api.collab.get("access_info", function (err, info) { if (err) return; publicEditor[info.private ? "uncheck" : "check"](); publicApp[info.appPublic || !info.private ? "check" : "uncheck"](); publicPreview[info.previewPublic || !info.private ? "check" : "uncheck"](); publicApp[!info.private ? "disable" : "enable"](); publicPreview[!info.private ? "disable" : "enable"](); }); } function inviteUser() { var username = txtUsername.value; username = username.replace(/^\s*(<\s*)?|\s*(>\s*)?$/g, ""); var access = accessButton.classList.contains("rw") ? "rw" : "r"; var accessString = access === "rw" ? "Read+Write" : "Read-Only"; btnInvite.disable(); var options = { silent: !cbNotify.checked }; workspace.addMember(username, access, options, function(err, member) { btnInvite.enable(); if (err) return alert("Error", "Error adding workspace member", err.message); txtUsername.setValue(""); alert("Invitation Sent", "Workspace Member Added", "You have granted " + member.name + " " + accessString + " access to this workspace!"); }); } function show() { draw(); dialog.show(); membersPanel.show(); txtUsername.setValue(""); txtUsername.blur(); } function hide() { dialog && dialog.hide(); } plugin.on("load", function() { load(); }); plugin.freezePublicAPI({ }); register(null, { "dialog.share": plugin }); } }); 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); }; }); define("ace/lib/useragent",[], 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; } }; if (typeof navigator != "object") return; var os = (navigator.platform.match(/mac|win|linux/i) || ["other"])[0].toLowerCase(); var ua = navigator.userAgent; exports.isWin = (os == "win"); exports.isMac = (os == "mac"); exports.isLinux = (os == "linux"); exports.isIE = (navigator.appName == "Microsoft Internet Explorer" || navigator.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 = window.opera && 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.isAIR = ua.indexOf("AdobeAIR") >= 0; exports.isIPad = ua.indexOf("iPad") >= 0; exports.isChromeOS = ua.indexOf(" CrOS ") >= 0; exports.isIOS = /iPad|iPhone|iPod/.test(ua) && !window.MSStream; if (exports.isIOS) exports.isMac = true; }); define("ace/lib/dom",[], 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)) 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") { 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, container) { var root = container && container.getRootNode ? container.getRootNode() : container || document; var doc = root.ownerDocument || root; if (id && exports.hasCssString(id, root)) 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 (root == doc) root = exports.getDocumentHead(doc); root.insertBefore(style, root.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; if (typeof document !== "undefined") { var div = document.createElement("div"); if (typeof div.style.animationName !== "undefined") { exports.HAS_CSS_ANIMATION = true; } } exports.HAS_CSS_TRANSFORMS = false; exports.HI_DPI = useragent.isWin ? typeof window !== "undefined" && window.devicePixelRatio >= 1.5 : true; if (exports.HI_DPI && typeof document !== "undefined") { var div = document.createElement("div"); if (div.style.transform !== undefined) exports.HAS_CSS_TRANSFORMS = 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"; }; } }); 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 1) base = parts[parts.length - 2]; var path = options[component + "Path"]; if (path == null) path = options.basePath; if (path && path.slice(-1) != "/") path += "/"; return path + component + "-" + 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); }; }); define("ace_tree/layer/cells",[], function(require, exports, module) { "use strict"; var oop = require("ace/lib/oop"); var dom = require("ace/lib/dom"); var lang = require("ace/lib/lang"); var escapeHTML = lang.escapeHTML; var EventEmitter = require("ace/lib/event_emitter").EventEmitter; var Cells = function(parentEl) { this.element = dom.createElement("div"); this.element.className = "ace_tree_layer ace_tree_cell-layer"; parentEl.appendChild(this.element); }; (function() { oop.implement(this, EventEmitter); this.config = {}, this.setDataProvider = function(provider) { this.provider = provider; if (provider) this.update = provider.renderRow ? this.$customUpdate : this.$treeModeUpdate; }; this.update = function (config) { }; this.measureSizes = function() { var domNode = this.element.firstChild; if (domNode) { this.provider.rowHeight = domNode.offsetHeight; this.provider.rowHeightInner = domNode.clientHeight; } }; this.$treeModeUpdate = function (config) { this.config = config; var provider = this.provider; var row, html = [], view = config.view, datarow; var firstRow = config.firstRow, lastRow = config.lastRow + 1; var hsize = "auto;", vsize = provider.rowHeightInner || provider.rowHeight; for (row = firstRow; row < lastRow; row++) { datarow = view[row - firstRow]; if (provider.getItemHeight) vsize = provider.getItemHeight(datarow, row); this.$renderRow(html, datarow, vsize, hsize, row); } if (firstRow <= 0 && lastRow <= 0) { this.renderPlaceHolder(provider, html, config); } this.element.innerHTML = html.join(""); if (!vsize) { this.measureSizes(); } }; this.columnNode = function(datarow, column) { return ""; }; this.getRowClass = function(datarow, row) { var provider = this.provider; return "tree-row " + (provider.isSelected(datarow) ? "selected ": '') + (provider.getClassName(datarow) || "") + (row & 1 ? " odd" : " even"); }; this.$renderRow = function(html, datarow, vsize, hsize, row) { var provider = this.provider; var columns = provider.columns; var indent = provider.$indentSize;// provider.getIndent(datarow); html.push("
"); if (!columns || columns[0].type == "tree") { if (columns) { html.push(this.columnNode(datarow, columns[0], row)); } var depth = provider.getRowIndent(datarow); html.push( (depth ? "" : "" ) + "" + (provider.getCheckboxHTML ? provider.getCheckboxHTML(datarow) : "") + provider.getIconHTML(datarow) + ( provider.getContentHTML ? provider.getContentHTML(datarow) : "" + provider.getCaptionHTML(datarow) + "" ) ); } if (columns) { for (var col = columns[0].type == "tree" ? 1 : 0; col < columns.length; col++) { var column = columns[col]; var rowStr = (column.getHTML) ? column.getHTML(datarow) : escapeHTML(column.getText(datarow) + ""); html.push("" + this.columnNode(datarow, column, row) + rowStr); } html.push(""); } html.push("
"); }; this.$customUpdate = function(config) { this.config = config; var provider = this.provider; var html = []; var firstRow = config.firstRow, lastRow = config.lastRow + 1; for (var row = firstRow; row < lastRow; row++) { provider.renderRow(row, html, config); } if (firstRow <= 0 && lastRow <= 0) { this.renderPlaceHolder(provider, html, config); } this.element.innerHTML = html.join(""); }; this.updateClasses = function(config) { if (this.update == this.$customUpdate && !this.provider.updateNode) return this.update(config); this.config = config; var provider = this.provider; var row, view = config.view, datarow; var firstRow = config.firstRow, lastRow = config.lastRow + 1; var children = this.element.children; if (children.length != lastRow - firstRow) return this.update(config); for (row = firstRow; row < lastRow; row++) { datarow = view[row - firstRow]; var el = children[row - firstRow]; el.className = this.getRowClass(datarow, row); if (provider.redrawNode) provider.redrawNode(el, datarow); } }; this.scroll = function(config) { return this.update(config); this.element.insertAdjacentHTML("afterBegin", "ar"); this.element.insertAdjacentHTML("beforeEnd", "ar"); }; this.updateRows = function(config, firstRow, lastRow) { }; this.destroy = function() { }; this.getDomNodeAtIndex = function(i) { return this.element.children[i - this.config.firstRow]; }; this.renderPlaceHolder = function(provider, html, config) { if (provider.renderEmptyMessage) { provider.renderEmptyMessage(html, config); } else if (provider.getEmptyMessage) { html.push( "
", escapeHTML(provider.getEmptyMessage()), "
" ); } }; }).call(Cells.prototype); exports.Cells = Cells; }); define("ace_tree/layer/markers",[], function(require, exports, module) { "use strict"; var dom = require("ace/lib/dom"); var Selection = function(parentEl, renderer) { this.element = dom.createElement("div"); this.element.className = "ace_tree_layer ace_tree_selection-layer"; parentEl.appendChild(this.element); this.renderer = renderer; this.markerEl = null; this.arrowEl = null; }; (function() { this.setDataProvider = function(provider) { this.provider = provider; }; this.update = function(config) { if (!this.provider.markedFolder || this.provider.markedFolderType) { this.markerEl && this.clearFolderMarker(); } else { this.showFolderMarker(config); } if (!this.provider.markedFolder || !this.provider.markedFolderType) { this.arrowEl && this.clearInsertionMarker(); } else { this.showInsertionMarker(config); } }; this.showFolderMarker = function(config) { this.config = config; var provider = this.provider; var node = provider.markedFolder; var start = provider.getIndexForNode(node); var items = provider.visibleItems; var end = start + 1; var depth = node.$depth; while (items[end] && items[end].$depth > depth) { end++; } end --; if (start > config.lastRow || end < config.firstRow || start === end) { return this.clearFolderMarker(); } start++; end++; var top = Math.max(start - config.firstRow, - 1) * provider.rowHeight; var left = (depth + 1) * provider.$indentSize; var bottom = Math.min(end - config.firstRow, config.lastRow - config.firstRow + 2) * provider.rowHeight; if (!this.markerEl) { this.markerEl = dom.createElement("div"); this.markerEl.className = "dragHighlight"; this.element.appendChild(this.markerEl); } this.markerEl.style.top = top + "px"; this.markerEl.style.left = left + "px"; this.markerEl.style.right = "7px"; this.markerEl.style.height = bottom - top + "px"; }; this.showInsertionMarker = function(config) { this.config = config; var provider = this.provider; var node = provider.markedFolder; var type = this.provider.markedFolderType; var start = provider.getIndexForNode(node); var depth = node.$depth; if (start > config.lastRow || start < config.firstRow) { return this.clearInsertionMarker(); } if (type == 1) start++; var top = Math.max(start - config.firstRow, - 1) * provider.rowHeight; var left = (depth + 1) * provider.$indentSize; if (!this.arrowEl) { this.arrowEl = dom.createElement("div"); this.arrowEl.className = "dragArrow"; this.element.appendChild(this.arrowEl); } this.arrowEl.style.top = top + "px"; this.arrowEl.style.left = left + "px"; this.arrowEl.style.right = "7px"; }; this.clearFolderMarker = function() { if (this.markerEl) { this.markerEl.parentNode.removeChild(this.markerEl); this.markerEl = null; } }; this.clearInsertionMarker = function() { if (this.arrowEl) { this.arrowEl.parentNode.removeChild(this.arrowEl); this.arrowEl = null; } }; this.clear = function() { this.clearFolderMarker(); this.clearInsertMarker(); }; this.destroy = function() { }; }).call(Selection.prototype); exports.Selection = Selection; }); define("ace_tree/layer/heading",[], function(require, exports, module) { "use strict"; var oop = require("ace/lib/oop"); var dom = require("ace/lib/dom"); var lang = require("ace/lib/lang"); var EventEmitter = require("ace/lib/event_emitter").EventEmitter; var RESIZER_WIDTH = 3; function getColumnText(node) { return node[this.value] || this.defaultValue || ""; } function ColumnHeader(parentEl, renderer) { this.element = dom.createElement("div"); parentEl.appendChild(this.element); this.element.className = "tree-headings"; this.visible = false; } (function() { this.minWidth = 25; this.update = function() { if (!this.provider || !this.visible) return; var columns = this.provider.columns; var html = []; for (var i = 0; i < columns.length; i++) { var col = columns[i]; html.push("" + col.caption + "" + "" + "" ); } this.element.style.paddingRight = columns.$fixedWidth; this.element.innerHTML = html.join(""); }; this.setDataProvider = function(provider) { this.provider = provider; if (!provider) return; var columns = this.provider.columns; if (!columns) { this.visible = false; return; } this.visible = true; var fixedWidth = 0; columns.forEach(function(col, i) { col.index = i; if (col.value && !col.getText) col.getText = getColumnText; var w = col.width; if (typeof w == "string" && w.slice(-1) == "%") { col.flex = parseInt(w, 10) / 100; col.$width = col.width; } else { col.width = parseInt(w, 10) || this.minWidth; fixedWidth += col.width; col.$width = col.width + "px"; } col.pixelWidth = 0; }, this); columns.fixedWidth = fixedWidth; columns.$fixedWidth = fixedWidth + "px"; columns.width = null; provider.columns = columns; }; this.updateWidth = function(width) { if (!this.provider || !this.visible) return; var columns = this.provider.columns; var fixedWidth = 0; columns.width = width; columns.forEach(function(col) { if (!col.flex) { fixedWidth += col.width; } }); var flexWidth = width - fixedWidth; columns.forEach(function(col) { if (col.flex) { col.pixelWidth = flexWidth * col.flex; col.$width = col.flex * 100 + "%"; } else { col.pixelWidth = col.width; col.$width = col.width + "px"; } }); columns.fixedWidth = fixedWidth; columns.$fixedWidth = fixedWidth + "px"; }; this.changeColumnWidth = function(changedColumn, dw, total) { this.updateWidth(total); var columns = this.provider.columns; var minWidth = this.minWidth; if (!dw) return; var index = columns.indexOf(changedColumn); var col, nextCol, prevCol; for (var i = index + 1; i < columns.length; i++) { col = columns[i]; if (Math.floor(col.pixelWidth) > minWidth || dw < 0) { if (col.flex) { nextCol = col; break; } else if (!nextCol) { nextCol = col; } } } for (var i = index; i >= 0; i--) { col = columns[i]; if (Math.floor(col.pixelWidth) > minWidth || dw > 0) { if (col.flex) { prevCol = col; break; } else if (!prevCol) { prevCol = col; if (col == changedColumn) break; } } } if (!prevCol || !nextCol) return; if (nextCol.pixelWidth - dw < minWidth) dw = nextCol.pixelWidth - minWidth; if (prevCol.pixelWidth + dw < minWidth) dw = minWidth - prevCol.pixelWidth; nextCol.pixelWidth -= dw; prevCol.pixelWidth += dw; if (!nextCol.flex) columns.fixedWidth -= dw; if (!prevCol.flex) columns.fixedWidth += dw; var flexWidth = total - columns.fixedWidth; columns.forEach(function(col) { if (col.flex) { col.flex = col.pixelWidth / flexWidth; } else { col.width = col.pixelWidth; } }); this.updateWidth(total); }; this.findColumn = function(x) { var columns = this.provider.columns; if (this.element.offsetWidth != columns.width) this.updateWidth(this.element.offsetWidth); var w = 0; for (var i = 0; i < columns.length; i++) { var column = columns[i]; w += column.pixelWidth; if (x < w + RESIZER_WIDTH) { return { index: i, column: column, overResizer: x > w - RESIZER_WIDTH }; } } }; }).call(ColumnHeader.prototype); exports.ColumnHeader = ColumnHeader; }); define("ace/lib/keys",[], 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' }, KEY_MODS: { "ctrl": 1, "alt": 2, "option" : 2, "shift": 4, "super": 8, "meta": 8, "command": 8, "cmd": 8 }, 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(); }; }); define("ace/lib/event",[], function(require, exports, module) { "use strict"; var keys = require("./keys"); var useragent = require("./useragent"); var pressedKeys = null; var ts = 0; exports.addListener = function(elem, type, callback) { if (elem.addEventListener) { return elem.addEventListener(type, callback, false); } if (elem.attachEvent) { var wrapper = function() { callback.call(elem, window.event); }; callback._wrapper = wrapper; elem.attachEvent("on" + type, wrapper); } }; exports.removeListener = function(elem, type, callback) { if (elem.removeEventListener) { return elem.removeEventListener(type, callback, false); } if (elem.detachEvent) { elem.detachEvent("on" + type, callback._wrapper || callback); } }; exports.stopEvent = function(e) { exports.stopPropagation(e); exports.preventDefault(e); return false; }; exports.stopPropagation = function(e) { if (e.stopPropagation) e.stopPropagation(); else e.cancelBubble = true; }; exports.preventDefault = function(e) { if (e.preventDefault) e.preventDefault(); else e.returnValue = false; }; exports.getButton = function(e) { if (e.type == "dblclick") return 0; if (e.type == "contextmenu" || (useragent.isMac && (e.ctrlKey && !e.altKey && !e.shiftKey))) return 2; if (e.preventDefault) { return e.button; } else { return {1:0, 2:2, 4:1}[e.button]; } }; exports.capture = function(el, eventHandler, releaseCaptureHandler) { function onMouseUp(e) { eventHandler && eventHandler(e); releaseCaptureHandler && releaseCaptureHandler(e); exports.removeListener(document, "mousemove", eventHandler, true); exports.removeListener(document, "mouseup", onMouseUp, true); exports.removeListener(document, "dragstart", onMouseUp, true); } exports.addListener(document, "mousemove", eventHandler, true); exports.addListener(document, "mouseup", onMouseUp, true); exports.addListener(document, "dragstart", onMouseUp, true); return onMouseUp; }; exports.addTouchMoveListener = function (el, callback) { var startx, starty; exports.addListener(el, "touchstart", function (e) { var touches = e.touches; var touchObj = touches[0]; startx = touchObj.clientX; starty = touchObj.clientY; }); exports.addListener(el, "touchmove", function (e) { var touches = e.touches; if (touches.length > 1) return; var touchObj = touches[0]; e.wheelX = startx - touchObj.clientX; e.wheelY = starty - touchObj.clientY; startx = touchObj.clientX; starty = touchObj.clientY; callback(e); }); }; exports.addMouseWheelListener = function(el, callback) { if ("onmousewheel" in el) { exports.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); }); } else if ("onwheel" in el) { exports.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); }); } else { exports.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); }); } }; exports.addMultiMouseDownListener = function(elements, timeouts, eventHandler, callbackName) { 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); } function onDblclick(e) { clicks = 2; if (timer) clearTimeout(timer); timer = setTimeout(function() {timer = null;}, timeouts[clicks - 1] || 600); eventHandler[callbackName]("mousedown", e); eventHandler[callbackName](eventNames[clicks], e); } if (!Array.isArray(elements)) elements = [elements]; elements.forEach(function(el) { exports.addListener(el, "mousedown", onMousedown); if (useragent.isOldIE) exports.addListener(el, "dblclick", onDblclick); }); }; var getModifierHash = useragent.isMac && useragent.isOpera && !("KeyboardEvent" in window) ? function(e) { return 0 | (e.metaKey ? 1 : 0) | (e.altKey ? 2 : 0) | (e.shiftKey ? 4 : 0) | (e.ctrlKey ? 8 : 0); } : 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 & 8 && (keyCode >= 91 && keyCode <= 93)) { 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) { var addListener = exports.addListener; if (useragent.isOldGecko || (useragent.isOpera && !("KeyboardEvent" in window))) { var lastKeyDownKeyCode = null; addListener(el, "keydown", function(e) { lastKeyDownKeyCode = e.keyCode; }); addListener(el, "keypress", function(e) { return normalizeCommandKeys(callback, e, lastKeyDownKeyCode); }); } 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; }); addListener(el, "keypress", function(e) { if (lastDefaultPrevented && (e.ctrlKey || e.altKey || e.shiftKey || e.metaKey)) { exports.stopEvent(e); lastDefaultPrevented = null; } }); addListener(el, "keyup", function(e) { pressedKeys[e.keyCode] = null; }); 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); exports.removeListener(win, "message", listener); callback(); } }; exports.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); }; }); define("ace/scrollbar",[], 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.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; }); define("ace/renderloop",[], 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.window = win || window; }; (function() { this.schedule = function(change) { this.changes = this.changes | change; if (this.changes) { var _self = this; event.nextFrame(function(ts) { var changes = _self.changes; if (changes) { event.blockIdle(100); _self.changes = 0; _self.onRender(changes); } if (_self.changes) _self.schedule(); }); } }; }).call(RenderLoop.prototype); exports.RenderLoop = RenderLoop; }); define("ace/requirejs/text!ace_tree/css/tree.css",[],""); define("ace/requirejs/text!ace_tree/css/light_theme.css",[],""); define("ace_tree/css/light_theme",[], function(require, exports, module) { exports.isDark = false; exports.cssClass = "ace_tree-light"; exports.cssText = require("ace/requirejs/text!./light_theme.css"); var dom = require("ace/lib/dom"); dom.importCssString(exports.cssText, exports.cssClass); }); define("ace_tree/virtual_renderer",[], function(require, exports, module) { "use strict"; var oop = require("ace/lib/oop"); var dom = require("ace/lib/dom"); var config = require("./config"); var CellLayer = require("./layer/cells").Cells; var MarkerLayer = require("./layer/markers").Selection; var HeaderLayer = require("./layer/heading").ColumnHeader; var ScrollBarH = require("ace/scrollbar").ScrollBarH; var ScrollBarV = require("ace/scrollbar").ScrollBarV; var RenderLoop = require("ace/renderloop").RenderLoop; var EventEmitter = require("ace/lib/event_emitter").EventEmitter; var pivotCss = require("ace/requirejs/text!./css/tree.css"); dom.importCssString(pivotCss, "ace_tree"); var defaultTheme = require("./css/light_theme"); var VirtualRenderer = function(container, cellWidth, cellHeight) { var _self = this; this.container = container || dom.createElement("div"); dom.addCssClass(this.container, "ace_tree"); dom.addCssClass(this.container, "ace_tree"); this.setTheme(this.$theme); this.scroller = dom.createElement("div"); this.scroller.className = "ace_tree_scroller"; this.container.appendChild(this.scroller); this.cells = dom.createElement("div"); this.cells.className = "ace_tree_cells"; this.scroller.appendChild(this.cells); this.$headingLayer = new HeaderLayer(this.container, this); this.$markerLayer = new MarkerLayer(this.cells, this); this.$cellLayer = new CellLayer(this.cells); this.canvas = this.$cellLayer.element; this.$horizScroll = false; this.scrollBarV = new ScrollBarV(this.container, this); this.scrollBarV.setVisible(true); this.scrollBarV.addEventListener("scroll", function(e) { if (!_self.$inScrollAnimation) _self.setScrollTop(e.data - _self.scrollMargin.top); }); this.scrollBarH = new ScrollBarH(this.container, this); this.scrollBarH.addEventListener("scroll", function(e) { if (!_self.$inScrollAnimation) _self.setScrollLeft(e.data); }); this.scrollTop = 0; this.scrollLeft = 0; this.caretPos = { row : 0, column : 0 }; this.$size = { width: 0, height: 0, scrollerHeight: 0, scrollerWidth: 0, headingHeight: 0 }; this.layerConfig = { width : 1, padding : 0, firstRow : 0, firstRowScreen: 0, lastRow : 0, lineHeight : 1, characterWidth : 1, minHeight : 1, maxHeight : 1, offset : 0, height : 1 }; this.scrollMargin = { left: 0, right: 0, top: 0, bottom: 0, v: 0, h: 0 }; this.$scrollIntoView = null; this.$loop = new RenderLoop( this.$renderChanges.bind(this), this.container.ownerDocument.defaultView ); this.$loop.schedule(this.CHANGE_FULL); this.setTheme(defaultTheme); this.$windowFocus = this.$windowFocus.bind(this); window.addEventListener("focus", this.$windowFocus); }; (function() { this.CHANGE_SCROLL = 1; this.CHANGE_COLUMN = 2; this.CHANGE_ROW = 4; this.CHANGE_CELLS = 8; this.CHANGE_SIZE = 16; this.CHANGE_CLASS = 32; this.CHANGE_MARKER = 64; this.CHANGE_FULL = 128; this.CHANGE_H_SCROLL = 1024; oop.implement(this, EventEmitter); this.setDataProvider = function(provider) { this.provider = provider; this.model = provider; if (this.scrollMargin.top && provider && provider.getScrollTop() <= 0) provider.setScrollTop(-this.scrollMargin.top); this.scroller.className = "ace_tree_scroller"; this.$cellLayer.setDataProvider(provider); this.$markerLayer.setDataProvider(provider); this.$headingLayer.setDataProvider(provider); this.$size.headingHeight = provider && provider.columns ? provider.headerHeight || provider.rowHeight : 0; this.$loop.schedule(this.CHANGE_FULL); }; this.updateRows = function(firstRow, lastRow) { 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.firstRow > this.layerConfig.lastRow || this.$changedLines.lastRow < this.layerConfig.firstRow) return; this.$loop.schedule(this.CHANGE_ROW); }; this.updateCaret = function() { this.$loop.schedule(this.CHANGE_CLASS); }; this.updateCells = function() { this.$loop.schedule(this.CHANGE_CELLS); }; this.updateFull = function(force) { if (force) this.$renderChanges(this.CHANGE_FULL, true); else this.$loop.schedule(this.CHANGE_FULL); }; this.updateHorizontalHeadings = function(){ this.$loop.schedule(this.CHANGE_COLUMN); }; this.updateVerticalHeadings = function(){ this.$loop.schedule(this.CHANGE_ROW); }; this.$changes = 0; this.onResize = function(force, 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, width, height); if (!this.$size.scrollerHeight || (!width && !height)) return this.resizing = 0; if (force) this.$renderChanges(changes, true); else this.$loop.schedule(changes | this.$changes); if (this.resizing) this.resizing = 0; }; this.$windowFocus = function(){ this.onResize(); }; this.$updateCachedSize = function(force, width, height) { var changes = 0; var size = this.$size; var provider = this.provider; if (provider) { var headingHeight = provider.columns ? provider.headerHeight || provider.rowHeight : 0; if (headingHeight != size.headingHeight) { size.headingHeight = headingHeight; changes |= this.CHANGE_SIZE; } } 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(); size.scrollerHeight -= size.headingHeight; this.$headingLayer.element.style.height = this.scroller.style.top = this.scrollBarV.element.style.top = size.headingHeight + "px"; this.scrollBarV.element.style.bottom = this.scrollBarH.getHeight() + "px"; if (provider && provider.setScrollTop) { changes |= this.CHANGE_SCROLL; } if (this.$scrollIntoView) if (this.$scrollIntoView.model == this.model) { this.scrollCaretIntoView(this.$scrollIntoView.caret, this.$scrollIntoView.offset); this.$scrollIntoView = null; } } if (width && (force || size.width != width)) { changes |= this.CHANGE_SIZE; size.width = width; this.scrollBarH.element.style.left = this.scroller.style.left = 0 + "px"; size.scrollerWidth = Math.max(0, width - this.scrollBarV.getWidth()); this.$headingLayer.element.style.right = this.scrollBarH.element.style.right = this.scroller.style.right = this.scrollBarV.getWidth() + "px"; this.scroller.style.bottom = this.scrollBarH.getHeight() + "px"; this.$headingLayer.updateWidth(size.scrollerWidth); if (provider && provider.columns) changes |= this.CHANGE_FULL; } if (changes) this._signal("resize"); return changes; }; this.setVerHeadingVisible = function(value){ this.$treeLayer.visible = value; if (this.layerConfig.vRange && this.layerConfig.hRange) { this.$renderChanges(this.CHANGE_FULL, true); this.onResize(true); } }; this.getContainerElement = function() { return this.container; }; this.getMouseEventTarget = function() { return this.scroller; }; this.getVisibleNodes = function(tolerance) { var nodes = this.layerConfig.vRange; var first = 0; var last = nodes.length - 1; while (this.isNodeVisible(nodes[first], tolerance) && first < last) first++; while (!this.isNodeVisible(nodes[last], tolerance) && last > first) last--; return nodes.slice(first, last + 1); }; this.isNodeVisible = function(node, tolerance) { var layerConfig = this.layerConfig; if (!layerConfig.vRange) return; var provider = this.provider; var i = layerConfig.vRange.indexOf(node); if (i == -1) return false; var nodePos = provider.getNodePosition(node); var top = nodePos.top; var height = nodePos.height; if (tolerance === undefined) tolerance = 1 / 3; if (this.scrollTop > top + tolerance * height) return false; if (this.scrollTop + this.$size.scrollerHeight <= top + (1 - tolerance) * height) return false; return true; }; this.$updateScrollBar = function() { this.$updateScrollBarH(); this.$updateScrollBarV(); }; 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.provider) this.provider.setScrollTop(-sm.top); this.updateFull(); }; this.$updateScrollBarV = function() { this.scrollBarV.setInnerHeight(this.layerConfig.maxHeight + this.scrollMargin.v); this.scrollBarV.setScrollTop(this.scrollTop + this.scrollMargin.top); }; this.$updateScrollBarH = function() { this.scrollBarH.setInnerWidth(this.layerConfig.maxWidth + 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.provider || !this.container.offsetWidth || this.$frozen) || (!changes && !force)) { this.$changes |= changes; return; } if (!this.$size.width) { this.$changes |= changes; return this.onResize(true); } this._signal("beforeRender"); var config = this.layerConfig; if (changes & this.CHANGE_FULL || changes & this.CHANGE_SIZE || changes & this.CHANGE_SCROLL || changes & this.CHANGE_H_SCROLL || changes & this.CHANGE_COLUMN || changes & this.CHANGE_ROW || changes & this.CHANGE_CELLS ) { changes |=this.$computeLayerConfig(); config = this.layerConfig; this.$updateScrollBar(); this.cells.style.marginTop = -config.vOffset + "px"; this.cells.style.marginLeft = -config.hOffset + "px"; this.cells.style.width = config.width + "px"; this.cells.style.height = config.height + config.rowHeight + "px"; } if (changes & this.CHANGE_FULL) { this.$headingLayer.update(this.layerConfig); this.$cellLayer.update(this.layerConfig); this.$markerLayer.update(this.layerConfig); this._signal("afterRender"); return; } if (changes & this.CHANGE_SCROLL) { if (changes & this.CHANGE_ROW || changes & this.CHANGE_COLUMN || changes & this.CHANGE_CELLS ) { this.$headingLayer.update(this.layerConfig); this.$cellLayer.update(this.layerConfig); } else { this.$headingLayer.update(this.layerConfig); this.$cellLayer.scroll(this.layerConfig); } this.$markerLayer.update(this.layerConfig); this.$updateScrollBar(); this._signal("afterRender"); return; } if (changes & this.CHANGE_CLASS) this.$cellLayer.updateClasses(this.layerConfig); if (changes & this.CHANGE_MARKER || changes & this.CHANGE_CELLS) this.$markerLayer.update(this.layerConfig); if (changes & this.CHANGE_COLUMN) this.$horHeadingLayer.update(this.layerConfig); if (changes & this.CHANGE_CELLS) this.$cellLayer.update(this.layerConfig); if (changes & this.CHANGE_SIZE) this.$updateScrollBar(); this._signal("afterRender"); if (this.$scrollIntoView) this.$scrollIntoView = null; }; this.$autosize = function() { var headingHeight = this.$size.headingHeight; var height = this.provider.getTotalHeight() + headingHeight; var maxHeight = this.getMaxHeight ? this.getMaxHeight() : this.$maxLines * this.provider.rowHeight + headingHeight; var desiredHeight = Math.max( (this.$minLines || 1) * this.provider.rowHeight + headingHeight, Math.min(maxHeight, height) ) + this.scrollMargin.v; var vScroll = 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, w, desiredHeight); this.desiredHeight = desiredHeight; this._signal("autoresize"); } }; this.$computeLayerConfig = function() { if (this.$maxLines) this.$autosize(); var provider = this.provider; var vertical = this.$treeLayer; var horizontal = this.$horHeadingLayer; var minHeight = this.$size.scrollerHeight; var maxHeight = provider.getTotalHeight(); var minWidth = this.$size.scrollerWidth; var maxWidth = 0 //horizontal.size; var hideScrollbars = this.$size.height <= 2 * 10; var horizScroll = !hideScrollbars && (this.$hScrollBarAlwaysVisible || this.$size.scrollerWidth - maxWidth < 0); var hScrollChanged = this.$horizScroll !== horizScroll; if (hScrollChanged) { this.$horizScroll = horizScroll; this.scrollBarH.setVisible(horizScroll); } var vScroll = !hideScrollbars && (this.$vScrollBarAlwaysVisible || this.$size.scrollerHeight - maxHeight < 0); var vScrollChanged = this.$vScroll !== vScroll; if (vScrollChanged) { this.$vScroll = vScroll; this.scrollBarV.setVisible(vScroll); } this.provider.setScrollTop(Math.max(-this.scrollMargin.top, Math.min(this.scrollTop, maxHeight - this.$size.scrollerHeight + this.scrollMargin.bottom))); this.provider.setScrollLeft(Math.max(-this.scrollMargin.left, Math.min(this.scrollLeft, maxWidth - this.$size.scrollerWidth + this.scrollMargin.right))); if (this.provider.getScrollTop() != this.scrollTop) this.scrollTop = this.provider.getScrollTop(); var top = Math.max(this.scrollTop, 0); var vRange = provider.getRange(top, top + this.$size.height); var hRange = { size: 0 };// horizontal.getRange(this.scrollLeft, this.scrollLeft + this.$size.width); var vOffset = this.scrollTop - vRange.size; var hOffset = this.scrollLeft - hRange.size; var rowCount = vRange.length; var firstRow = vRange.count; var lastRow = firstRow + rowCount - 1; var colCount = hRange.length; var firstCol = hRange.count; var lastCol = firstCol + colCount - 1; if (this.layerConfig) this.layerConfig.discard = true; var changes = 0; if (hScrollChanged || vScrollChanged) { changes = this.$updateCachedSize(true, this.$size.width, this.$size.height); this._signal("scrollbarVisibilityChanged"); } this.layerConfig = { vRange : vRange, hRange : hRange, width : minWidth, height : minHeight, firstRow : firstRow, lastRow : lastRow, firstCol : firstCol, lastCol : lastCol, minHeight : minHeight, maxHeight : maxHeight, minWidth : minWidth, maxWidth : maxWidth, vOffset : vOffset, hOffset : hOffset, rowHeight: provider.rowHeight }; var config = this.layerConfig, renderer = this; if (vRange) { config.view = provider.getDataRange( {start: vRange.count, length: vRange.length}, {start: hRange.count, length: hRange.length}, function(err, view, update){ if (err) return false; //@todo config.view = view; if (update) renderer.$loop.schedule(renderer.CHANGE_CELLS); }); } return changes; }; this.$updateRows = function() { 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) { this.$cellLayer.update(layerConfig); return; } this.$cellLayer.updateRows(layerConfig, firstRow, lastRow); return true; }; this.scrollSelectionIntoView = function(anchor, lead, offset) { this.scrollCaretIntoView(anchor, offset); this.scrollCaretIntoView(lead, offset); }; this.scrollCaretIntoView = function(caret, offset) { this.$scrollIntoView = { caret: caret, offset: offset, scrollTop: this.scrollTop, model: this.model, height: this.$size.scrollerHeight }; if (this.$size.scrollerHeight === 0) return; var provider = this.provider; var node = caret || provider.selection.getCursor(); if (!node) return; var nodePos = provider.getNodePosition(node); var top = nodePos.top; var height = nodePos.height; var left = 0; var width = 0; if (this.scrollTop > top) { if (offset) top -= offset * this.$size.scrollerHeight; if (top === 0) top = -this.scrollMargin.top; this.provider.setScrollTop(top); } else if (this.scrollTop + this.$size.scrollerHeight < top + height) { if (offset) top += offset * this.$size.scrollerHeight; this.provider.setScrollTop(top + height - this.$size.scrollerHeight); } var scrollLeft = this.scrollLeft; if (scrollLeft > left) { if (left < 0) left = 0; this.provider.setScrollLeft(left); } else if (scrollLeft + this.$size.scrollerWidth < left + width) { this.provider.setScrollLeft(Math.round(left + width - this.$size.scrollerWidth)); } this.$scrollIntoView.scrollTop = this.scrollTop; }; this.getScrollTop = function() { return this.scrollTop; }; this.getScrollLeft = function() { return this.scrollLeft; }; this.setScrollTop = function(scrollTop) { scrollTop = Math.round(scrollTop); if (this.scrollTop === scrollTop || isNaN(scrollTop)) return; this.scrollToY(scrollTop); }; this.setScrollLeft = function(scrollLeft) { scrollLeft = Math.round(scrollLeft); if (this.scrollLeft === scrollLeft || isNaN(scrollLeft)) return; this.scrollToX(scrollLeft); }; this.getScrollTopRow = function() { return this.layerConfig.firstRow; }; this.getScrollBottomRow = function() { return this.layerConfig.lastRow; }; this.alignCaret = function(cursor, alignment) { if (typeof cursor == "number") cursor = {row: cursor, column: 0}; var node = this.provider.findNodeByIndex(cursor.row); var pos = this.provider.findSizeAtIndex(cursor.row); var h = this.$size.scrollerHeight; var offset = pos - ((h - node.size) * (alignment || 0)); this.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.scrollToRow = function(row, center, animate, callback) { var node = this.provider.findNodeByIndex(row); var offset = this.provider.findSizeAtIndex(row); if (center) offset -= (this.$size.scrollerHeight - node.size) / 2; var initialScroll = this.scrollTop; this.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.provider.setScrollTop(steps.shift()); _self.provider.$scrollTop = toValue; this.$timer = setInterval(function() { if (steps.length) { _self.provider.setScrollTop(steps.shift()); _self.provider.$scrollTop = toValue; } else if (toValue != null) { _self.provider.$scrollTop = -1; _self.provider.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 (scrollLeft < 0) scrollLeft = 0; if (this.scrollLeft !== scrollLeft) { this.$loop.schedule(this.CHANGE_SCROLL); this.scrollLeft = scrollLeft; } }; this.scrollBy = function(deltaX, deltaY) { deltaY && this.provider.setScrollTop(this.provider.getScrollTop() + deltaY); deltaX && this.provider.setScrollLeft(this.provider.getScrollLeft() + deltaX); }; this.isScrollableBy = function(deltaX, deltaY) { if (deltaY < 0 && this.getScrollTop() >= 1 - this.scrollMargin.top) return true; if (deltaY > 0 && this.getScrollTop() + this.$size.scrollerHeight - this.layerConfig.maxHeight < -1 + this.scrollMargin.bottom) return true; if (deltaX < 0 && this.getScrollLeft() >= 1) return true; if (deltaX > 0 && this.getScrollLeft() + this.$size.scrollerWidth - this.layerConfig.maxWidth < -1) return true; }; this.screenToTextCoordinates = function(x, y) { var canvasPos = this.scroller.getBoundingClientRect(); y -= canvasPos.top; x -= canvasPos.left; return { x : x + this.scrollLeft, y : y + this.scrollTop }; }; this.textToScreenCoordinates = function(row, column) { throw new Error(); }; this.findNodeAt = function(x, y, coords) { }; this.$moveTextAreaToCursor = function(){}; this.visualizeFocus = function() { dom.addCssClass(this.container, "ace_tree_focus"); }; this.visualizeBlur = function() { dom.removeCssClass(this.container, "ace_tree_focus"); }; this.setTheme = function(theme, cb) { var _self = this; this.$themeValue = theme; _self._dispatchEvent('themeChange',{theme:theme}); if (!theme || typeof theme == "string") { var moduleName = theme || "ace/theme/textmate"; config.loadModule(["theme", moduleName], afterLoad); } else { afterLoad(theme); } function afterLoad(module) { if (_self.$themeValue != theme) return cb && cb(); if (!module.cssClass) return; dom.importCssString( module.cssText, module.cssClass, _self.container.ownerDocument ); if (_self.theme) dom.removeCssClass(_self.container, _self.theme.cssClass); _self.$theme = module.cssClass; _self.theme = module; dom.addCssClass(_self.container, module.cssClass); dom.setCssClass(_self.container, "ace_dark", module.isDark); var padding = module.padding || 4; if (_self.$padding && padding != _self.$padding) _self.setPadding(padding); if (_self.$size) { _self.$size.width = 0; _self.onResize(); } _self._dispatchEvent('themeLoaded', {theme:module}); cb && cb(); } }; this.getTheme = function() { return this.$themeValue; }; this.setStyle = function setStyle(style, include) { dom.setCssClass(this.container, style, include !== false); }; this.unsetStyle = function unsetStyle(style) { dom.removeCssClass(this.container, style); }; this.destroy = function() { window.removeEventListener("focus", this.$windowFocus); this.$cellLayer.destroy(); }; }).call(VirtualRenderer.prototype); config.defineOptions(VirtualRenderer.prototype, "renderer", { animatedScroll: {initialValue: true}, showInvisibles: { set: function(value) { if (this.$cellLayer.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; } }, displayIndentGuides: { set: function(show) { if (this.$cellLayer.setDisplayIndentGuides(show)) this.$loop.schedule(this.CHANGE_TEXT); }, initialValue: true }, hScrollBarAlwaysVisible: { set: function(alwaysVisible) { this.$hScrollBarAlwaysVisible = alwaysVisible; 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) { this.updateFull(); } }, 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 } }); exports.VirtualRenderer = VirtualRenderer; }); define("ace/keyboard/textinput_ios",[], 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 KEYS = require("../lib/keys"); var MODS = KEYS.KEY_MODS; var BROKEN_SETDATA = useragent.isChrome < 18; var USE_IE_MIME_TYPE = useragent.isIE; var TextInput = function(parentNode, host) { var self = this; var text = dom.createElement("textarea"); text.className = useragent.isIOS ? "ace_text-input ace_text-input-ios" : "ace_text-input"; if (useragent.isTouchPad) text.setAttribute("x-palm-disable-auto-cap", true); 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 PLACEHOLDER = "\n aaaa a\n"; var copied = false; var cut = false; var pasted = false; var inComposition = false; var tempStyle = ''; var isSelectionEmpty = true; try { var isFocused = document.activeElement === text; } catch(e) {} event.addListener(text, "blur", function(e) { host.onBlur(e); isFocused = false; }); event.addListener(text, "focus", function(e) { isFocused = true; host.onFocus(e); resetSelection(); }); this.focus = function() { if (tempStyle) return text.focus(); text.style.position = "fixed"; text.focus(); }; this.blur = function() { text.blur(); }; this.isFocused = function() { return isFocused; }; var syncSelection = lang.delayedCall(function() { isFocused && resetSelection(isSelectionEmpty); }); var syncValue = lang.delayedCall(function() { if (!inComposition) { text.value = PLACEHOLDER; isFocused && resetSelection(); } }); function resetSelection(isEmpty) { if (inComposition) return; inComposition = true; if (inputHandler) { selectionStart = 0; selectionEnd = isEmpty ? 0 : text.value.length - 1; } else { var selectionStart = 4; var selectionEnd = 5; } try { text.setSelectionRange(selectionStart, selectionEnd); } catch(e) {} inComposition = false; } function resetValue() { if (inComposition) return; text.value = PLACEHOLDER; if (useragent.isWebKit) syncValue.schedule(); } useragent.isWebKit || host.addEventListener('changeSelection', function() { if (host.selection.isEmpty() != isSelectionEmpty) { isSelectionEmpty = !isSelectionEmpty; syncSelection.schedule(); } }); resetValue(); if (isFocused) host.onFocus(); var isAllSelected = function(text) { return text.selectionStart === 0 && text.selectionEnd === text.value.length; }; var onSelect = function(e) { if (isAllSelected(text)) { host.selectAll(); resetSelection(); } else if (inputHandler) { resetSelection(host.selection.isEmpty()); } }; var inputHandler = null; this.setInputHandler = function(cb) {inputHandler = cb;}; this.getInputHandler = function() {return inputHandler;}; var afterContextMenu = false; var sendText = function(data) { if (text.selectionStart === 4 && text.selectionEnd === 5) { return; } if (inputHandler) { data = inputHandler(data); inputHandler = null; } if (pasted) { resetSelection(); if (data) host.onPaste(data); pasted = false; } else if (data == PLACEHOLDER.substr(0) && text.selectionStart === 4) { if (afterContextMenu) host.execCommand("del", {source: "ace"}); else // some versions of android do not fire keydown when pressing backspace host.execCommand("backspace", {source: "ace"}); } else if (!copied) { if (data.substring(0, 9) == PLACEHOLDER && data.length > PLACEHOLDER.length) data = data.substr(9); else if (data.substr(0, 4) == PLACEHOLDER.substr(0, 4)) data = data.substr(4, data.length - PLACEHOLDER.length + 1); else if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0)) data = data.slice(0, -1); if (data == PLACEHOLDER.charAt(0)) { } else if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0)) data = data.slice(0, -1); if (data) host.onTextInput(data); } if (copied) { copied = false; } if (afterContextMenu) afterContextMenu = false; }; var onInput = function(e) { if (inComposition) return; var data = text.value; sendText(data); resetValue(); }; 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 (useragent.isIOS) { cut = isCut; text.value = "\n aa" + data + "a a\n"; text.setSelectionRange(4, 4 + data.length); copied = { value: data }; } isCut ? host.onCut() : host.onCopy(); if (!useragent.isIOS) event.preventDefault(e); } else { copied = true; text.value = data; text.select(); setTimeout(function(){ copied = false; resetValue(); 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 (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)); event.addListener(text, "select", onSelect); event.addListener(text, "input", onInput); event.addListener(text, "cut", onCut); event.addListener(text, "copy", onCopy); event.addListener(text, "paste", onPaste); var onCompositionStart = function(e) { if (inComposition || !host.onCompositionStart || host.$readOnly) return; inComposition = {}; inComposition.canUndo = host.session.$undoManager; host.onCompositionStart(); setTimeout(onCompositionUpdate, 0); host.on("mousedown", onCompositionEnd); if (inComposition.canUndo && !host.selection.isEmpty()) { host.insert(""); host.session.markUndoGroup(); host.selection.clearSelection(); } host.session.markUndoGroup(); }; var onCompositionUpdate = function() { if (!inComposition || !host.onCompositionUpdate || host.$readOnly) return; var val = text.value.replace(/\x01/g, ""); if (inComposition.lastValue === val) return; host.onCompositionUpdate(val); if (inComposition.lastValue) host.undo(); if (inComposition.canUndo) inComposition.lastValue = val; if (inComposition.lastValue) { var r = host.selection.getRange(); host.insert(inComposition.lastValue); host.session.markUndoGroup(); inComposition.range = host.selection.getRange(); host.selection.setRange(r); host.selection.clearSelection(); } }; var onCompositionEnd = function(e) { if (!host.onCompositionEnd || host.$readOnly) return; var c = inComposition; inComposition = false; var timer = setTimeout(function() { timer = null; var str = text.value.replace(/\x01/g, ""); if (inComposition) return; else if (str == c.lastValue) resetValue(); else if (!c.lastValue && str) { resetValue(); sendText(str); } }); inputHandler = function compositionInputHandler(str) { if (timer) clearTimeout(timer); str = str.replace(/\x01/g, ""); if (str == c.lastValue) return ""; if (c.lastValue && timer) host.undo(); return str; }; host.onCompositionEnd(); host.removeListener("mousedown", onCompositionEnd); if (e.type == "compositionend" && c.range) { host.selection.setRange(c.range); } var needsOnInput = (!!useragent.isChrome && useragent.isChrome >= 53) || (!!useragent.isWebKit && useragent.isWebKit >= 603); if (needsOnInput) { onInput(); } }; var syncComposition = lang.delayedCall(onCompositionUpdate, 50); event.addListener(text, "compositionstart", onCompositionStart); event.addListener(text, "compositionupdate", function(){syncComposition.schedule();}); event.addListener(text, "keyup", function(){syncComposition.schedule();}); event.addListener(text, "keydown", function(){syncComposition.schedule();}); event.addListener(text, "compositionend", onCompositionEnd); this.getElement = function() { return text; }; this.setReadOnly = function(readOnly) { text.readOnly = readOnly; }; this.onContextMenu = function(e) { afterContextMenu = true; resetSelection(host.selection.isEmpty()); 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;" : "") + "height:" + text.style.height + ";" + (useragent.isIE ? "opacity:0.1;" : ""); 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) { text.style.left = e.clientX - left - 2 + "px"; text.style.top = Math.min(e.clientY - top - 2, maxTop) + "px"; }; move(e); if (e.type != "mousedown") return; if (host.renderer.$keepTextAreaAtCursor) host.renderer.$keepTextAreaAtCursor = null; 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 = ''; } if (host.renderer.$keepTextAreaAtCursor == null) { host.renderer.$keepTextAreaAtCursor = true; host.renderer.$moveTextAreaToCursor(); } }, 0); } var onContextMenu = function(e) { host.textInput.onContextMenu(e); onContextMenuClose(); }; event.addListener(text, "mouseup", onContextMenu); event.addListener(text, "mousedown", function(e) { e.preventDefault(); onContextMenuClose(); }); event.addListener(host.renderer.scroller, "contextmenu", onContextMenu); event.addListener(text, "contextmenu", onContextMenu); if (useragent.isIOS) { var typingResetTimeout = null; var typing = false; parentNode.addEventListener("keydown", function (e) { if (typingResetTimeout) clearTimeout(typingResetTimeout); typing = true; }); parentNode.addEventListener("keyup", function (e) { typingResetTimeout = setTimeout(function () { typing = false; }, 100); }); var detectArrowKeys = function(e) { if (document.activeElement !== text) return; if (typing) return; if (cut) { return setTimeout(function () { cut = false; }, 100); } var selectionStart = text.selectionStart; var selectionEnd = text.selectionEnd; text.setSelectionRange(4, 5); if (selectionStart == selectionEnd) { switch (selectionStart) { case 0: host.onCommandKey(null, 0, KEYS.up); break; case 1: host.onCommandKey(null, 0, KEYS.home); break; case 2: host.onCommandKey(null, MODS.option, KEYS.left); break; case 4: host.onCommandKey(null, 0, KEYS.left); break; case 5: host.onCommandKey(null, 0, KEYS.right); break; case 7: host.onCommandKey(null, MODS.option, KEYS.right); break; case 8: host.onCommandKey(null, 0, KEYS.end); break; case 9: host.onCommandKey(null, 0, KEYS.down); break; } } else { switch (selectionEnd) { case 6: host.onCommandKey(null, MODS.shift, KEYS.right); break; case 7: host.onCommandKey(null, MODS.shift | MODS.option, KEYS.right); break; case 8: host.onCommandKey(null, MODS.shift, KEYS.end); break; case 9: host.onCommandKey(null, MODS.shift, KEYS.down); break; } switch (selectionStart) { case 0: host.onCommandKey(null, MODS.shift, KEYS.up); break; case 1: host.onCommandKey(null, MODS.shift, KEYS.home); break; case 2: host.onCommandKey(null, MODS.shift | MODS.option, KEYS.left); break; case 3: host.onCommandKey(null, MODS.shift, KEYS.left); break; } } }; document.addEventListener("selectionchange", detectArrowKeys); host.on("destroy", function() { document.removeEventListener("selectionchange", detectArrowKeys); }); } }; exports.TextInput = TextInput; }); define("ace/keyboard/textinput",[], 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 BROKEN_SETDATA = useragent.isChrome < 18; var USE_IE_MIME_TYPE = useragent.isIE; var HAS_FOCUS_ARGS = useragent.isChrome > 63; var TextInputIOS = require("./textinput_ios").TextInput; var TextInput = function(parentNode, host) { if (useragent.isIOS) return TextInputIOS.call(this, 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 PLACEHOLDER = useragent.isIE ? "\x01\x01" : "\u2028\u2028"; var PLACEHOLDER_RE = useragent.isIE ? /\x01/g : /\u2028/g; var copied = false; var pasted = false; var inComposition = false; var tempStyle = ''; var isSelectionEmpty = true; var copyWithEmptySelection = false; var commandMode = false; try { var isFocused = document.activeElement === text; } catch(e) {} event.addListener(text, "blur", function(e) { host.onBlur(e); isFocused = false; }); event.addListener(text, "focus", function(e) { isFocused = true; host.onFocus(e); resetSelection(); }); this.$focusScroll = false; this.focus = function() { if (tempStyle || HAS_FOCUS_ARGS || this.$focusScroll == "browser") return text.focus({ preventScroll: true }); if (!document.documentElement.contains(text)) return; var top = text.style.top; text.style.position = "fixed"; text.style.top = "0px"; var isTransformed = text.getBoundingClientRect().top != 0; 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; }; var syncSelection = lang.delayedCall(function() { isFocused && resetSelection(isSelectionEmpty); }); var syncValue = lang.delayedCall(function() { if (!inComposition) { text.value = PLACEHOLDER; isFocused && resetSelection(); } }); function resetSelection(isEmpty) { isEmpty = copyWithEmptySelection ? false : isEmpty; if (inComposition) return; inComposition = true; if (inputHandler) { var selectionStart = 0; var selectionEnd = isEmpty ? 0 : text.value.length - 1; } else { var selectionStart = isEmpty ? 2 : 1; var selectionEnd = 2; } try { text.setSelectionRange(selectionStart, selectionEnd); } catch(e){} inComposition = false; } function resetValue() { if (inComposition) return; text.value = PLACEHOLDER; if (useragent.isWebKit) syncValue.schedule(); } useragent.isWebKit || host.addEventListener('changeSelection', function() { if (host.selection.isEmpty() != isSelectionEmpty) { isSelectionEmpty = !isSelectionEmpty; syncSelection.schedule(); } }); resetValue(); if (isFocused) host.onFocus(); var isAllSelected = function(text) { return text.selectionStart === 0 && text.selectionEnd === text.value.length; }; var onSelect = function(e) { if (copied) { copied = false; } else if (isAllSelected(text)) { host.selectAll(); resetSelection(); } else if (inputHandler) { resetSelection(host.selection.isEmpty()); } }; var inputHandler = null; this.setInputHandler = function(cb) {inputHandler = cb;}; this.getInputHandler = function() {return inputHandler;}; var afterContextMenu = false; var sendText = function(data) { if (inputHandler) { data = inputHandler(data); inputHandler = null; } if (pasted) { resetSelection(); if (data) host.onPaste(data); pasted = false; } else if (data == PLACEHOLDER.charAt(0)) { if (afterContextMenu) host.execCommand("del", {source: "ace"}); else // some versions of android do not fire keydown when pressing backspace host.execCommand("backspace", {source: "ace"}); } else { if (data.substring(0, 2) == PLACEHOLDER) data = data.substr(2); else if (data.charAt(0) == PLACEHOLDER.charAt(0)) data = data.substr(1); else if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0)) data = data.slice(0, -1); if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0)) data = data.slice(0, -1); if (data) host.onTextInput(data); } if (afterContextMenu) afterContextMenu = false; }; var onInput = function(e) { if (inComposition) return; var data = text.value; sendText(data); resetValue(); }; 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)) { isCut ? host.onCut() : host.onCopy(); event.preventDefault(e); } else { copied = true; text.value = data; text.select(); setTimeout(function(){ copied = false; resetValue(); 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 (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)); event.addListener(text, "select", onSelect); event.addListener(text, "input", onInput); event.addListener(text, "cut", onCut); event.addListener(text, "copy", onCopy); event.addListener(text, "paste", onPaste); 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; } }); } var onCompositionStart = function(e) { if (inComposition || !host.onCompositionStart || host.$readOnly) return; inComposition = {}; inComposition.canUndo = host.session.$undoManager; host.onCompositionStart(); setTimeout(onCompositionUpdate, 0); host.on("mousedown", onCompositionEnd); if (inComposition.canUndo && !host.selection.isEmpty()) { host.insert(""); host.session.markUndoGroup(); host.selection.clearSelection(); } host.session.markUndoGroup(); }; var onCompositionUpdate = function() { if (!inComposition || !host.onCompositionUpdate || host.$readOnly) return; var val = text.value.replace(PLACEHOLDER_RE, ""); if (inComposition.lastValue === val) return; host.onCompositionUpdate(val); if (inComposition.lastValue) host.undo(); if (inComposition.canUndo) inComposition.lastValue = val; if (inComposition.lastValue) { var r = host.selection.getRange(); host.insert(inComposition.lastValue); host.session.markUndoGroup(); inComposition.range = host.selection.getRange(); host.selection.setRange(r); host.selection.clearSelection(); } }; var onCompositionEnd = function(e) { if (!host.onCompositionEnd || host.$readOnly) return; var c = inComposition; inComposition = false; var timer = setTimeout(function() { timer = null; var str = text.value.replace(PLACEHOLDER_RE, ""); if (inComposition) return; else if (str == c.lastValue) resetValue(); else if (!c.lastValue && str) { resetValue(); sendText(str); } }); inputHandler = function compositionInputHandler(str) { if (timer) clearTimeout(timer); str = str.replace(PLACEHOLDER_RE, ""); if (str == c.lastValue) return ""; if (c.lastValue && timer) host.undo(); return str; }; host.onCompositionEnd(); host.removeListener("mousedown", onCompositionEnd); if (e.type == "compositionend" && c.range) { host.selection.setRange(c.range); } var needsOnInput = useragent.isIE || (useragent.isChrome && useragent.isChrome >= 53) || (useragent.isWebKit && useragent.isWebKit >= 603); if (needsOnInput) { onInput(); } }; var syncComposition = lang.delayedCall(onCompositionUpdate, 50); event.addListener(text, "compositionstart", onCompositionStart); event.addListener(text, "compositionupdate", function(){syncComposition.schedule();}); event.addListener(text, "keyup", function(){syncComposition.schedule();}); event.addListener(text, "keydown", function(){syncComposition.schedule();}); event.addListener(text, "compositionend", onCompositionEnd); 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) { copyWithEmptySelection = value; }; this.onContextMenu = function(e) { afterContextMenu = true; resetSelection(host.selection.isEmpty()); 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;" : "") + "height:" + text.style.height + ";" + (useragent.isIE ? "opacity:0.1;" : ""); 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) { text.style.left = e.clientX - left - 2 + "px"; text.style.top = Math.min(e.clientY - top - 2, maxTop) + "px"; }; move(e); if (e.type != "mousedown") return; if (host.renderer.$keepTextAreaAtCursor) host.renderer.$keepTextAreaAtCursor = null; 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 = ''; } if (host.renderer.$keepTextAreaAtCursor == null) { host.renderer.$keepTextAreaAtCursor = true; host.renderer.$moveTextAreaToCursor(); } }, 0); } var onContextMenu = function(e) { host.textInput.onContextMenu(e); onContextMenuClose(); }; event.addListener(text, "mouseup", onContextMenu); event.addListener(text, "mousedown", function(e) { e.preventDefault(); onContextMenuClose(); }); event.addListener(host.renderer.scroller, "contextmenu", onContextMenu); event.addListener(text, "contextmenu", onContextMenu); }; exports.TextInput = TextInput; }); define("ace_tree/mouse/default_handlers",[], function(require, exports, module) { "use strict"; var dom = require("ace/lib/dom"); var DRAG_OFFSET = 5; // pixels 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("mouseleave", this.onMouseLeave.bind(mouseHandler)); editor.setDefaultHandler("mousemove", this.onMouseMove.bind(mouseHandler)); editor.setDefaultHandler("mousewheel", this.onMouseWheel.bind(mouseHandler)); editor.setDefaultHandler("mouseup", this.onMouseUp.bind(mouseHandler)); editor.setDefaultHandler("click", this.onClick.bind(mouseHandler)); var exports = ["dragMoveSelection", "dragWait", "dragWaitEnd", "getRegion", "updateHoverState"]; exports.forEach(function(x) { mouseHandler[x] = this[x]; }, this); } (function() { function isTogglerClick(target) { return dom.hasCssClass(target, "toggler") && !dom.hasCssClass(target, "empty"); } this.onMouseMove = function(e) { var editor = this.editor; var node = e.getNode(); var title, provider = editor.provider; if (!node) { title = ""; } else if (provider.columns) { var pos = e.getDocumentPosition(); var columnData = editor.renderer.$headingLayer.findColumn(pos.x); title = columnData ? columnData.column.getText(node) : ""; } else { title = provider.getTooltipText ? provider.getTooltipText(node) : provider.getText(node); } if (!editor.tooltip && editor.container.title != title) editor.container.title = title; this.updateHoverState(node); }; this.onMouseLeave = function() { this.updateHoverState(null); }; this.updateHoverState = function(node) { var provider = this.editor.provider; if (node !== this.node && provider) { if (this.node) provider.setClass(this.node, "hover", false); this.node = node; if (this.node) provider.setClass(this.node, "hover", true); } }; this.onMouseDown = function(ev) { var editor = this.editor; var provider = editor.provider; ev.detail = 1; this.mousedownEvent = ev; this.delayedSelect = false; this.isMousePressed = true; var button = ev.getButton(); var selectedNodes = editor.selection.getSelectedNodes(); var isMultiSelect = selectedNodes.length > 1; if (button !== 0 && isMultiSelect) { return; // stopping event here breaks contextmenu on ff mac } var node = ev.getNode(); this.$clickNode = node; if (!node) return; // Click outside cells var inSelection = provider.isSelected(node); var target = ev.domEvent.target; this.region = null; if (isTogglerClick(target) || node.clickAction == "toggle") { this.region = "toggler"; var toggleChildren = ev.getShiftKey(); var deep = ev.getAccelKey(); if (button === 0) { if (toggleChildren) { if (deep) { node = node.parent; } provider.close(node, true); provider.open(node); } else { provider.toggleNode(node, deep); } } this.$clickNode = null; } else if (dom.hasCssClass(target, "checkbox")) { var nodes = inSelection && editor.selection.getSelectedNodes(); provider._signal("toggleCheckbox", { target: node, selectedNodes: nodes }); node.isChecked = !node.isChecked; if (nodes) { nodes.forEach(function(n) { n.isChecked = node.isChecked }); } provider._signal(node.isChecked ? "check" : "uncheck", nodes || [node]); provider._signal("change"); } else if (dom.hasCssClass(target, "icon-ok")) { if (ev.getShiftKey()) { editor.selection.expandSelection(node, null, true); } else { editor.selection.toggleSelect(node); } } else if (ev.getAccelKey()) { if (inSelection && isMultiSelect) this.delayedSelect = "toggle"; else if (!inSelection || isMultiSelect) editor.selection.toggleSelect(node); } else if (ev.getShiftKey()) { editor.selection.expandSelection(node); } else if (inSelection && isMultiSelect) { if (!editor.isFocused()) this.$clickNode = null; else this.delayedSelect = true; } else { editor.selection.setSelection(node); } if (this.$clickNode) editor.$mouseHandler.captureMouse(ev, "dragWait"); return ev.preventDefault(); }; this.onMouseUp = function(ev) { if (this.isMousePressed == 2) return; // wait until release capture this.isMousePressed = false; var pos = ev.getDocumentPosition(); var node = this.editor.provider.findItemAtOffset(pos.y); if (node && this.$clickNode && this.$clickNode == node) { ev.button = ev.getButton(); ev.target = ev.domEvent.target; ev.detail = this.mousedownEvent.detail; this.onMouseEvent("click", ev); } this.$clickNode = this.mouseEvent = null; }; this.onClick = function(ev) { if (this.mousedownEvent.detail === 2) { this.editor._emit("afterChoose"); } }; this.onDoubleClick = function(ev) { var provider = this.editor.provider; if (provider.toggleNode && !isTogglerClick(ev.domEvent.target)) { var node = ev.getNode(); if (node) provider.toggleNode(node); } if (this.mousedownEvent) this.mousedownEvent.detail = 2; }; this.dragMoveSelection = function() { var editor = this.editor; var ev = this.mouseEvent; ev.$pos = ev.node = null; var node = ev.getNode(true); if (node != editor.selection.getCursor() && node) { if (ev.getShiftKey()) { editor.selection.expandSelection(node, null, true); } else { editor.selection.selectNode(node); } editor.renderer.scrollCaretIntoView(); } }; this.dragWait = function() { var ev = this.mousedownEvent; if (Math.abs(this.x - ev.x) + Math.abs(this.y - ev.y) > DRAG_OFFSET) { this.delayedSelect = false; this.editor._emit("startDrag", ev); if (this.state == "dragWait" && ev.getButton() === 0) this.setState("dragMoveSelection"); } }; this.dragWaitEnd = function() { if (this.delayedSelect) { var selection = this.editor.selection; if (this.$clickNode) { if (this.delayedSelect == "toggle") selection.toggleSelect(this.$clickNode); else selection.setSelection(this.$clickNode); } this.delayedSelect = false; } }; this.onMouseWheel = function(ev) { if (ev.getShiftKey() || ev.getAccelKey()) return; var t = ev.domEvent.timeStamp; var dt = t - (this.$lastScrollTime || 0); var editor = this.editor; var isScrolable = editor.renderer.isScrollableBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed); if (isScrolable || dt < 200) { this.$lastScrollTime = t; editor.renderer.scrollBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed); return ev.stop(); } }; }).call(DefaultHandlers.prototype); exports.DefaultHandlers = DefaultHandlers; }); define("ace_tree/mouse/mouse_event",[], function(require, exports, module) { "use strict"; var event = require("ace/lib/event"); var useragent = require("ace/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 node = this.getNode(); this.$inSelection = !!(node && node.isSelected); return this.$inSelection; }; this.node = null; this.getNode = function(clip) { if (this.node) return this.node; var pos = this.getDocumentPosition(clip); if (!pos || !this.editor.provider) return; // Click outside cells return this.node = this.editor.provider.findItemAtOffset(pos.y, clip); }; 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); }); define("ace_tree/mouse/drag_handler",[], function(require, exports, module) { "use strict"; var event = require("ace/lib/event"); var useragent = require("ace/lib/useragent"); var DefaultHandlers = require("./default_handlers").DefaultHandlers; var MouseEvent = require("./mouse_event").MouseEvent; var config = require("../config"); var dom = require("ace/lib/dom"); function initDragHandlers(mouseHandler) { var tree = mouseHandler.editor; var UNFOLD_TIMEOUT = 500; var WIDGET_UNFOLD_TIMEOUT = 500; var AUTOSCROLL_DELAY = 300; var MIN_DRAG_T = 500; var dragInfo, x, y, dx, dy; var scrollerRect; mouseHandler.drag = function() { var ev = this.mouseEvent; if (!dragInfo || !ev) return; var node = ev.getNode(); dx = ev.x - x; dy = ev.y - y; x = ev.x; y = ev.y; var isInTree = isInRect(x, y, scrollerRect); if (!isInTree) { node = null; } if (dragInfo.isInTree != isInTree && dragInfo.selectedNodes) { dragInfo.isInTree = isInTree; ev.dragInfo = dragInfo; tree._signal(isInTree ? "dragIn" : "dragOut" , ev); } if (!isInTree) { ev.dragInfo = dragInfo; tree._signal("dragMoveOutside", ev); } if (dragInfo.el) { dragInfo.el.style.top = ev.y - dragInfo.offsetY + "px"; dragInfo.el.style.left = ev.x - dragInfo.offsetX + "px"; } var hoverNode = node; if (hoverNode) { var xOffset = x - scrollerRect.left; var depth = Math.max(0, Math.floor(xOffset / tree.provider.$indentSize)); var depthDiff = hoverNode.$depth - depth; while (depthDiff > 0 && hoverNode.parent) { depthDiff--; hoverNode = hoverNode.parent; } if (!hoverNode.isFolder && dragInfo.mode != "sort") { hoverNode = hoverNode.parent; } } if (dragInfo.hoverNode !== hoverNode) { if (dragInfo.hoverNode) { tree.provider.setClass(dragInfo.hoverNode, "dropTarget", false); tree._signal("folderDragLeave", dragInfo); } if (hoverNode && dragInfo.selectedNodes && dragInfo.selectedNodes.indexOf(hoverNode) != -1) { hoverNode = null; } dragInfo.hoverNode = hoverNode; if (dragInfo.hoverNode) { tree._signal("folderDragEnter", dragInfo); if (dragInfo.mode !== "sort") tree.provider.setClass(dragInfo.hoverNode, "dropTarget", true); } highlightFolder(tree, dragInfo.hoverNode, dragInfo.insertPos); } var now = Date.now(); var target = ev.domEvent.target; var isFoldWidget = target && (dom.hasCssClass(target, "toggler") && !dom.hasCssClass(target, "empty")); var distance = Math.abs(dx) + Math.abs(dy); var pos = ev.y - scrollerRect.top; var rowHeight = tree.provider.rowHeight; var renderer = tree.renderer; var autoScrollMargin = 1.5 * rowHeight; var scroll = pos - autoScrollMargin; if (scroll > 0) { scroll += -renderer.$size.scrollerHeight + 2 * autoScrollMargin; if (scroll < 0) scroll = 0; } if (!scroll || !isInTree) dragInfo.autoScroll = false; if (distance <= 2) { if (!dragInfo.stopTime) dragInfo.stopTime = now; } else { if (!isFoldWidget) dragInfo.stopTime = undefined; } var dt = now - dragInfo.stopTime; if (scroll && isInTree) { if (dt > AUTOSCROLL_DELAY || dragInfo.autoScroll) { tree.renderer.scrollBy(0, scroll / 2); dragInfo.autoScroll = true; } } else if (node && dragInfo.mode === "move") { if (node.parent === tree.provider.root || node.isRoot || node.parent && node.parent.isRoot) isFoldWidget = false; if (isFoldWidget && dt > WIDGET_UNFOLD_TIMEOUT && dt < 2 * WIDGET_UNFOLD_TIMEOUT) { tree.provider.toggleNode(node); dragInfo.stopTime = Infinity; } else if (!isFoldWidget && dt > UNFOLD_TIMEOUT && dt < 2 * UNFOLD_TIMEOUT) { tree.provider.open(node); dragInfo.stopTime = Infinity; } } }; mouseHandler.dragEnd = function(e, cancel) { if (dragInfo) { window.removeEventListener("mousedown", keyHandler, true); window.removeEventListener("keydown", keyHandler, true); window.removeEventListener("keyup", keyHandler, true); if (dragInfo.el && dragInfo.el.parentNode) dragInfo.el.parentNode.removeChild(dragInfo.el); if (dragInfo.hoverNode) { tree.provider.setClass(dragInfo.hoverNode, "dropTarget", false); tree._signal("folderDragLeave", dragInfo); } highlightFolder(tree, null); if (tree.isFocused()) tree.renderer.visualizeFocus(); tree.renderer.setStyle("dragOver", false); dragInfo.target = dragInfo.hoverNode; if (!cancel && dragInfo.selectedNodes && Date.now() - dragInfo.startT > MIN_DRAG_T) tree._emit("drop", dragInfo); if (!dragInfo.isInTree) { if (cancel) dragInfo.selectedNodes = null; tree._signal("dropOutside" , {dragInfo: dragInfo}); } dragInfo = null; } }; mouseHandler.dragStart = function() { if (dragInfo) this.dragEnd(null, true); mouseHandler.setState("drag"); tree.renderer.visualizeBlur(); tree.renderer.setStyle("dragOver", true); scrollerRect = tree.renderer.scroller.getBoundingClientRect(); dragInfo = {}; }; tree.on("startDrag", function(ev) { if (!tree.getOption("enableDragDrop")) return; var node = ev.getNode(); if (!node || ev.getButton()) return; mouseHandler.dragStart(); window.addEventListener("mousedown", keyHandler, true); window.addEventListener("keydown", keyHandler, true); window.addEventListener("keyup", keyHandler, true); var selectedNodes = tree.selection.getSelectedNodes(); var el = constructDragNode(node); dragInfo = { el: el, node: node, selectedNodes: selectedNodes, offsetX: 10, offsetY: 10, target: node, startT: Date.now(), isInTree: true, mode: "move" }; ev.dragInfo = dragInfo; tree._signal("dragStarted", ev); if (mouseHandler.state == "drag") mouseHandler.drag(); }); function constructDragNode(node) { var i = tree.provider.getIndexForNode(node); var domNode = tree.renderer.$cellLayer.getDomNodeAtIndex(i); if (!domNode) return; var offset = domNode.offsetHeight; var selectedNodes = tree.selection.getSelectedNodes(); var el = document.createElement("div"); el.className = tree.container.className + " dragImage"; var ch = el.appendChild(domNode.cloneNode(true)); ch.removeChild(ch.firstChild); ch.style.paddingRight = "5px"; ch.style.opacity = "0.8"; el.style.position = "absolute"; el.style.zIndex = "1000000"; el.style.pointerEvents = "none"; el.style.overflow = "visible"; if (selectedNodes.length > 1) { ch.style.color = "transparent"; ch = el.appendChild(domNode.cloneNode(true)); ch.removeChild(ch.firstChild); ch.style.paddingRight = "5px"; ch.style.top = - offset + 2 + "px"; ch.style.left = "2px"; ch.style.position = "relative"; ch.style.opacity = "0.8"; } document.body.appendChild(el); return el; } function keyHandler(e){ if (dragInfo) { if (e.keyCode === 27 || e.type == "mousedown") { mouseHandler.dragEnd(null, true); event.stopEvent(e); } else if (dragInfo && e.keyCode == 17 || e.keyCode == 18) { dragInfo.isCopy = e.type == "keydown"; dom.setCssClass(dragInfo.el, "copy", dragInfo.isCopy); } } } } function highlightFolder(tree, node, type) { tree.provider.markedFolder = node; tree.provider.markedFolderType = type; tree.renderer.$loop.schedule(tree.renderer.CHANGE_MARKER); } function isInRect(x, y, rect) { if (x < rect.right && x > rect.left && y > rect.top && y < rect.bottom) return true; } module.exports = initDragHandlers; }); define("ace_tree/mouse/heading_handler",[], function(require, exports, module) { "use strict"; var event = require("ace/lib/event"); function HeadingHandler(mouseHandler) { var editor = mouseHandler.editor; var headingLayer = editor.renderer.$headingLayer; event.addListener(headingLayer.element, "mousedown", mouseHandler.onMouseEvent.bind(mouseHandler, "headerMouseDown")); event.addListener(headingLayer.element, "mousemove", mouseHandler.onMouseEvent.bind(mouseHandler, "headerMouseMove")); var overResizer, dragStartPos, columnData; editor.setDefaultHandler("headerMouseMove", function(e) { if (dragStartPos || !editor.provider || !editor.provider.columns) return; var pos = e.getDocumentPosition(); var width = editor.renderer.$size.scrollerWidth; if (width != editor.provider.columns.width) headingLayer.updateWidth(width); columnData = headingLayer.findColumn(pos.x); overResizer = columnData && columnData.overResizer; headingLayer.element.style.cursor = overResizer ? "ew-resize" : "default"; }); editor.setDefaultHandler("headerMouseDown", function(e) { if (overResizer) { var pos = e.getDocumentPosition(); dragStartPos = {x: pos.x}; mouseHandler.setState("headerResize"); mouseHandler.captureMouse(e); mouseHandler.mouseEvent = e; } e.stop(); }); mouseHandler.headerResize = function() { if (this.mouseEvent && dragStartPos) { var pos = this.mouseEvent.getDocumentPosition(); var dx = pos.x // - dragStartPos.x; var columns = editor.renderer.provider.columns; for (var i = 0; i < columns.length; i++) { var col = columns[i]; dx -= col.pixelWidth; if (col === columnData.column) break; } var total = editor.renderer.$size.scrollerWidth; headingLayer.changeColumnWidth(columnData.column, dx, total); var renderer = editor.renderer; renderer.updateFull(); } }; mouseHandler.headerResizeEnd = function() { dragStartPos = null; headingLayer.element.style.cursor = ""; overResizer = false; }; } exports.HeadingHandler = HeadingHandler; }); define("ace_tree/mouse/mouse_handler",[], function(require, exports, module) { "use strict"; var event = require("ace/lib/event"); var useragent = require("ace/lib/useragent"); var DefaultHandlers = require("./default_handlers").DefaultHandlers; var initDragHandlers = require("./drag_handler"); var HeadingHandler = require("./heading_handler").HeadingHandler; var MouseEvent = require("./mouse_event").MouseEvent; var config = require("../config"); var MouseHandler = function(editor) { this.editor = editor; new DefaultHandlers(this); new HeadingHandler(this); initDragHandlers(this); var mouseTarget = editor.renderer.getMouseEventTarget(); event.addListener(mouseTarget, "mousedown", function(e) { editor.focus(true); return event.preventDefault(e); }); event.addListener(mouseTarget, "mousemove", this.onMouseEvent.bind(this, "mousemove")); event.addListener(mouseTarget, "mouseup", this.onMouseEvent.bind(this, "mouseup")); event.addMultiMouseDownListener(mouseTarget, [300, 300, 250], this, "onMouseEvent"); event.addMultiMouseDownListener(editor.renderer.scrollBarV.inner, [300, 300, 250], this, "onMouseEvent"); event.addMultiMouseDownListener(editor.renderer.scrollBarH.inner, [300, 300, 250], this, "onMouseEvent"); event.addMouseWheelListener(editor.container, this.onMouseWheel.bind(this, "mousewheel")); event.addListener(mouseTarget, "mouseout", this.onMouseEvent.bind(this, "mouseleave")); }; (function() { this.onMouseEvent = function(name, e) { 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, state) { if (state) this.setState(state); this.x = ev.x; this.y = ev.y; this.isMousePressed = 2; var renderer = this.editor.renderer; if (renderer.$keepTextAreaAtCursor) renderer.$keepTextAreaAtCursor = null; var self = this; var onMouseMove = function(e) { self.x = e.clientX; self.y = e.clientY; self.mouseEvent = new MouseEvent(e, self.editor); self.$mouseMoved = true; }; var onCaptureEnd = function(e) { clearInterval(timerId); onCaptureInterval(); self[self.state + "End"] && self[self.state + "End"](e); self.$clickSelection = null; if (renderer.$keepTextAreaAtCursor == null) { renderer.$keepTextAreaAtCursor = true; renderer.$moveTextAreaToCursor(); } self.isMousePressed = false; e && self.onMouseEvent("mouseup", e); self.$onCaptureMouseMove = self.releaseMouse = null; }; var onCaptureInterval = function() { self[self.state] && self[self.state](); self.$mouseMoved = false; }; if (useragent.isOldIE && ev.domEvent.type == "dblclick") { return setTimeout(function() {onCaptureEnd(ev.domEvent);}); } self.$onCaptureMouseMove = onMouseMove; self.releaseMouse = event.capture(this.editor.container, onMouseMove, onCaptureEnd); var timerId = setInterval(onCaptureInterval, 20); }; this.releaseMouse = null; }).call(MouseHandler.prototype); config.defineOptions(MouseHandler.prototype, "mouseHandler", { scrollSpeed: {initialValue: 2}, dragDelay: {initialValue: 150}, focusTimeout: {initialValue: 0}, enableDragDrop: {initialValue: false} }); exports.MouseHandler = MouseHandler; }); define("ace/keyboard/keybinding",[], 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); this.$callKeyboardHandlers(hashId, keyString, keyCode, e); }; this.onTextInput = function(text) { this.$callKeyboardHandlers(-1, text); }; }).call(KeyBinding.prototype); exports.KeyBinding = KeyBinding; }); define("ace_tree/selection",[], function(require, exports, module) { "use strict"; var oop = require("ace/lib/oop"); var EventEmitter = require("ace/lib/event_emitter").EventEmitter; var Selection = function(provider) { this.provider = provider; if (this.provider && !this.provider.selectedItems) this.provider.selectedItems = []; this.provider.on("remove", this.unselectRemoved = this.unselectRemoved.bind(this)); }; (function() { oop.implement(this, EventEmitter); this.$wrapAround = false; this.getRange = function() {}; this.selectAll = function() { var sel = this.provider.selectedItems; this.expandSelection(sel[0], sel[sel.length -1]); this._signal("change"); }; this.moveSelection = function(dir, select, add) { var provider = this.provider; var cursor = this.getCursor(); var anchor = this.getAnchor(); var i = provider.getIndexForNode(cursor); if (!add) { this.clear(true); } else if (add && !select) { this.unselectNode(cursor); } var min = provider.getMinIndex(); var max = provider.getMaxIndex(); var wrapped = false; var newI = i; do { newI += dir; if (newI < min) { newI = this.$wrapAround ? max : min; wrapped = true; } else if (newI > max) { newI = this.$wrapAround ? min : max; wrapped = true; } var newNode = provider.getNodeAtIndex(newI); } while (!wrapped && newNode && !provider.isSelectable(newNode)); if (!newNode || !provider.isSelectable(newNode)) newNode = cursor; if (select) { this.expandSelection(newNode, anchor, add); } else { this.selectNode(newNode, add); } }; this.getCursor = function() { var sel = this.provider.selectedItems; return sel.cursor || sel[sel.length - 1]; }; this.getAnchor = function() { var sel = this.provider.selectedItems; return sel.anchor || sel.cursor || sel[0]; }; this.getSelectedNodes = function() { var sel = this.provider.selectedItems; return sel.slice(); }; this.getVisibleSelectedNodes = function() { var provider = this.provider; var sel = provider.selectedItems; return sel.filter(function(node) { return provider.isVisible(node); }); }; this.isEmpty = function() { var sel = this.provider.selectedItems; return sel.length === 0; }; this.isMultiRow = function() { var sel = this.provider.selectedItems; return sel.length > 1; }; this.toggleSelect = function(node) { var provider = this.provider; var sel = provider.selectedItems; var i = sel.indexOf(node); if (i != -1) sel.splice(i, 1); provider.setSelected(node, !provider.isSelected(node)); if (provider.isSelected(node)) { sel.push(node); sel.anchor = sel.cursor = node; } else sel.anchor = sel.cursor = sel[sel.length - 1]; this._signal("change"); }; this.selectNode = function(node, add, silent) { var provider = this.provider; var sel = provider.selectedItems; if (!provider.isSelectable(node)) return; if (!add) this.clear(true); if (node) { var i = sel.indexOf(node); if (i != -1) sel.splice(i, 1); provider.setSelected(node, true); if (provider.isSelected(node)) sel.push(node); } sel.anchor = sel.cursor = node; this._signal("change"); }; this.add = function(node) { this.selectNode(node, true); }; this.remove = function(node) { if (this.provider.isSelected(node)) this.toggleSelect(node); }; this.clear = this.clearSelection = function(silent) { var provider = this.provider; var sel = provider.selectedItems; sel.forEach(function(node) { provider.setSelected(node, false); }); sel.splice(0, sel.length); sel.anchor = sel.cursor; silent || this._signal("change"); }; this.unselectNode = function(node, silent) { var provider = this.provider; var sel = provider.selectedItems; var i = sel.indexOf(node); if (i != -1) { sel.splice(i, 1); provider.setSelected(node, false); if (sel.anchor == node) sel.anchor = sel[i-1] || sel[i]; if (sel.cursor == node) sel.cursor = sel[i] || sel[i-1]; silent || this._signal("change"); } }; this.setSelection = function(nodes) { if (Array.isArray(nodes)) { this.clear(true); nodes.forEach(function(node) { this.selectNode(node, true, true); }, this); } else this.selectNode(nodes, false, true); }; this.expandSelection = function(cursor, anchor, additive) { anchor = anchor || this.getAnchor(); if (!additive) this.clear(true); var provider = this.provider; var sel = provider.selectedItems; var end = provider.getIndexForNode(cursor); var start = provider.getIndexForNode(anchor || cursor); if (end > start) { for (var i = start; i <= end; i++) { var node = provider.getNodeAtIndex(i); var index = sel.indexOf(node); if (index != -1) sel.splice(index, 1); if (provider.isSelectable(node)) provider.setSelected(node, true); sel.push(node); } } else { for (var i = start; i >= end; i--) { var node = provider.getNodeAtIndex(i); var index = sel.indexOf(node); if (index != -1) sel.splice(index, 1); if (provider.isSelectable(node)) provider.setSelected(node, true); sel.push(node); } } sel.cursor = cursor; sel.anchor = anchor; this._signal("change"); }; this.unselectRemoved = function(toRemove) { var sel = this.getSelectedNodes(); var provider = this.provider; var changed, cursor = this.getCursor(); sel.forEach(function(n) { if (provider.isAncestor(toRemove, n)) { changed = true; this.unselectNode(n, true); } }, this); if (changed && !provider.isSelected(cursor)) { var parent = toRemove.parent; var ch = []; if (parent && provider.isOpen(parent)) { ch = provider.getChildren(parent); var i = ch.indexOf(toRemove); } if (i == -1) { i = toRemove.index; var node = ch[i] || ch[i - 1] || parent; } else { node = ch[i + 1] || ch[i - 1] || parent; } if (node == provider.root) node = ch[0] || node; if (node) this.selectNode(node, true); this._signal("change"); } }; }).call(Selection.prototype); exports.Selection = Selection; }); define("ace/keyboard/hash_handler",[], 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; }); define("ace/commands/command_manager",[], 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.removeEventListener("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; }); define("ace_tree/commands/default_commands",[], function(require, exports, module) { "use strict"; function bindKey(win, mac) { return {win: win, mac: mac}; } exports.commands = [{ name: "selectAll", bindKey: bindKey("Ctrl-A", "Command-A"), exec: function(editor) { editor.selectAll(); } }, { name: "centerselection", bindKey: bindKey(null, "Ctrl-L"), exec: function(editor) { editor.centerSelection(); } }, { name: "closeOrlevelUp", bindKey: bindKey("Left", "Left|Ctrl-B"), exec: function(editor) { editor.navigateLevelUp(true); } }, , { name: "levelUp", bindKey: bindKey("Shift-Left", "Shift-Left|Ctrl-B"), exec: function(editor) { editor.navigateLevelUp(); } }, { name: "levelDown", bindKey: bindKey("Right", "Right|Ctrl-F"), exec: function(editor) { editor.navigateLevelDown(); } }, { name: "goToStart", editorKey: bindKey("Ctrl-Home", "Ctrl-Home"), bindKey: bindKey("Home|Ctrl-Home", "Home|Ctrl-Home"), exec: function(editor) { editor.navigateStart(); } }, { name: "goToEnd", editorKey: bindKey("Ctrl-End", "Ctrl-End"), bindKey: bindKey("End|Ctrl-End", "End|Ctrl-End"), exec: function(editor) { editor.navigateEnd(); } }, { name: "closeAllFromSelected", bindKey: bindKey("Ctrl-Left", "Ctrl-Left"), exec: function(ed) { ed.provider.close(ed.selection.getCursor(), true); } }, { name: "openAllFromSelected", bindKey: bindKey("Ctrl-Right", "Ctrl-Right"), exec: function(ed) { ed.provider.open(ed.selection.getCursor(), true); } }, { name: "pageup", bindKey: "Option-PageUp", exec: function(editor) { editor.scrollPageUp(); } }, { name: "gotopageup", bindKey: "PageUp", exec: function(editor) { editor.gotoPageUp(); } }, { name: "pagedown", bindKey: "Option-PageDown", exec: function(editor) { editor.scrollPageDown(); } }, { name: "gotopageDown", bindKey: "PageDown", exec: function(editor) { editor.gotoPageDown(); } }, { name: "scrollup", bindKey: bindKey("Ctrl-Up", null), exec: function(e) { e.renderer.scrollBy(0, -2 * e.renderer.layerConfig.lineHeight); } }, { name: "scrolldown", bindKey: bindKey("Ctrl-Down", null), exec: function(e) { e.renderer.scrollBy(0, 2 * e.renderer.layerConfig.lineHeight); } }, { name: "insertstring", exec: function(e, args) { e.insertSting(args) } }, { name: "goUp", bindKey: bindKey("Up", "Up|Ctrl-P"), exec: function(editor) { editor.selection.moveSelection(-1); } }, { name: "goDown", bindKey: bindKey("Down", "Down|Ctrl-N"), exec: function(editor) { editor.selection.moveSelection(1); } }, { name: "selectUp", bindKey: bindKey("Shift-Up", "Shift-Up"), exec: function(editor) { editor.selection.moveSelection(-1, true); } }, { name: "selectDown", bindKey: bindKey("Shift-Down", "Shift-Down"), exec: function(editor) { editor.selection.moveSelection(1, true); } }, { name: "selectToUp", bindKey: bindKey("Ctrl-Up", "Ctrl-Up"), exec: function(editor) { editor.selection.moveSelection(-1, false, true); } }, { name: "selectToDown", bindKey: bindKey("Ctrl-Down", "Ctrl-Down"), exec: function(editor) { editor.selection.moveSelection(1, false, true); } }, { name: "selectMoreUp", bindKey: bindKey("Ctrl-Shift-Up", "Ctrl-Shift-Up"), exec: function(editor) { editor.selection.moveSelection(-1, true, true); } }, { name: "selectMoreDown", bindKey: bindKey("Ctrl-Shift-Down", "Ctrl-Shift-Down"), exec: function(editor) { editor.selection.moveSelection(1, true, true); } }, { name: "rename", bindKey: "F2", exec: function(tree) { tree.edit && tree.edit.startRename(); } }, { name: "chose", bindKey: "Enter", exec: function(tree) { tree._emit("afterChoose"); } }, { name: "delete", bindKey: "Delete", exec: function(tree) { tree._emit("delete"); } }, { name: "foldOther", bindKey: bindKey("Alt-0", "Command-Option-0"), exec: function(tree) { tree.provider.close(tree.provider.root, true); tree.reveal(tree.selection.getCursor()); } } ]; }); define("ace_tree/quicksearch",[], function(require, exports, module) { "use strict"; var quickSearch = function(tree, str) { var node = tree.selection.getCursor() var siblings = tree.provider.getChildren(node.parent); if (!siblings || siblings.length == 1) { return; } var index = siblings.indexOf(node); var newNode for (var i = index + 1; i < siblings.length; i++) { node = siblings[i]; var label = node.label || node.name || ""; if (label[0] == str) { newNode = node; break; } } if (!newNode) { for (var i = 0; i < index; i++) { node = siblings[i]; var label = node.label || node.name || ""; if (label[0] == str) { newNode = node; break; } } } if (newNode) { tree.selection.selectNode(newNode); tree.renderer.scrollCaretIntoView(newNode, 0.5); } }; module.exports = quickSearch; }); define("ace_tree/tree",[], function(require, exports, module) { "use strict"; var Renderer = require("./virtual_renderer").VirtualRenderer; exports.config = require("./config"); var oop = require("ace/lib/oop"); var lang = require("ace/lib/lang"); var useragent = require("ace/lib/useragent"); var TextInput = require("ace/keyboard/textinput").TextInput; var MouseHandler = require("./mouse/mouse_handler").MouseHandler; var KeyBinding = require("ace/keyboard/keybinding").KeyBinding; var Selection = require("./selection").Selection; var EventEmitter = require("ace/lib/event_emitter").EventEmitter; var CommandManager = require("ace/commands/command_manager").CommandManager; var defaultCommands = require("./commands/default_commands").commands; var config = require("./config"); var quickSearch = require("./quicksearch"); var Tree = function(element, cellWidth, cellHeight) { this.cellWidth = cellWidth || 80; this.cellHeight = cellHeight || 24; this.renderer = new Renderer(element, this.cellWidth, this.cellHeight); this.container = this.renderer.container; this.commands = new CommandManager(useragent.isMac ? "mac" : "win", defaultCommands); this.textInput = new TextInput(this.container, this); this.keyBinding = new KeyBinding(this); this.$mouseHandler = new MouseHandler(this); this.$blockScrolling = 0; var _self = this; this.renderer.on("edit", function(e){ _self._emit("edit", e); }); this.commands.on("exec", function() { this.selectionChanged = false; }.bind(this)); this.commands.on("afterExec", function() { if (this.selectionChanged) { this.selectionChanged = false; this.renderer.scrollCaretIntoView(); this._signal("userSelect"); } }.bind(this)); this.on("changeSelection", function() { if (this.$mouseHandler.isMousePressed) this._signal("userSelect"); }.bind(this)); config.resetOptions(this); config._emit("Tree", this); }; (function(){ oop.implement(this, EventEmitter); this.setDataProvider = function(provider) { if (this.provider) { var oldProvider = this.provider; this.selection.off("changeCaret", this.$onCaretChange); this.selection.off("change", this.$onSelectionChange); oldProvider.off("changeClass", this.$onChangeClass); oldProvider.off("expand", this.$redraw); oldProvider.off("collapse", this.$redraw); oldProvider.off("change", this.$redraw); oldProvider.off("changeScrollTop", this.$onScrollTopChange); oldProvider.off("changeScrollLeft", this.$onScrollLeftChange); } this.provider = provider; this.model = provider; // TODO remove provider in favor of model if (provider) { this.renderer.setDataProvider(provider); if (!this.$redraw) this.$redraw = this.redraw.bind(this); this.provider.on("expand", this.$redraw); this.provider.on("collapse", this.$redraw); this.provider.on("change", this.$redraw); if (!this.provider.selection) { this.provider.selection = new Selection(this.provider); } this.selection = this.provider.selection; this.$onCaretChange = this.onCaretChange.bind(this); this.selection.on("changeCaret", this.$onCaretChange); this.$onChangeClass = this.$onChangeClass.bind(this); this.provider.on("changeClass", this.$onChangeClass); this.$onSelectionChange = this.onSelectionChange.bind(this); this.selection.on("change", this.$onSelectionChange); this.$onScrollTopChange = this.onScrollTopChange.bind(this); this.provider.on("changeScrollTop", this.$onScrollTopChange); this.$onScrollLeftChange = this.onScrollLeftChange.bind(this); this.provider.on("changeScrollLeft", this.$onScrollLeftChange); this.$blockScrolling += 1; this.onCaretChange(); this.$blockScrolling -= 1; this.onScrollTopChange(); this.onScrollLeftChange(); this.onSelectionChange(); this.renderer.updateFull(); } this._emit("changeDataProvider", { provider: provider, oldProvider: oldProvider }); }; this.redraw = function() { this.renderer.updateFull(); }; this.getLength = function(){ return 0; // this.renderer.$treeLayer.length; }; this.getLine = function(row){ return { length : 0 // this.renderer.$horHeadingLayer.length - 1 }; }; this.getDataProvider = function() { return this.provider; }; this.getSelection = function() { return this.selection; }; this.resize = function(force) { this.renderer.onResize(force); }; this.focus = function(once) { var _self = this; once || setTimeout(function() { _self.textInput.focus(); }); this.textInput.focus(); }; this.isFocused = function() { return this.textInput.isFocused(); }; this.blur = function() { this.textInput.blur(); }; this.onFocus = function() { if (this.$isFocused) return; this.$isFocused = true; this.renderer.visualizeFocus(); this._emit("focus"); }; this.onBlur = function() { if (!this.$isFocused) return; this.$isFocused = false; this.renderer.visualizeBlur(); this._emit("blur"); }; this.onScrollTopChange = function() { this.renderer.scrollToY(this.provider.getScrollTop()); }; this.onScrollLeftChange = function() { this.renderer.scrollToX(this.renderer.getScrollLeft()); }; this.$onChangeClass = function() { this.renderer.updateCaret(); }; this.onCaretChange = function() { this.$onChangeClass(); if (!this.$blockScrolling) this.selectionChanged = true; this._emit("changeSelection"); }; this.onSelectionChange = function(e) { this.onCaretChange(); }; this.execCommand = function(command, args) { this.commands.exec(command, this, args); }; this.onTextInput = function(text) { this.keyBinding.onTextInput(text); }; this.onCommandKey = function(e, hashId, keyCode) { this.keyBinding.onCommandKey(e, hashId, keyCode); }; this.insertSting = function(str) { if (this.startFilter) return this.startFilter(str); quickSearch(this, str); }; this.setTheme = function(theme) { this.renderer.setTheme(theme); }; this.$getSelectedRows = function() { var range = this.getSelectionRange().collapseRows(); return { first: range.start.row, last: range.end.row }; }; this.getVisibleNodes = function(tolerance) { return this.renderer.getVisibleNodes(tolerance); }; this.isNodeVisible = function(node, tolerance) { return this.renderer.isNodeVisible(node, tolerance); }; this.$moveByPage = function(dir, select) { var renderer = this.renderer; var config = this.renderer.layerConfig; config.lineHeight = this.provider.rowHeight; var rows = dir * Math.floor(config.height / config.lineHeight); this.$blockScrolling++; this.selection.moveSelection(rows, select); this.$blockScrolling--; var scrollTop = renderer.scrollTop; renderer.scrollBy(0, rows * config.lineHeight); if (select != null) renderer.scrollCaretIntoView(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, center, animate, callback) { this.renderer.scrollToRow(row, 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.alignCaret(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.$blockScrolling += 1; this.selection.selectAll(); this.$blockScrolling -= 1; }; this.clearSelection = function() { this.selection.clearSelection(); }; this.moveCaretTo = function(row, column) { this.selection.moveCaretTo(row, column); }; this.moveCaretToPosition = function(pos) { this.selection.moveCaretToPosition(pos); }; this.gotoRow = function(rowNumber, column, animate) { this.selection.clearSelection(); if (column === undefined) column = this.selection.getCursor().column; this.$blockScrolling += 1; this.moveCaretTo(rowNumber - 1, column || 0); this.$blockScrolling -= 1; if (!this.isRowFullyVisible(rowNumber - 1)) this.scrollToRow(rowNumber - 1, true, animate); }; this.navigateTo = function(row, column) { this.clearSelection(); this.moveCaretTo(row, column); }; this.navigateUp = function() { var node = this.provider.navigate("up"); node && this.selection.setSelection(node); this.$scrollIntoView(); }; this.navigateDown = function() { var node = this.provider.navigate("down"); node && this.selection.setSelection(node); }; this.navigateLevelUp = function(toggleNode) { var node = this.selection.getCursor(); if (!node) { } else if (toggleNode && this.provider.isOpen(node)) { this.provider.close(node); } else { this.selection.setSelection(node.parent); } }; this.navigateLevelDown = function() { var node = this.selection.getCursor(); var hasChildren = this.provider.hasChildren(node); if (!hasChildren || this.provider.isOpen(node)) return this.selection.moveSelection(1); this.provider.open(node); }; this.navigateStart = function() { var node = this.getFirstNode(); this.selection.setSelection(node); }; this.navigateEnd = function() { var node = this.getLastNode(); this.selection.setSelection(node); }; this.getFirstNode = function() { var index = this.provider.getMinIndex(); return this.provider.getNodeAtIndex(index); }; this.getLastNode = function() { var index = this.provider.getMaxIndex(); return this.provider.getNodeAtIndex(index); }; this.$scrollIntoView = function(node) { this.renderer.scrollCaretIntoView(); }; this.select = function(node) { this.selection.setSelection(node); }; this.getCopyText = function(node) { return ""; }; this.onPaste = function(node) { return ""; }; this.reveal = function(node, animate) { var provider = this.provider; var parent = node.parent; while (parent) { if (!provider.isOpen(parent)) provider.expand(parent); parent = parent.parent; } this.select(node); var scrollTop = this.renderer.scrollTop; this.renderer.scrollCaretIntoView(node, 0.5); if (animate !== false) this.renderer.animateScrolling(scrollTop); }; this.undo = function() { this.$blockScrolling++; this.session.getUndoManager().undo(); this.$blockScrolling--; this.renderer.scrollCaretIntoView(null, 0.5); }; this.redo = function() { this.$blockScrolling++; this.session.getUndoManager().redo(); this.$blockScrolling--; this.renderer.scrollCaretIntoView(null, 0.5); }; this.getReadOnly = function() { return this.getOption("readOnly"); }; this.destroy = function() { this.renderer.destroy(); this._emit("destroy", this); }; this.setHorHeadingVisible = function(value){ this.renderer.setHorHeadingVisible(value); }; this.setVerHeadingVisible = function(value){ this.renderer.setVerHeadingVisible(value); }; this.enable = function() { this.$disabled = false; this.container.style.pointerEvents = ""; this.container.style.opacity = ""; }; this.disable = function() { this.$disabled = true; this.container.style.pointerEvents = "none"; this.container.style.opacity = "0.9"; if (this.isFocused()) this.blur(); }; }).call(Tree.prototype); config.defineOptions(Tree.prototype, "Tree", { toggle: { set: function(toggle) { }, initialValue: false }, readOnly: { set: function(readOnly) { this.textInput.setReadOnly(readOnly); }, initialValue: false }, animatedScroll: "renderer", maxLines: "renderer", minLines: "renderer", scrollSpeed: "$mouseHandler", enableDragDrop: "$mouseHandler" }); module.exports = Tree; }); define("ace_tree/scrollable",[], function(require, exports, module) { "use strict"; var oop = require("ace/lib/oop"); var EventEmitter = require("ace/lib/event_emitter").EventEmitter; var scrollable = {}; (function() { oop.implement(this, EventEmitter); this.$scrollTop = 0; this.getScrollTop = function() { return this.$scrollTop; }; this.setScrollTop = function(scrollTop) { scrollTop = Math.round(scrollTop); if (this.$scrollTop === scrollTop || isNaN(scrollTop)) return; this.$scrollTop = scrollTop; this._signal("changeScrollTop", scrollTop); }; this.$scrollLeft = 0; this.getScrollLeft = function() { return this.$scrollLeft; }; this.setScrollLeft = function(scrollLeft) { scrollLeft = Math.round(scrollLeft); if (this.$scrollLeft === scrollLeft || isNaN(scrollLeft)) return; this.$scrollLeft = scrollLeft; this._signal("changeScrollLeft", scrollLeft); }; }).call(scrollable); module.exports = scrollable; }); define("ace_tree/data_provider",[], function(require, exports, module) { "use strict"; var oop = require("ace/lib/oop"); var Scrollable = require("./scrollable"); var dom = require("ace/lib/dom"); var escapeHTML = require("ace/lib/lang").escapeHTML; var DataProvider = function(root) { this.rowHeight = 25; this.setRoot(root); }; (function() { this.rowHeight = undefined; this.rowHeightInner = undefined; this.$indentSize = 10; oop.implement(this, Scrollable); this.$sortNodes = true; this.setRoot = function(root){ if (Array.isArray(root)) root = {items: root}; this.root = root || {}; if (this.root.$depth == undefined) { this.root.$depth = -1; } if (this.root.$depth < 0) { this.visibleItems = []; this.open(this.root); this.visibleItems.unshift(); } else { this.visibleItems = [this.root]; } this.$selectedNode = this.root; this._signal("setRoot"); this._signal("change"); }; this.open = this.expand = function(node, deep, silent) { if (typeof deep != "number") deep = deep ? 100 : 0; if (!node) return; var items = this.visibleItems; if (this.isOpen(node) && (node !== this.root || items.length)) return; var ch = this.getChildren(node); if (this.loadChildren && this.shouldLoadChildren(node, ch)) { var timer = setTimeout(function() { node.status = "loading"; this._signal("change", node); }.bind(this), 100); this.loadChildren(node, function(err, ch) { clearTimeout(timer); this.collapse(node, null, true); node.status = "loaded"; if (!err) this.expand(node, null, false); }.bind(this)); this.setOpen(node, true); return; } this.setOpen(node, true); var i = items.indexOf(node); if (!ch) { this._signal("change", node); return; } if (i === -1 && items.length || this.forceEmpty) return; ch = [i + 1, 0].concat(ch); items.splice.apply(items, ch); for (var j = 2; j < ch.length; j++) { var childNode = ch[j]; if (this.isOpen(childNode)) { this.setOpen(childNode, false); this.open(childNode, deep - 1, silent); } else if (deep > 0) { this.open(childNode, deep - 1, silent); } } this.rows = items.length; silent || this._signal("expand", node); }; this.close = this.collapse = function(node, deep, silent) { if (typeof deep != "number") deep = deep ? 1000 : 0; var items = this.visibleItems; var isRoot = node === this.root; if (isRoot) { this.setOpen(node, false); if (deep) { for (var i = 0; i < items.length; i++) { var ch = items[i]; if (!ch.isRoot) if (this.isOpen(ch) && ch.$depth - node.$depth < deep) { this.setOpen(ch, false); silent || this._signal("collapse", ch); } } } items.length = 0; if (isRoot) this.open(this.root, 0, silent); return; } if (!node || !this.isOpen(node)) return; var i = items.indexOf(node); if (i === -1) return; var thisDepth = node.$depth; var deletecount = 0; for (var t = i + 1; t < items.length; t++) { if (items[t].$depth > thisDepth) deletecount++; else break; } if (deep) { for (var j = 0; j < deletecount; j++) { var ch = items[j + i]; if (this.isOpen(ch) && ch.$depth - node.$depth < deep) { this.setOpen(ch, false); silent || this._signal("collapse", ch); } } } items.splice(i + 1, deletecount); this.setOpen(node, false); silent || this._signal("collapse", node); if (isRoot) this.open(this.root, 0, silent); }; this.toggleNode = function(node, deep, silent) { if (node && this.isOpen(node)) this.close(node, deep, silent); else this.open(node, deep, silent); }; this.sort = function(children, compare) { if (!compare) { compare = alphanumCompare; } return children.sort(function(a, b) { var aChildren = a.children || a.map; var bChildren = b.children || b.map; if (aChildren && !bChildren) return -1; if (!aChildren && bChildren) return 1; return compare(a.label || "", b.label || ""); }); }; this.setFilter = function(fn) { this.$filterFn = fn; this.setRoot(this.root); }; this.getChildren = function(node) { var children = node.children; if (!children) { if (node.status === "pending") return; if (node.map) { children = Object.keys(node.map).map(function(key) { var ch = node.map[key]; ch.parent = node; return ch; }); } else if (node.items) { children = node.items; } if (children) { node.children = children; } } var ch = children && children[0] && children[0]; if (ch) { var d = (node.$depth + 1) || 0; children.forEach(function(n) { n.$depth = d; n.parent = node; }); } if (this.$filterFn) { children = children && children.filter(this.$filterFn); } if (this.$sortNodes && !node.$sorted) { children && this.sort(children); } return children; }; this.loadChildren = null; this.shouldLoadChildren = function(node, ch) { return node.status === "pending"; }; this.hasChildren = function(node) { if (node.children) return node.children.length !== 0; return node.map || node.status === "pending" || node.items && node.items.length; }; this.findNodeByPath = function() { }; this.getSibling = function(node, dir) { if (!dir) dir = 1; var parent = node.parent; var ch = this.getChildren(parent); var pos = ch.indexOf(node); return ch[pos + dir]; }; this.getNodeAtIndex = function(i) { return this.visibleItems[i]; }; this.getIndexForNode = function(node) { return this.visibleItems.indexOf(node); }; this.getMinIndex = function() {return 0}; this.getMaxIndex = function() {return this.visibleItems.length - 1}; this.setOpen = function(node, val) { return node.isOpen = val; }; this.isOpen = function(node) { return node.isOpen; }; this.isVisible = function(node) { return this.visibleItems.indexOf(node) !== -1; }; this.isSelected = function(node) { return node.isSelected; }; this.setSelected = function(node, val) { return node.isSelected = !!val; }; this.isSelectable = function(node) { return !node || !(node.noSelect || node.$depth < 0); }; this.isAncestor = function(node, child) { do { if (child == node) return true; } while (child = child.parent); return false; }; this.setAttribute = function(node, name, value) { node[name] = value; this._signal("change", node); }; this.getDataRange = function(rows, columns, callback) { var view = this.visibleItems.slice(rows.start, rows.start + rows.length); callback(null, view, false); return view; }; this.getRange = function(top, bottom) { var start = Math.floor(top / this.rowHeight); var end = Math.ceil(bottom / this.rowHeight) + 1; var range = this.visibleItems.slice(start, end); range.count = start; range.size = this.rowHeight * range.count; return range; }; this.getTotalHeight = function(top, bottom) { return this.rowHeight * this.visibleItems.length; }; this.getNodePosition = function(node) { var i = this.visibleItems.indexOf(node); if (i == -1 && node && node.parent) { i = this.visibleItems.indexOf(node.parent); } var top = i * this.rowHeight; var height = this.rowHeight; return {top: top, height: height}; }; this.findItemAtOffset = function(offset, clip) { var index = Math.floor(offset / this.rowHeight); if (clip) index = Math.min(Math.max(0, index), this.visibleItems.length - 1); return this.visibleItems[index]; }; this.getIconHTML = function(node) { return ""; }; this.getClassName = function(node) { return (node.className || "") + (node.status == "loading" ? " loading" : ""); }; this.setClass = function(node, name, include) { node.className = node.className || ""; dom.setCssClass(node, name, include); this._signal("changeClass"); }; this.redrawNode = null; this.getCaptionHTML = function(node) { return escapeHTML(node.label || node.name || (typeof node == "string" ? node : "")); }; this.getContentHTML = null; this.getEmptyMessage = function() { return this.emptyMessage || "" }; this.getText = function(node) { return node.label || node.name || ""; }; this.getRowIndent = function(node){ return node.$depth; }; this.hideAllNodes = function(){ this.visibleItems = []; this.forceEmpty = true; this.setRoot(this.root); }; this.showAllNodes = function(){ this.forceEmpty = false; this.setRoot(this.root); }; }).call(DataProvider.prototype); function alphanumCompare(a, b) { var caseOrder = 0; for (var x = 0, l = Math.min(a.length, b.length); x < l; x++) { var ch1 = a.charCodeAt(x); var ch2 = b.charCodeAt(x); if (ch1 < 58 && ch2 < 58 && ch1 > 47 && ch2 > 47) { var num1 = 0, num2 = 0; var n = x; do { num1 = 10 * num1 + (ch1 - 48); ch1 = a.charCodeAt(++n); } while(ch1 > 47 && ch1 < 58); n = x; do { num2 = 10 * num2 + (ch2 - 48); ch2 = b.charCodeAt(++n); } while(ch2 > 47 && ch2 < 58); if (num1 === num2) x = n - 1; else return num1 - num2; } else if (ch1 !== ch2) { var ch1L = a[x].toLowerCase(); var ch2L = b[x].toLowerCase(); if (ch1L < ch2L) return -1; if (ch1L > ch2L) return 1; if (!caseOrder) caseOrder = ch2 - ch1; } } return caseOrder || a.length - b.length; } DataProvider.alphanumCompare = alphanumCompare; DataProvider.prototype.alphanumCompare = alphanumCompare; DataProvider.variableHeightRowMixin = function() { var reset = function () { this.$cachedTotalHeight = 0; }.bind(this); this.on("collapse", reset); this.on("expand", reset); this.getNodePosition = function(node) { var i = this.visibleItems.indexOf(node); if (i == -1 && node && node.parent) { i = this.visibleItems.indexOf(node.parent); } var items = this.visibleItems; var top = 0, height = 0; for (var index = 0; index < i; index++) { height = this.getItemHeight(items[index], index); top += height; } height = this.getItemHeight(items[i], i); return {top: top, height: height}; }; this.findIndexAtOffset = function(offset, clip) { var items = this.visibleItems; var top = 0, index = 0, l = items.length; while (index < l) { var height = this.getItemHeight(items[index], index); top += height; index++; if (top >= offset) { index--; top -= height; break; } } if (clip) index = Math.min(Math.max(0, index), items.length - 1); return index; }; this.findItemAtOffset = function(offset, clip) { var index = this.findIndexAtOffset(offset, clip); return this.visibleItems[index]; }; this.getItemHeight = function(node, index) { return node.height || this.rowHeight; }; this.getRange = function(top, bottom) { var items = this.visibleItems; var startH = 0, index = 0, l = items.length; while (index < l) { var height = this.getItemHeight(items[index], index); startH += height; index++; if (startH >= top) { index--; startH -= height; break; } } index = Math.min(Math.max(0, index), items.length - 1); var start = index; var end = this.findIndexAtOffset(bottom, true) + 1; var range = this.visibleItems.slice(start, end); range.count = start; range.size = startH; return range; }; this.getTotalHeight = function () { if (!this.$cachedTotalHeight) { var items = this.visibleItems; var height = 0; for (var index = 0; index < items.length; index++) { height += this.getItemHeight(items[index], index); } this.$cachedTotalHeight = height; } return this.$cachedTotalHeight; }; }; module.exports = DataProvider; }); define("plugins/c9.ide.collab/members/membersdp",[], function(require, exports, module) { var oop = require("ace/lib/oop"); var BaseClass = require("ace_tree/data_provider"); var escapeHTML = require("ace/lib/lang").escapeHTML; function DataProvider(root) { BaseClass.call(this, root || {}); this.rowHeight = 22; this.rowHeightInner = 20; this.expandedList = Object.create(null); this.selectedList = Object.create(null); Object.defineProperty(this, "loaded", { get: function() { return this.visibleItems.length; } }); } oop.inherits(DataProvider, BaseClass); (function() { this.$sortNodes = false; this.getEmptyMessage = function() { return "Loading Members..."; }; this.getContentHTML = function (datarow) { var nameHTML = escapeHTML(datarow.name || ""); if (datarow.type == "file") return "" + nameHTML + ""; if (!datarow.uid) return "" + nameHTML + ""; var access = datarow.acl || "r"; var canAccessControl = this.iAmAdmin && !datarow.isAdmin; var disabledLabel = access == "r" ? "
R
" : "
RW
"; var status = datarow.onlineStatus || "offline"; var color = datarow.color || "transparent"; var html = [ "" + nameHTML + "\n", "\n", "\n", canAccessControl ? ("
" + "
R
" + "
RW
" + "
\n") : ("
" + disabledLabel + "
\n" + (datarow.name == "You" && !datarow.isAdmin ? "
\n" : "") ), ]; return html.join(""); }; this.getClassName = function(node) { return (node.className || ""); }; this.setOpen = function(node, val) { if (!node.id) return (node.isOpen = val); if (val) this.expandedList[node.id] = val; else delete this.expandedList[node.id]; }; this.isOpen = function(node) { if (!node.id) return node.isOpen; return this.expandedList[node.id]; }; this.isSelected = function(node) { if (!node.id) return node.isSelected; return this.selectedList[node.id]; }; this.setSelected = function(node, val) { if (!node.id) return (node.isSelected = !!val); if (val) this.selectedList[node.id] = !!val; else delete this.selectedList[node.id]; }; this.loadChildren = function(node) { }; this.shouldLoadChildren = function(node, ch) { return node.client ? node.client.status === "pending" : node.children && node.children.status === "pending"; }; this.hasChildren = function(node) { return node.children; }; }).call(DataProvider.prototype); return DataProvider; }); define("plugins/c9.ide.collab/members/members_panel",[], function(require, exports, module) { "use strict"; main.consumes = [ "Plugin", "ui", "util", "apf", "Menu", "MenuItem", "Divider", "collab.workspace", "info", "dialog.error", "dialog.confirm", "accessControl", "collab" ]; main.provides = ["MembersPanel"]; return main; function main(options, imports, register) { var Plugin = imports.Plugin; var c9Util = imports.util; var apf = imports.apf; var Menu = imports.Menu; var Divider = imports.Divider; var MenuItem = imports.MenuItem; var workspace = imports["collab.workspace"]; var info = imports.info; var showError = imports["dialog.error"].show; var confirm = imports["dialog.confirm"].show; var accessControl = imports.accessControl; var collab = imports.collab; var cloneObject = c9Util.cloneObject; var Tree = require("ace_tree/tree"); var TreeData = require("./membersdp"); var mnuCtxTreeEl; var ROLE_ADMIN = "a"; function MembersPanel(developer, deps, options) { var plugin = new Plugin(developer, deps); var membersTree, membersDataProvider, parent; var drawn = false; function draw(options) { if (drawn) return; drawn = true; parent = options.aml; membersTree = new Tree(parent.$int); membersDataProvider = new TreeData(); membersTree.renderer.setTheme({ cssClass: "memberstree" }); membersTree.renderer.setScrollMargin(0, 10); membersTree.setDataProvider(membersDataProvider); membersTree.on("mousedown", function(e) { var domTarget = e.domEvent.target; var node = e.getNode(); if (!node || !domTarget || e.domEvent.button) return; var className = domTarget.classList; membersDataProvider.selection.selectNode(node); if (className.contains("access_control")) { if (className.contains("rw")) { className.remove("rw"); className.add("r"); } else { className.remove("r"); className.add("rw"); } } }); membersTree.on("mouseup", function(e) { var domTarget = e.domEvent.target; var node = e.getNode(); if (!node || !domTarget || e.domEvent.button) return; if (e.editor.$mouseHandler.isMousePressed) return; var className = domTarget.classList; membersDataProvider.selection.selectNode(node); if (className.contains("access_control")) updateAccess(node.acl == "rw" ? "r" : "rw"); else if (className == "kickout") removeMember(); }); membersTree.on("dblclick", function(e) { var domTarget = e.domEvent.target; var node = e.getNode(); if (!node || !domTarget) return; if (domTarget.classList.contains("ace_tree_cells")) { if (node.type == "file") { e.stop(); revealUser(); } } }); membersDataProvider.loadChildren = function(node, cb) { if (node.clientId) { if (node.client) node.client.status = "loading"; node.children.status = "loading"; collab.listOpenFiles(node.clientId, function() { cb && cb(); node.children.status = "loaded"; onWorkspaceSync(); }); } }; var mnuCtxTree = new Menu({ id: "mnuMembers", items: [ new MenuItem({ caption: "Request Read+Write Access", match: function(item, node) { item.setAttribute("visible", !workspace.accessInfo.member); }, onclick: accessControl.requestAccess }), new MenuItem({ caption: "Leave workspace", match: function(item, node) { item.setAttribute("visible", !workspace.accessInfo.admin); return node.name == "You"; }, onclick: removeMember.bind(null, "rw") }), new MenuItem({ caption: "Grant Read+Write Access", match: function(item, node) { item.setAttribute("visible", workspace.accessInfo.admin); return node.acl == "r"; }, onclick: updateAccess.bind(null, "rw") }), new MenuItem({ caption: "Revoke Write Access", match: function(item, node) { item.setAttribute("visible", workspace.accessInfo.admin); return node.acl == "rw" && !node.isAdmin; }, onclick: updateAccess.bind(null, "r") }), new MenuItem({ caption: "Revoke Access", match: function(item, node) { item.setAttribute("visible", workspace.accessInfo.admin); return !node.isAdmin; }, onclick: removeMember }), new Divider(), new MenuItem({ caption: "Show Location", match: "online", onclick: revealUser }) ] }, plugin); mnuCtxTreeEl = mnuCtxTree.aml; mnuCtxTree.on("show", function() { var node = getSelectedMember() || {}; if (!node.uid) return mnuCtxTreeEl.hide(); mnuCtxTreeEl.childNodes.forEach(function(item) { var match = item.match; var disabled = false; if (match == "online") { disabled = !node.clientId; } else if (typeof match == "function") { disabled = match(item, node) == false; } item.setAttribute("disabled", disabled); }); }); parent.setAttribute("contextmenu", mnuCtxTreeEl); window.addEventListener('resize', resize, true); parent.on("resize", resize); membersTree.container.style.position = "relative"; membersTree.container.style.top = "0px"; } function hide() { workspace.off("sync", onWorkspaceSync); } function alertIfError(err) { err && showError("Error", "Members Panel Error", err.message); } function show() { workspace.loadMembers(alertIfError); workspace.off("sync", onWorkspaceSync); workspace.on("sync", onWorkspaceSync); setTimeout(resize); } function resize() { var next = parent; var h = 0; if (!parent.parentNode || !parent.parentNode.visible) return; if (!options.autoSize || parent.tagName != "frame") return membersTree.resize(); var m1 = next.state[0] == "m"; next = next.nextSibling; var m2 = next && next.state[0] == "m"; next = next && next.nextSibling; var m3 = next && next.state[0] == "m"; if (m1) return; if (m2 && m3) { membersTree.renderer.setOption("maxLines", 0); h = parent.$ext.parentNode.clientHeight - 3 * parent.$ext.firstElementChild.clientHeight; } var rowHeight = membersTree.provider.rowHeight; var maxLines = Math.max(h || (window.innerHeight / 2 - 60), 60) / rowHeight; membersTree.renderer.setOption("maxLines", maxLines); membersTree.resize(); } function updateAccess(acl) { var node = getSelectedMember(); var uid = node.uid; workspace.updateAccess(uid, acl, alertIfError); } function removeMember() { var node = getSelectedMember(); var isPublic = workspace.accessInfo.private === false; confirm( "Remove Member?", "Are you sure you want to " + (node.name == "You" ? "leave " : "remove '" + node.name + "' out of your ") + "workspace '" + info.getWorkspace().name + "'?", "People who are not members of a workspace, can not " + (isPublic ? "" : "read, ") + "write or collaborate on that workspace ", function() { // Yes var uid = node.uid; workspace.removeMember(uid, alertIfError); }, function() { /* No */ }, { yes: node.name == "You" ? "Leave" : "Remove Member", no: "Cancel" } ); } function revealUser() { var node = getSelectedMember(); var clientId = node && node.clientId; if (!clientId) return; collab.revealUser(clientId, node.tabId); } function loadUserState() { var node = getSelectedMember(); return node; } function getSelectedMember() { return membersTree.selection.getCursor(); } function onWorkspaceSync() { var me = info.getUser(); var membersById = membersDataProvider.byId || (membersDataProvider.byId = {}); var members = { r: [], rw: []}; var myRow = {}; var myClientId = workspace.myClientId; var cachedMembers = workspace.members; var users = workspace.users; if (!cachedMembers.length) { // We're visiting a public workspace cachedMembers = [{ acl: "r", name: "You", pending: false, role: "v", uid: me.id, email: me.email }]; membersDataProvider.byId = null; } cachedMembers.forEach(function(newM) { var m = membersById[newM.uid] || (membersById[newM.uid] = {}); for (var i in newM) m[i] = newM[i]; m.isAdmin = m.role == ROLE_ADMIN; m.color = workspace.getUserColor(m.uid); m.onlineStatus = workspace.getUserState(m.uid); if (!m.md5Email) m.md5Email = m.email ? apf.crypto.MD5.hex_md5(m.email.trim().toLowerCase()) : ""; members[m.acl == "rw" ? "rw" : "r"].push(m); var user = users[m.uid]; var clientIds = user && user.clients; m.children = clientIds && clientIds.length && clientIds.map(function(k, i) { var children = null, client; if (options.showTabs) { client = clientIds[k]; if (client) { if (!client.status) client.status = "pending"; children = client.documents.map(function(x, i) { return { type: "file", name: x, tabId: x, className: i == client.active ? "active" : "", id: k + "::" + x, clientId: k }; }); client.status = client.status || "pending"; } else if (user.online) { children = []; children.status = "pending"; } } return { type: "ide", pending: true, clientId: k, name: "Ide instance " + i, user: m, children: children, id: k }; }); if (m.uid == me.id) { m.name = "0000"; // top in every sort m.status = "online"; myRow = m; m.clientId = myClientId; m.client = null; if (m.children) { m.children = m.children.filter(function(ide) { return ide.clientId !== myClientId; }); if (!m.children.length) { m.children = null; } } } else { m.clientId = clientIds && clientIds[0]; m.client = clientIds && clientIds[m.clientId]; if (m.children && m.children.length == 1) { m.pending = true; m.children = m.children[0].children; } } }); function memberCompartor (m1, m2) { return m1.name > m2.name; } members.r.sort(memberCompartor); members.rw.sort(memberCompartor); myRow.name = "You"; membersDataProvider.iAmAdmin = myRow.isAdmin; var root = membersDataProvider.root; if (!root.rw) { root.rw = { name: "Read+Write", children: members.rw, noSelect: true, clickAction: "toggle", className: "caption", isOpen: true }; root.r = { name: "Read Only", noSelect: true, clickAction: "toggle", className: "caption", isOpen: true }; } root.rw.children = members.rw; root.r.children = members.r; root.children = [root.rw, root.r].filter(function(x) { return x.children.length; }); membersDataProvider.setRoot(root); } plugin.freezePublicAPI.baseclass(); plugin.freezePublicAPI({ draw: draw, resize: resize, show: show, hide: hide }); return plugin; } register(null, { MembersPanel: MembersPanel }); } }); define("text!plugins/c9.ide.collab/notifications/notifications.css",[],""); define("plugins/c9.ide.collab/notifications/notificationsdp",[], function(require, exports, module) { var oop = require("ace/lib/oop"); var BaseClass = require("ace_tree/data_provider"); function DataProvider(root) { BaseClass.call(this, root || {}); this.rowHeight = 50; this.rowHeightInner = 48; Object.defineProperty(this, "loaded", { get: function() { return this.visibleItems.length; } }); } oop.inherits(DataProvider, BaseClass); (function() { this.$sortNodes = false; this.emptyMessage = "Loading Notifications ..."; this.setRoot = function(root) { if (Array.isArray(root)) root = { items: root }; this.root = root || {}; this.visibleItems = []; this.open(this.root, true); this._signal("change"); }; this.getContentHTML = function (datarow) { return datarow.getHTML(); }; }).call(DataProvider.prototype); return DataProvider; }); define("plugins/c9.ide.collab/notifications/notifications",[], function(require, exports, module) { "use strict"; main.consumes = ["CollabPanel", "ui", "api", "dialog.alert", "dialog.error", "c9", "panels", "collab.workspace"]; main.provides = ["notifications"]; return main; function main(options, imports, register) { var CollabPanel = imports.CollabPanel; var c9 = imports.c9; var ui = imports.ui; var api = imports.api; var panels = imports.panels; var alert = imports["dialog.alert"].show; var showError = imports["dialog.error"].show; var workspace = imports["collab.workspace"]; var css = require("text!./notifications.css"); var oop = require("ace/lib/oop"); var Tree = require("ace_tree/tree"); var TreeData = require("./notificationsdp"); var plugin = new CollabPanel("Ajax.org", main.consumes, { name: "notifications", index: 150, caption: "Notifications", height: "20%" }); var NOTIFICATION_TYPES = {}; var notificationsParent, notificationsTree, notificationsDataProvider; var frame, panelButton, bubble; var loaded = false; function load() { if (loaded) return; loaded = true; ui.insertCss(css, null, plugin); notificationsDataProvider = new TreeData(); c9.once("ready", function() { setTimeout(loadNotifications, 10000); }); if (!options.hosted && c9.debug) { addNotifications([ { name: "Bas de Wachter", uid: 8, email: "bas@c9.io", type: "access_request" }, { name: "Mostafa Eweda", uid: 1, email: "mostafa@c9.io", type: "access_request" }, { name: "Lennart Kats", uid: 5, email: "lennart@c9.io", type: "access_request" }, { name: "Ruben Daniels", uid: 2, email: "ruben@ajax.org", type: "access_request" }, { name: "Fabian Jakobs", uid: 4, email: "fabian@ajax.org", type: "access_request" } ]); } workspace.on("notification", function(notif) { addNotifications(notif); postLoadedNotifications(); if (!isOpen()) { var sound = document.getElementById("chatNotif"); sound && sound.play(); } }); } var drawn = false; function draw(options) { if (drawn) return; drawn = true; notificationsParent = options.html; frame = options.aml; notificationsTree = new Tree(notificationsParent); notificationsTree.renderer.setScrollMargin(0, 10); notificationsTree.renderer.setTheme({ cssClass: "notificationstree" }); notificationsTree.setOption("maxLines", 3); notificationsTree.setDataProvider(notificationsDataProvider); notificationsTree.on("mousedown", function(e) { var domTarget = e.domEvent.target; var pos = e.getDocumentPosition(); var notif = notificationsDataProvider.findItemAtOffset(pos.y); if (!notif || !domTarget) return; notif.handleMouseDown(e); }); notificationsTree.on("mouseup", function(e) { var domTarget = e.domEvent.target; var pos = e.getDocumentPosition(); var notif = notificationsDataProvider.findItemAtOffset(pos.y); if (!notif || !domTarget) return; notif.handleMouseUp(e); }); plugin.on("hide", function(e) { notificationsTree.renderer.freeze(); }); plugin.on("show", function(e) { notificationsTree.renderer.unfreeze(); notificationsTree.renderer.$loop.schedule(notificationsTree.renderer.CHANGE_FULL); }); if (!cachedNotifications.length) frame.minimize(); postLoadedNotifications(); frame.on("resize", resize); setTimeout(resize, 150); // HACK around apf layout bug } var cachedNotifications = []; function loadNotifications() { if (!options.isAdmin || !options.hosted) return postLoadedNotifications(); api.collab.get("members/list?pending=1", function (err, members) { if (err && (err.code === 0 || err.code === 503)) { return setTimeout(loadNotifications, 20000); } if (err) return showError(err); if (Array.isArray(members)) { var notifs = members.map(function(m) { m.type = "access_request"; return m; }); cachedNotifications = []; addNotifications(notifs); postLoadedNotifications(); } }); } function resize() { var count = cachedNotifications.length; if (!bubble) { if (!panels.panels.collab.enabled && count) panels.enablePanel("collab"); panelButton = document.querySelector(".panelsbutton.collab"); if (panelButton) { bubble = panelButton.appendChild(document.createElement("div")); bubble.className = "newnotifs"; } } if (bubble) { if (count) { bubble.textContent = count; bubble.style.display = "block"; bubble.className = "newnotifs size" + String(count).length; } else { bubble.style.display = "none"; } } if (drawn) { if (frame.state[0] != "m") { frame.$ext.style.height = count ? Math.min(count, 3) * 50 + 22 + "px" : 50 + "px"; notificationsTree.resize(); } else { frame.$ext.style.height = "0"; } } } function postLoadedNotifications() { resize(); if (!drawn) return; notificationsDataProvider.emptyMessage = "No pending notifications"; frame.setAttribute("caption", "Notifications (" + cachedNotifications.length + ")"); onNotificationsLoaded(); } function addNotifications(notifs) { if (!Array.isArray(notifs)) notifs = [notifs]; if (frame) frame.restore(); notifs.forEach(function(notif) { var NotifConstructor = NOTIFICATION_TYPES[notif.type]; if (!NotifConstructor) console.error("Invalid notification type:", notif.type); cachedNotifications.push(new NotifConstructor(notif)); }); if (notificationsDataProvider) notificationsDataProvider.setRoot(cachedNotifications); } function onNotificationsLoaded() { if (frame && cachedNotifications.length) frame.restore(); } function isOpen() { return panels.isActive("collab") && frame && frame.state[0] != "m"; } function Notification(datarow) { this.datarow = datarow; } (function () { this.getHTML = function (datarow) { throw new Error("No impl found - getHTML"); }; this.handleMouseDown = function () { throw new Error("No impl found - handleMouseDown"); }; this.remove = function () { var _self = this; cachedNotifications = cachedNotifications.filter(function (notif) { return notif !== _self; }); notificationsDataProvider.setRoot(cachedNotifications); postLoadedNotifications(); }; }).call(Notification.prototype); function AccessRequestNotification(datarow) { datarow.md5Email = datarow.email ? apf.crypto.MD5.hex_md5(datarow.email.trim().toLowerCase()) : ""; this.datarow = datarow; } oop.inherits(AccessRequestNotification, Notification); (function () { this.getHTML = function () { var datarow = this.datarow; var avatarImg = ''; var html = [ "", avatarImg, "", "", "", datarow.name, "", " requests access to this workspace", "", '
', '
R
RW
', '
', '
', '
Grant
', '
', '
', '
Deny
', '
', "
" ]; return html.join(""); }; this.acceptRequest = function (access) { var _self = this; if (!options.hosted) return requestAccepted(); var datarow = this.datarow; var uid = datarow.uid; api.collab.post("accept_request", { body: { uid: uid, access: access } }, function (err, data, res) { if (err) { var message = err.message || err; var user = workspace.getUser(uid); if (user && !user.pending || / isn't a pending workspace member/.test(message)) { return _self.remove(); // it was already handled ignore } return alert("Error", message); } requestAccepted(); }); function requestAccepted() { datarow.acl = access; workspace.addMemberNonPubSub(datarow); _self.remove(); } }; this.denyRequest = function () { var _self = this; if (!options.hosted) return requestDenied(); var uid = this.datarow.uid; api.collab.post("deny_request", { body: { uid: uid } }, function (err, data, res) { if (err) { var message = err.message || err; var user = workspace.getUser(uid); if (!user || / isn't a member of project /.test(message)) { return _self.remove(); // it was already handled ignore } return alert("Error", message); } requestDenied(); }); function requestDenied() { _self.remove(); } }; this.handleMouseDown = function (e) { var target = e.domEvent.target; if (e.domEvent.button) return; var className = target.classList; if (className.contains("access_control")) { var actionArr = className.contains("rw") ? ["rw", "r"] : ["r", "rw"]; className.remove(actionArr[0]); className.add(actionArr[1]); return; } }; this.handleMouseUp = function (e) { var target = e.domEvent.target; var className = target.classList; if (e.domEvent.button) return; if (e.editor.$mouseHandler.isMousePressed) return; if (className.contains("grant")) { var rwClassName = target.previousSibling.classList; var access = rwClassName.contains("rw") ? "rw" : "r"; this.acceptRequest(access); } else if (className.contains("deny")) { this.denyRequest(); } }; }).call(AccessRequestNotification.prototype); NOTIFICATION_TYPES["access_request"] = AccessRequestNotification; plugin.on("load", function() { load(); plugin.once("draw", draw); }); plugin.on("enable", function() { }); plugin.on("disable", function() { }); plugin.on("unload", function() { loaded = false; drawn = false; cachedNotifications = []; if (notificationsTree) notificationsTree.destroy(); notificationsDataProvider = null; notificationsTree = null; notificationsParent = null; frame = null; panelButton = null; bubble = null; }); plugin.freezePublicAPI({ addNotifications: addNotifications }); register(null, { notifications: plugin }); } }); define("text!plugins/c9.ide.collab/timeslider/timeslider.html",[],"
\n
\n \n \n - \n \n \n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
Revert
\n \n
\n
\n"); define("text!plugins/c9.ide.collab/timeslider/timeslider.css",[],""); define("plugins/c9.ide.collab/timeslider/timeslider",[], function(require, exports, module) { "use strict"; main.consumes = [ "Plugin", "c9", "ui", "ace", "tabManager", "settings", "menus", "commands", "save", "layout", "util" ]; main.provides = ["timeslider"]; return main; function main(options, imports, register) { var Plugin = imports.Plugin; var c9 = imports.c9; var ui = imports.ui; var ace = imports.ace; var util = imports.util; var tabs = imports.tabManager; var settings = imports.settings; var menus = imports.menus; var layout = imports.layout; var commands = imports.commands; var save = imports.save; var html = require("text!./timeslider.html"); var css = require("text!./timeslider.css"); var dom = require("ace/lib/dom"); var isLoading; var tsVisibleKey = "user/collab/@timeslider-visible"; var timesliderKeyboardHandler = { handleKeyboard: function(data, hashId, keystring) { if (keystring == "esc") { forceHideSlider(); return { command: "null" }; } } }; var container, timeslider, timesliderClose, slider; var sliderBar, handle, playButton, playButtonIcon, revisionInfo; var revisionDate, revisionLabel, leftStep, rightStep, revertButton; var sliderProgress, activeDocument; var plugin = new Plugin("Ajax.org", main.consumes); var emit = plugin.getEmitter(); var sliderLength = 1000; var sliderPos = 0; var sliderActive = false; var savedRevisions = []; var savedRevisionNums = []; var sliderPlaying = false; var LEFT_PADDING = 64; var loaded = false; function load(callback) { if (loaded) return false; loaded = true; commands.addCommand({ name: "toggleTimeslider", exec: toggleTimeslider, isAvailable: timesliderAvailable }, plugin); commands.addCommand({ name: "forceToggleTimeslider", exec: function() { var isVisible = settings.getBool(tsVisibleKey); settings.set(tsVisibleKey, !isVisible); toggleTimeslider(); }, isAvailable: timesliderAvailable }, plugin); menus.addItemByPath("File/Show File Revision History", new ui.item({ type: "check", checked: "" + tsVisibleKey + "", command: "toggleTimeslider" }), 1240, plugin); menus.addItemByPath("File/~", new ui.divider(), 1250, plugin); settings.on("read", function () { settings.set(tsVisibleKey, false); }, plugin); var mnuCtxEditorFileHistory = new ui.item({ caption: "File History", command: "forceToggleTimeslider" }, plugin); ace.getElement("menu", function(menu) { menus.addItemToMenu(menu, mnuCtxEditorFileHistory, 500, plugin); menus.addItemToMenu(menu, new ui.divider(), 550, plugin); menu.on("prop.visible", function(e) { if (e.value) { var editor = tabs.focussedTab.editor; if (timesliderAvailable(editor)) mnuCtxEditorFileHistory.enable(); else mnuCtxEditorFileHistory.disable(); } }); }); tabs.on("paneDestroy", function (e) { if (!tabs.getPanes(tabs.container).length) forceHideSlider(); }, plugin); tabs.on("focusSync", function(e) { util.nextFrame(function() { var doc = getTabCollabDocument(e.tab); if (activeDocument && isVisible) { if (activeDocument == doc) return; hide(); isVisible = true; } activeDocument = doc; if (!isVisible) return; if (!doc) return forceHideSlider(); show(); doc.loadRevisions(); }); }, plugin); save.on("beforeSave", function(e) { if (isVisible) return false; }, plugin); plugin.on("slider", function (revNum) { if (!activeDocument || !isVisible) return; schedule(revNum); }); } var scheduled, lastRevNum; function schedule(revNum) { lastRevNum = revNum; if (scheduled) return; util.nextFrame(function() { lastRevNum && activeDocument.updateToRevision(lastRevNum); scheduled = false; }); } var drawn = false; function draw () { if (drawn) return; drawn = true; ui.insertHtml(null, html, plugin); ui.insertCss(css, null, plugin); function $(id) { return document.getElementById(id); } var ext = $("timeslider-top"); timeslider = $("timeslider"); timesliderClose = $("timeslider_close"); slider = $("timeslider-slider"); sliderBar = $("ui-slider-bar"); sliderProgress = $("ui-slider-progress"); handle = $("ui-slider-handle"); playButton = $("playpause_button"); playButtonIcon = $("playpause_button_icon"); revisionInfo = $("revision_info"); revisionDate = $("revision_date"); revisionLabel = $("revision_label"); leftStep = $("leftstep"); rightStep = $("rightstep"); revertButton = $("revert_to_rev"); var tbcont = tabs.container; var box = new ui.vsplitbox({}); tbcont.parentNode.insertBefore(box, tbcont.nextSibling); container = box.appendChild(new ui.bar({ height: 64 })); container.$ext.appendChild(ext); box.appendChild(tbcont); box.$ext.style.top = 0; // Works around an APF bug timesliderClose.addEventListener("click", forceHideSlider); disableSelection(playButton); disableSelection(timeslider); layout.on("resize", function() { updateSliderElements(); }, plugin); slider.addEventListener("mousedown", function(evt) { if (evt.target.className == "star" && !sliderActive) onBarMouseDown(evt); }); sliderBar.addEventListener("mousedown", onBarMouseDown); handle.addEventListener("mousedown", onHandleMouseDown); playButton.addEventListener("mousedown", function(evt) { playButton.addEventListener("mouseup", function onMouseUp(evt2) { playButton.removeEventListener("mouseup", onMouseUp); playpause(); }); document.addEventListener("mouseup", function onMouseUp(evt2) { document.removeEventListener("mouseup", onMouseUp); }); }); revertButton.addEventListener("click", function() { if (!isRevertAvailable()) return console.log("Revert not available"); console.log("Revert", activeDocument.id, "to rev", sliderPos); hide(); activeDocument.revertToRevision(sliderPos); }); var steppers = [leftStep, rightStep]; steppers.forEach(function (stepper) { stepper.addEventListener("mousedown", function(evt) { var origcss = stepper.style["background-position"]; if (!origcss) origcss = stepper.style["background-position-x"].split("px")[0] + " " + stepper.style["background-position-y"].split("px")[0]; var origpos = parseInt(origcss.split(" ")[1], 10); var newpos = origpos - 43; if (newpos < 0) newpos += 87; var newcss = (origcss.split(" ")[0] + " " + newpos + "px"); if (stepper.style.opacity != 1.0) newcss = origcss; stepper.style["background-position"] = newcss; var pos, nextStar, i; stepper.addEventListener("mouseup", function onMouseUp(evt2) { stepper.style["background-position"] = origcss; stepper.removeEventListener("mouseup", onMouseUp); }); document.addEventListener("mouseup", function onMouseUp(evt2) { stepper.style["background-position"] = origcss; document.removeEventListener("mouseup", onMouseUp); }); var id = stepper.id; if (id == "leftstep") { setSliderPosition(sliderPos - 1); } else if (id == "rightstep") { setSliderPosition(sliderPos + 1); } else if (id == "leftstar") { nextStar = 0; // default to first revision in document for (i = 0; i < savedRevisionNums.length; i++) { pos = savedRevisionNums[i]; if (pos < sliderPos && nextStar < pos) nextStar = pos; } setSliderPosition(nextStar); } else if (id == "rightstar") { nextStar = sliderLength; // default to last revision in document for (i = 0; i < savedRevisionNums.length; i++) { pos = savedRevisionNums[i]; if (pos > sliderPos && nextStar > pos) nextStar = pos; } setSliderPosition(nextStar); } }); }); emit("draw"); } function disableSelection(element) { element.onselectstart = function() { return false; }; element.unselectable = "on"; element.style.MozUserSelect = "none"; element.style.cursor = "default"; } function cumulativeOffset(element) { var top = 0, left = 0; do { top += element.offsetTop || 0; left += element.offsetLeft || 0; element = element.offsetParent; } while (element); return { top: top, left: left }; } function setHandleLeft(pos) { handle.style.left = pos + "px"; sliderProgress.style.width = (pos - sliderBar.offsetLeft + 10) + "px"; } function onBarMouseDown(evt) { var newloc = evt.clientX - cumulativeOffset(sliderBar).left; var newSliderPos = Math.round(newloc * sliderLength / (sliderBar.offsetWidth - 2)); setHandleLeft(calcHandlerLeft(newSliderPos)); onHandleMouseDown(evt); } function onHandleMouseDown(evt) { var startLoc = evt.clientX; var currentLoc = parseInt(handle.style.left.split("px")[0], 10); sliderActive = true; function calcSliderPos(clientX) { var newloc = currentLoc + (clientX - startLoc) - LEFT_PADDING; if (newloc < 0) newloc = 0; var barWidth = sliderBar.offsetWidth - 2; if (newloc > barWidth) newloc = barWidth; return Math.round(newloc * sliderLength / barWidth); } function clamp(clientX) { var newloc = currentLoc + (clientX - startLoc); var handleOverflow = (handle.offsetWidth / 2); if (newloc < sliderBar.offsetLeft - handleOverflow + 1) newloc = sliderBar.offsetLeft - handleOverflow + 1; if (newloc > sliderBar.offsetLeft + sliderBar.offsetWidth - handleOverflow - 1) newloc = sliderBar.offsetLeft + sliderBar.offsetWidth - handleOverflow - 1; return newloc; } function onMouseMove(evt2) { handle.style.pointer = "move"; handle.style.transition = "none"; sliderProgress.style.transition = "none"; var newSliderPos = calcSliderPos(evt2.clientX); revisionLabel.textContent = "Version " + newSliderPos; setHandleLeft(clamp(evt2.clientX)); if (sliderPos != newSliderPos) { sliderPos = newSliderPos; emit("slider", newSliderPos); } } function onMouseUp(evt2) { document.removeEventListener("mousemove", onMouseMove); document.removeEventListener("mouseup", onMouseUp); sliderActive = false; var newSliderPos = calcSliderPos(evt2.clientX); currentLoc = calcHandlerLeft(newSliderPos); setHandleLeft(currentLoc); setSliderPosition(newSliderPos); handle.style.transition = "left .1s"; sliderProgress.style.transition = "width .1s"; } document.addEventListener("mousemove", onMouseMove); document.addEventListener("mouseup", onMouseUp); } function isRevertAvailable() { return !sliderPlaying && !sliderActive && !isLoading && activeDocument && sliderLength && sliderPos !== sliderLength; } var starWidth = 15; function updateSliderElements() { var prevX, prevStar, firstHidden; for (var i = 0; i < savedRevisions.length; i++) { var star = savedRevisions[i]; var position = parseInt(star.pos, 10); var x = calcHandlerLeft(position) - 1; if (x - prevX < 2 * starWidth) { if (prevStar) prevStar.style.opacity = 0.15; prevStar = star; if (!firstHidden) { firstHidden = x; } else if (x - firstHidden > 5 * starWidth) { firstHidden = prevStar = null; } } else { firstHidden = prevStar = null; } prevX = x; star.style.left = x + "px"; star.style.opacity = 1; } setHandleLeft(calcHandlerLeft(sliderPos)); } function addSavedRevision(revision) { var position = revision.revNum; var newSR = document.createElement("div"); newSR.className = "star"; newSR.title = "File Saved on " + dateFormat(revision.updated_at); newSR.pos = position; newSR.style.left = (calcHandlerLeft(position) - 1) + "px"; slider.appendChild(newSR); newSR.addEventListener("mouseup", function() { setSliderPosition(position); }); savedRevisions.push(newSR); savedRevisionNums.push(position); if (position === sliderPos) setSliderPosition(position); } function setSavedRevisions(revisions) { toArray(slider.getElementsByClassName("star")).forEach(function (star) { star.remove(); }); savedRevisions = []; savedRevisionNums = []; revisions.forEach(function(revision) { addSavedRevision(revision); }); } function toArray(arg) { return Array.prototype.slice.apply(arg); } function zpad(str, length) { str = str + ""; while (str.length < length) str = "0" + str; return str; } function dateFormat(time) { var date = new Date(time); var month = ["Jan", "Feb", "March", "April", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec"][date.getMonth()]; var day = zpad(date.getDate(), 2); var year = date.getFullYear(); var hours = zpad(date.getHours(), 2); var minutes = zpad(date.getMinutes(), 2); var seconds = zpad(date.getSeconds(), 2); return ([month, " ", day, ", ", year, " ", hours, ":", minutes, ":", seconds].join("")); } function updateTimer(time) { revisionDate.textContent = dateFormat(time); } function calcHandlerLeft(pos) { var left = pos * (sliderBar.offsetWidth - 2) / (sliderLength * 1.0); left = (left || 0) + LEFT_PADDING; return left; } function setSliderPosition(newpos) { newpos = Number(newpos); if (newpos < 0 || newpos > sliderLength) return; setHandleLeft(calcHandlerLeft(newpos)); if (savedRevisionNums.indexOf(newpos) === -1) { revisionLabel.textContent = "Version " + newpos; revisionLabel.className = "revision_label"; } else { revisionLabel.textContent = "Saved Version " + newpos; revisionLabel.className = "revision_label saved"; } if (newpos === 0) leftStep.className = "stepper disabled"; else leftStep.className = "stepper"; if (newpos == sliderLength) rightStep.className = "stepper disabled"; else rightStep.className = "stepper"; sliderPos = newpos; updateRevertVisibility(); emit("slider", newpos); } function updateRevertVisibility() { if (isRevertAvailable()) revertButton.className = "revert"; else revertButton.className = "revert disabled"; } function getSliderLength() { return sliderLength; } function setSliderLength(newlength) { sliderLength = newlength; updateSliderElements(); } function playButtonUpdater() { if (sliderPlaying) { if (sliderPos + 1 > sliderLength) { dom.toggleCssClass(playButtonIcon, "pause"); sliderPlaying = false; return; } setSliderPosition(sliderPos + 1); setTimeout(playButtonUpdater, 100); } } function playpause() { if (!isVisible) return console.error("[Timeslider] Can't playpause while not visible"); dom.toggleCssClass(playButtonIcon, "pause"); if (!sliderPlaying) { if (sliderPos == sliderLength) setSliderPosition(0); sliderPlaying = true; playButtonUpdater(); } else { sliderPlaying = false; updateRevertVisibility(); } } function getCodeEditorTab() { return $(".codeditorHolder .hsplitbox"); } var isVisible = false; var resizeInterval; function useStoredState(e) { if (e.state.filter && e.doc.meta.$storedState1) e.state = e.doc.meta.$storedState1; else if (!e.state.filter && e.doc.meta.$storedState0) e.state = e.doc.meta.$storedState0; } function show() { draw(); container.show(); clearInterval(resizeInterval); var oldWidth = timeslider.offsetWidth; resizeInterval = setInterval(function () { if (timeslider.offsetWidth !== oldWidth) { updateSliderElements(); oldWidth = timeslider.offsetWidth; } }, 100); isVisible = true; if (activeDocument) { var tab = activeDocument.original.tab; var aceEditor = tab.editor.ace; aceEditor.setReadOnly(true); aceEditor.keyBinding.addKeyboardHandler(timesliderKeyboardHandler); aceEditor.renderer.onResize(true); var doc = activeDocument.original; doc.meta.$storedState0 = doc.getState(); doc.meta.$storedState1 = doc.getState(true); doc.on("getState", useStoredState); } emit("visible", isVisible); } function hide() { draw(); if (sliderPlaying) playpause(); container.hide(); clearInterval(resizeInterval); isVisible = false; if (activeDocument) { if (activeDocument.loaded) activeDocument.updateToRevision(); var tab = activeDocument.original.tab; var aceEditor = tab.editor.ace; aceEditor.keyBinding.removeKeyboardHandler(timesliderKeyboardHandler); aceEditor.setReadOnly(!!c9.readonly); aceEditor.renderer.onResize(true); var doc = activeDocument.original; delete doc.meta.$storedState0; delete doc.meta.$storedState1; doc.off("getState", useStoredState); } emit("visible", isVisible); } function getTabCollabDocument(tab) { var session = tab.path && tab.document.getSession(); if (!session) return false; var aceSession = session.session; return aceSession && aceSession.collabDoc; } function toggleTimeslider() { if (isVisible) { activeDocument && activeDocument.loaded && activeDocument.updateToRevision(); lastRevNum = null; hide(); } else { show(); lastRevNum = null; activeDocument && activeDocument.loadRevisions(); } } function timesliderAvailable(editor) { if (!editor || editor.type !== "ace") return false; var aceEditor = editor.ace; var collabDoc = aceEditor.session.collabDoc; return !!collabDoc; } function forceHideSlider() { var tsVisible = isVisible || settings.getBool(tsVisibleKey); if (tsVisible) { settings.set(tsVisibleKey, false); toggleTimeslider(); } } function setLoading(loading) { if (loading === isLoading) return; isLoading = loading; if (loading) { setSavedRevisions([]); } else { } } plugin.on("load", function() { load(); }); plugin.on("enable", function() { }); plugin.on("disable", function() { }); plugin.on("unload", function() { loaded = false; drawn = false; }); plugin.freezePublicAPI({ get visible() { return isVisible; }, get loading() { return isLoading; }, set loading(value) { setLoading(value); }, get activeDocument() { return activeDocument; }, get sliderLength() { return getSliderLength(); }, set sliderLength(len) { setSliderLength(len); }, get sliderPosition() { return sliderPos; }, set sliderPosition(pos) { setSliderPosition(pos); }, updateTimer: updateTimer, setSavedRevisions: setSavedRevisions, show: show, hide: hide, playpause: playpause, addSavedRevision: addSavedRevision }); register(null, { timeslider: plugin }); } }); 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; }); define("plugins/c9.ide.threewaymerge/diff_match_patch_amd",[], function(require, exports, module) { function diff_match_patch() { this.Diff_Timeout = 1.0; this.Diff_EditCost = 4; this.Match_Threshold = 0.5; this.Match_Distance = 1000; this.Patch_DeleteThreshold = 0.5; this.Patch_Margin = 4; this.Match_MaxBits = 32; } var DIFF_DELETE = -1; var DIFF_INSERT = 1; var DIFF_EQUAL = 0; diff_match_patch.Diff; diff_match_patch.prototype.diff_main = function(text1, text2, opt_checklines, opt_deadline) { if (typeof opt_deadline == 'undefined') { if (this.Diff_Timeout <= 0) { opt_deadline = Number.MAX_VALUE; } else { opt_deadline = (new Date).getTime() + this.Diff_Timeout * 1000; } } var deadline = opt_deadline; if (text1 == null || text2 == null) { throw new Error('Null input. (diff_main)'); } if (text1 == text2) { if (text1) { return [[DIFF_EQUAL, text1]]; } return []; } if (typeof opt_checklines == 'undefined') { opt_checklines = true; } var checklines = opt_checklines; var commonlength = this.diff_commonPrefix(text1, text2); var commonprefix = text1.substring(0, commonlength); text1 = text1.substring(commonlength); text2 = text2.substring(commonlength); commonlength = this.diff_commonSuffix(text1, text2); var commonsuffix = text1.substring(text1.length - commonlength); text1 = text1.substring(0, text1.length - commonlength); text2 = text2.substring(0, text2.length - commonlength); var diffs = this.diff_compute_(text1, text2, checklines, deadline); if (commonprefix) { diffs.unshift([DIFF_EQUAL, commonprefix]); } if (commonsuffix) { diffs.push([DIFF_EQUAL, commonsuffix]); } this.diff_cleanupMerge(diffs); return diffs; }; diff_match_patch.prototype.diff_compute_ = function(text1, text2, checklines, deadline) { var diffs; if (!text1) { return [[DIFF_INSERT, text2]]; } if (!text2) { return [[DIFF_DELETE, text1]]; } var longtext = text1.length > text2.length ? text1 : text2; var shorttext = text1.length > text2.length ? text2 : text1; var i = longtext.indexOf(shorttext); if (i != -1) { diffs = [[DIFF_INSERT, longtext.substring(0, i)], [DIFF_EQUAL, shorttext], [DIFF_INSERT, longtext.substring(i + shorttext.length)]]; if (text1.length > text2.length) { diffs[0][0] = diffs[2][0] = DIFF_DELETE; } return diffs; } if (shorttext.length == 1) { return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]]; } longtext = shorttext = null; // Garbage collect. var hm = this.diff_halfMatch_(text1, text2); if (hm) { var text1_a = hm[0]; var text1_b = hm[1]; var text2_a = hm[2]; var text2_b = hm[3]; var mid_common = hm[4]; var diffs_a = this.diff_main(text1_a, text2_a, checklines, deadline); var diffs_b = this.diff_main(text1_b, text2_b, checklines, deadline); return diffs_a.concat([[DIFF_EQUAL, mid_common]], diffs_b); } if (checklines && text1.length > 100 && text2.length > 100) { return this.diff_lineMode_(text1, text2, deadline); } return this.diff_bisect_(text1, text2, deadline); }; diff_match_patch.prototype.diff_lineMode_ = function(text1, text2, deadline) { var a = this.diff_linesToChars_(text1, text2); text1 = a.chars1; text2 = a.chars2; var linearray = a.lineArray; var diffs = this.diff_main(text1, text2, false, deadline); this.diff_charsToLines_(diffs, linearray); this.diff_cleanupSemantic(diffs); diffs.push([DIFF_EQUAL, '']); var pointer = 0; var count_delete = 0; var count_insert = 0; var text_delete = ''; var text_insert = ''; while (pointer < diffs.length) { switch (diffs[pointer][0]) { case DIFF_INSERT: count_insert++; text_insert += diffs[pointer][1]; break; case DIFF_DELETE: count_delete++; text_delete += diffs[pointer][1]; break; case DIFF_EQUAL: if (count_delete >= 1 && count_insert >= 1) { diffs.splice(pointer - count_delete - count_insert, count_delete + count_insert); pointer = pointer - count_delete - count_insert; var a = this.diff_main(text_delete, text_insert, false, deadline); for (var j = a.length - 1; j >= 0; j--) { diffs.splice(pointer, 0, a[j]); } pointer = pointer + a.length; } count_insert = 0; count_delete = 0; text_delete = ''; text_insert = ''; break; } pointer++; } diffs.pop(); // Remove the dummy entry at the end. return diffs; }; diff_match_patch.prototype.diff_bisect_ = function(text1, text2, deadline) { var text1_length = text1.length; var text2_length = text2.length; var max_d = Math.ceil((text1_length + text2_length) / 2); var v_offset = max_d; var v_length = 2 * max_d; var v1 = new Array(v_length); var v2 = new Array(v_length); for (var x = 0; x < v_length; x++) { v1[x] = -1; v2[x] = -1; } v1[v_offset + 1] = 0; v2[v_offset + 1] = 0; var delta = text1_length - text2_length; var front = (delta % 2 != 0); var k1start = 0; var k1end = 0; var k2start = 0; var k2end = 0; for (var d = 0; d < max_d; d++) { if ((new Date()).getTime() > deadline) { break; } for (var k1 = -d + k1start; k1 <= d - k1end; k1 += 2) { var k1_offset = v_offset + k1; var x1; if (k1 == -d || (k1 != d && v1[k1_offset - 1] < v1[k1_offset + 1])) { x1 = v1[k1_offset + 1]; } else { x1 = v1[k1_offset - 1] + 1; } var y1 = x1 - k1; while (x1 < text1_length && y1 < text2_length && text1.charAt(x1) == text2.charAt(y1)) { x1++; y1++; } v1[k1_offset] = x1; if (x1 > text1_length) { k1end += 2; } else if (y1 > text2_length) { k1start += 2; } else if (front) { var k2_offset = v_offset + delta - k1; if (k2_offset >= 0 && k2_offset < v_length && v2[k2_offset] != -1) { var x2 = text1_length - v2[k2_offset]; if (x1 >= x2) { return this.diff_bisectSplit_(text1, text2, x1, y1, deadline); } } } } for (var k2 = -d + k2start; k2 <= d - k2end; k2 += 2) { var k2_offset = v_offset + k2; var x2; if (k2 == -d || (k2 != d && v2[k2_offset - 1] < v2[k2_offset + 1])) { x2 = v2[k2_offset + 1]; } else { x2 = v2[k2_offset - 1] + 1; } var y2 = x2 - k2; while (x2 < text1_length && y2 < text2_length && text1.charAt(text1_length - x2 - 1) == text2.charAt(text2_length - y2 - 1)) { x2++; y2++; } v2[k2_offset] = x2; if (x2 > text1_length) { k2end += 2; } else if (y2 > text2_length) { k2start += 2; } else if (!front) { var k1_offset = v_offset + delta - k2; if (k1_offset >= 0 && k1_offset < v_length && v1[k1_offset] != -1) { var x1 = v1[k1_offset]; var y1 = v_offset + x1 - k1_offset; x2 = text1_length - x2; if (x1 >= x2) { return this.diff_bisectSplit_(text1, text2, x1, y1, deadline); } } } } } return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]]; }; diff_match_patch.prototype.diff_bisectSplit_ = function(text1, text2, x, y, deadline) { var text1a = text1.substring(0, x); var text2a = text2.substring(0, y); var text1b = text1.substring(x); var text2b = text2.substring(y); var diffs = this.diff_main(text1a, text2a, false, deadline); var diffsb = this.diff_main(text1b, text2b, false, deadline); return diffs.concat(diffsb); }; diff_match_patch.prototype.diff_linesToChars_ = function(text1, text2) { var lineArray = []; // e.g. lineArray[4] == 'Hello\n' var lineHash = {}; // e.g. lineHash['Hello\n'] == 4 lineArray[0] = ''; function diff_linesToCharsMunge_(text) { var chars = ''; var lineStart = 0; var lineEnd = -1; var lineArrayLength = lineArray.length; while (lineEnd < text.length - 1) { lineEnd = text.indexOf('\n', lineStart); if (lineEnd == -1) { lineEnd = text.length - 1; } var line = text.substring(lineStart, lineEnd + 1); lineStart = lineEnd + 1; if (lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) : (lineHash[line] !== undefined)) { chars += String.fromCharCode(lineHash[line]); } else { chars += String.fromCharCode(lineArrayLength); lineHash[line] = lineArrayLength; lineArray[lineArrayLength++] = line; } } return chars; } var chars1 = diff_linesToCharsMunge_(text1); var chars2 = diff_linesToCharsMunge_(text2); return { chars1: chars1, chars2: chars2, lineArray: lineArray }; }; diff_match_patch.prototype.diff_charsToLines_ = function(diffs, lineArray) { for (var x = 0; x < diffs.length; x++) { var chars = diffs[x][1]; var text = []; for (var y = 0; y < chars.length; y++) { text[y] = lineArray[chars.charCodeAt(y)]; } diffs[x][1] = text.join(''); } }; diff_match_patch.prototype.diff_commonPrefix = function(text1, text2) { if (!text1 || !text2 || text1.charAt(0) != text2.charAt(0)) { return 0; } var pointermin = 0; var pointermax = Math.min(text1.length, text2.length); var pointermid = pointermax; var pointerstart = 0; while (pointermin < pointermid) { if (text1.substring(pointerstart, pointermid) == text2.substring(pointerstart, pointermid)) { pointermin = pointermid; pointerstart = pointermin; } else { pointermax = pointermid; } pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin); } return pointermid; }; diff_match_patch.prototype.diff_commonSuffix = function(text1, text2) { if (!text1 || !text2 || text1.charAt(text1.length - 1) != text2.charAt(text2.length - 1)) { return 0; } var pointermin = 0; var pointermax = Math.min(text1.length, text2.length); var pointermid = pointermax; var pointerend = 0; while (pointermin < pointermid) { if (text1.substring(text1.length - pointermid, text1.length - pointerend) == text2.substring(text2.length - pointermid, text2.length - pointerend)) { pointermin = pointermid; pointerend = pointermin; } else { pointermax = pointermid; } pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin); } return pointermid; }; diff_match_patch.prototype.diff_commonOverlap_ = function(text1, text2) { var text1_length = text1.length; var text2_length = text2.length; if (text1_length == 0 || text2_length == 0) { return 0; } if (text1_length > text2_length) { text1 = text1.substring(text1_length - text2_length); } else if (text1_length < text2_length) { text2 = text2.substring(0, text1_length); } var text_length = Math.min(text1_length, text2_length); if (text1 == text2) { return text_length; } var best = 0; var length = 1; while (true) { var pattern = text1.substring(text_length - length); var found = text2.indexOf(pattern); if (found == -1) { return best; } length += found; if (found == 0 || text1.substring(text_length - length) == text2.substring(0, length)) { best = length; length++; } } }; diff_match_patch.prototype.diff_halfMatch_ = function(text1, text2) { if (this.Diff_Timeout <= 0) { return null; } var longtext = text1.length > text2.length ? text1 : text2; var shorttext = text1.length > text2.length ? text2 : text1; if (longtext.length < 4 || shorttext.length * 2 < longtext.length) { return null; // Pointless. } var dmp = this; // 'this' becomes 'window' in a closure. function diff_halfMatchI_(longtext, shorttext, i) { var seed = longtext.substring(i, i + Math.floor(longtext.length / 4)); var j = -1; var best_common = ''; var best_longtext_a, best_longtext_b, best_shorttext_a, best_shorttext_b; while ((j = shorttext.indexOf(seed, j + 1)) != -1) { var prefixLength = dmp.diff_commonPrefix(longtext.substring(i), shorttext.substring(j)); var suffixLength = dmp.diff_commonSuffix(longtext.substring(0, i), shorttext.substring(0, j)); if (best_common.length < suffixLength + prefixLength) { best_common = shorttext.substring(j - suffixLength, j) + shorttext.substring(j, j + prefixLength); best_longtext_a = longtext.substring(0, i - suffixLength); best_longtext_b = longtext.substring(i + prefixLength); best_shorttext_a = shorttext.substring(0, j - suffixLength); best_shorttext_b = shorttext.substring(j + prefixLength); } } if (best_common.length * 2 >= longtext.length) { return [best_longtext_a, best_longtext_b, best_shorttext_a, best_shorttext_b, best_common]; } else { return null; } } var hm1 = diff_halfMatchI_(longtext, shorttext, Math.ceil(longtext.length / 4)); var hm2 = diff_halfMatchI_(longtext, shorttext, Math.ceil(longtext.length / 2)); var hm; if (!hm1 && !hm2) { return null; } else if (!hm2) { hm = hm1; } else if (!hm1) { hm = hm2; } else { hm = hm1[4].length > hm2[4].length ? hm1 : hm2; } var text1_a, text1_b, text2_a, text2_b; if (text1.length > text2.length) { text1_a = hm[0]; text1_b = hm[1]; text2_a = hm[2]; text2_b = hm[3]; } else { text2_a = hm[0]; text2_b = hm[1]; text1_a = hm[2]; text1_b = hm[3]; } var mid_common = hm[4]; return [text1_a, text1_b, text2_a, text2_b, mid_common]; }; diff_match_patch.prototype.diff_cleanupSemantic = function(diffs) { var changes = false; var equalities = []; // Stack of indices where equalities are found. var equalitiesLength = 0; // Keeping our own length var is faster in JS. var lastequality = null; var pointer = 0; // Index of current position. var length_insertions1 = 0; var length_deletions1 = 0; var length_insertions2 = 0; var length_deletions2 = 0; while (pointer < diffs.length) { if (diffs[pointer][0] == DIFF_EQUAL) { // Equality found. equalities[equalitiesLength++] = pointer; length_insertions1 = length_insertions2; length_deletions1 = length_deletions2; length_insertions2 = 0; length_deletions2 = 0; lastequality = diffs[pointer][1]; } else { // An insertion or deletion. if (diffs[pointer][0] == DIFF_INSERT) { length_insertions2 += diffs[pointer][1].length; } else { length_deletions2 += diffs[pointer][1].length; } if (lastequality && (lastequality.length <= Math.max(length_insertions1, length_deletions1)) && (lastequality.length <= Math.max(length_insertions2, length_deletions2))) { diffs.splice(equalities[equalitiesLength - 1], 0, [DIFF_DELETE, lastequality]); diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT; equalitiesLength--; equalitiesLength--; pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1; length_insertions1 = 0; // Reset the counters. length_deletions1 = 0; length_insertions2 = 0; length_deletions2 = 0; lastequality = null; changes = true; } } pointer++; } if (changes) { this.diff_cleanupMerge(diffs); } this.diff_cleanupSemanticLossless(diffs); pointer = 1; while (pointer < diffs.length) { if (diffs[pointer - 1][0] == DIFF_DELETE && diffs[pointer][0] == DIFF_INSERT) { var deletion = diffs[pointer - 1][1]; var insertion = diffs[pointer][1]; var overlap_length1 = this.diff_commonOverlap_(deletion, insertion); var overlap_length2 = this.diff_commonOverlap_(insertion, deletion); if (overlap_length1 >= overlap_length2) { if (overlap_length1 >= deletion.length / 2 || overlap_length1 >= insertion.length / 2) { diffs.splice(pointer, 0, [DIFF_EQUAL, insertion.substring(0, overlap_length1)]); diffs[pointer - 1][1] = deletion.substring(0, deletion.length - overlap_length1); diffs[pointer + 1][1] = insertion.substring(overlap_length1); pointer++; } } else { if (overlap_length2 >= deletion.length / 2 || overlap_length2 >= insertion.length / 2) { diffs.splice(pointer, 0, [DIFF_EQUAL, deletion.substring(0, overlap_length2)]); diffs[pointer - 1][0] = DIFF_INSERT; diffs[pointer - 1][1] = insertion.substring(0, insertion.length - overlap_length2); diffs[pointer + 1][0] = DIFF_DELETE; diffs[pointer + 1][1] = deletion.substring(overlap_length2); pointer++; } } pointer++; } pointer++; } }; diff_match_patch.prototype.diff_cleanupSemanticLossless = function(diffs) { function diff_cleanupSemanticScore_(one, two) { if (!one || !two) { return 6; } var char1 = one.charAt(one.length - 1); var char2 = two.charAt(0); var nonAlphaNumeric1 = char1.match(diff_match_patch.nonAlphaNumericRegex_); var nonAlphaNumeric2 = char2.match(diff_match_patch.nonAlphaNumericRegex_); var whitespace1 = nonAlphaNumeric1 && char1.match(diff_match_patch.whitespaceRegex_); var whitespace2 = nonAlphaNumeric2 && char2.match(diff_match_patch.whitespaceRegex_); var lineBreak1 = whitespace1 && char1.match(diff_match_patch.linebreakRegex_); var lineBreak2 = whitespace2 && char2.match(diff_match_patch.linebreakRegex_); var blankLine1 = lineBreak1 && one.match(diff_match_patch.blanklineEndRegex_); var blankLine2 = lineBreak2 && two.match(diff_match_patch.blanklineStartRegex_); if (blankLine1 || blankLine2) { return 5; } else if (lineBreak1 || lineBreak2) { return 4; } else if (nonAlphaNumeric1 && !whitespace1 && whitespace2) { return 3; } else if (whitespace1 || whitespace2) { return 2; } else if (nonAlphaNumeric1 || nonAlphaNumeric2) { return 1; } return 0; } var pointer = 1; while (pointer < diffs.length - 1) { if (diffs[pointer - 1][0] == DIFF_EQUAL && diffs[pointer + 1][0] == DIFF_EQUAL) { var equality1 = diffs[pointer - 1][1]; var edit = diffs[pointer][1]; var equality2 = diffs[pointer + 1][1]; var commonOffset = this.diff_commonSuffix(equality1, edit); if (commonOffset) { var commonString = edit.substring(edit.length - commonOffset); equality1 = equality1.substring(0, equality1.length - commonOffset); edit = commonString + edit.substring(0, edit.length - commonOffset); equality2 = commonString + equality2; } var bestEquality1 = equality1; var bestEdit = edit; var bestEquality2 = equality2; var bestScore = diff_cleanupSemanticScore_(equality1, edit) + diff_cleanupSemanticScore_(edit, equality2); while (edit.charAt(0) === equality2.charAt(0)) { equality1 += edit.charAt(0); edit = edit.substring(1) + equality2.charAt(0); equality2 = equality2.substring(1); var score = diff_cleanupSemanticScore_(equality1, edit) + diff_cleanupSemanticScore_(edit, equality2); if (score >= bestScore) { bestScore = score; bestEquality1 = equality1; bestEdit = edit; bestEquality2 = equality2; } } if (diffs[pointer - 1][1] != bestEquality1) { if (bestEquality1) { diffs[pointer - 1][1] = bestEquality1; } else { diffs.splice(pointer - 1, 1); pointer--; } diffs[pointer][1] = bestEdit; if (bestEquality2) { diffs[pointer + 1][1] = bestEquality2; } else { diffs.splice(pointer + 1, 1); pointer--; } } } pointer++; } }; diff_match_patch.nonAlphaNumericRegex_ = /[^a-zA-Z0-9]/; diff_match_patch.whitespaceRegex_ = /\s/; diff_match_patch.linebreakRegex_ = /[\r\n]/; diff_match_patch.blanklineEndRegex_ = /\n\r?\n$/; diff_match_patch.blanklineStartRegex_ = /^\r?\n\r?\n/; diff_match_patch.prototype.diff_cleanupEfficiency = function(diffs) { var changes = false; var equalities = []; // Stack of indices where equalities are found. var equalitiesLength = 0; // Keeping our own length var is faster in JS. var lastequality = null; var pointer = 0; // Index of current position. var pre_ins = false; var pre_del = false; var post_ins = false; var post_del = false; while (pointer < diffs.length) { if (diffs[pointer][0] == DIFF_EQUAL) { // Equality found. if (diffs[pointer][1].length < this.Diff_EditCost && (post_ins || post_del)) { equalities[equalitiesLength++] = pointer; pre_ins = post_ins; pre_del = post_del; lastequality = diffs[pointer][1]; } else { equalitiesLength = 0; lastequality = null; } post_ins = post_del = false; } else { // An insertion or deletion. if (diffs[pointer][0] == DIFF_DELETE) { post_del = true; } else { post_ins = true; } if (lastequality && ((pre_ins && pre_del && post_ins && post_del) || ((lastequality.length < this.Diff_EditCost / 2) && (pre_ins + pre_del + post_ins + post_del) == 3))) { diffs.splice(equalities[equalitiesLength - 1], 0, [DIFF_DELETE, lastequality]); diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT; equalitiesLength--; // Throw away the equality we just deleted; lastequality = null; if (pre_ins && pre_del) { post_ins = post_del = true; equalitiesLength = 0; } else { equalitiesLength--; // Throw away the previous equality. pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1; post_ins = post_del = false; } changes = true; } } pointer++; } if (changes) { this.diff_cleanupMerge(diffs); } }; diff_match_patch.prototype.diff_cleanupMerge = function(diffs) { diffs.push([DIFF_EQUAL, '']); // Add a dummy entry at the end. var pointer = 0; var count_delete = 0; var count_insert = 0; var text_delete = ''; var text_insert = ''; var commonlength; while (pointer < diffs.length) { switch (diffs[pointer][0]) { case DIFF_INSERT: count_insert++; text_insert += diffs[pointer][1]; pointer++; break; case DIFF_DELETE: count_delete++; text_delete += diffs[pointer][1]; pointer++; break; case DIFF_EQUAL: if (count_delete + count_insert > 1) { if (count_delete !== 0 && count_insert !== 0) { commonlength = this.diff_commonPrefix(text_insert, text_delete); if (commonlength !== 0) { if ((pointer - count_delete - count_insert) > 0 && diffs[pointer - count_delete - count_insert - 1][0] == DIFF_EQUAL) { diffs[pointer - count_delete - count_insert - 1][1] += text_insert.substring(0, commonlength); } else { diffs.splice(0, 0, [DIFF_EQUAL, text_insert.substring(0, commonlength)]); pointer++; } text_insert = text_insert.substring(commonlength); text_delete = text_delete.substring(commonlength); } commonlength = this.diff_commonSuffix(text_insert, text_delete); if (commonlength !== 0) { diffs[pointer][1] = text_insert.substring(text_insert.length - commonlength) + diffs[pointer][1]; text_insert = text_insert.substring(0, text_insert.length - commonlength); text_delete = text_delete.substring(0, text_delete.length - commonlength); } } if (count_delete === 0) { diffs.splice(pointer - count_insert, count_delete + count_insert, [DIFF_INSERT, text_insert]); } else if (count_insert === 0) { diffs.splice(pointer - count_delete, count_delete + count_insert, [DIFF_DELETE, text_delete]); } else { diffs.splice(pointer - count_delete - count_insert, count_delete + count_insert, [DIFF_DELETE, text_delete], [DIFF_INSERT, text_insert]); } pointer = pointer - count_delete - count_insert + (count_delete ? 1 : 0) + (count_insert ? 1 : 0) + 1; } else if (pointer !== 0 && diffs[pointer - 1][0] == DIFF_EQUAL) { diffs[pointer - 1][1] += diffs[pointer][1]; diffs.splice(pointer, 1); } else { pointer++; } count_insert = 0; count_delete = 0; text_delete = ''; text_insert = ''; break; } } if (diffs[diffs.length - 1][1] === '') { diffs.pop(); // Remove the dummy entry at the end. } var changes = false; pointer = 1; while (pointer < diffs.length - 1) { if (diffs[pointer - 1][0] == DIFF_EQUAL && diffs[pointer + 1][0] == DIFF_EQUAL) { if (diffs[pointer][1].substring(diffs[pointer][1].length - diffs[pointer - 1][1].length) == diffs[pointer - 1][1]) { diffs[pointer][1] = diffs[pointer - 1][1] + diffs[pointer][1].substring(0, diffs[pointer][1].length - diffs[pointer - 1][1].length); diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1]; diffs.splice(pointer - 1, 1); changes = true; } else if (diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) == diffs[pointer + 1][1]) { diffs[pointer - 1][1] += diffs[pointer + 1][1]; diffs[pointer][1] = diffs[pointer][1].substring(diffs[pointer + 1][1].length) + diffs[pointer + 1][1]; diffs.splice(pointer + 1, 1); changes = true; } } pointer++; } if (changes) { this.diff_cleanupMerge(diffs); } }; diff_match_patch.prototype.diff_xIndex = function(diffs, loc) { var chars1 = 0; var chars2 = 0; var last_chars1 = 0; var last_chars2 = 0; var x; for (x = 0; x < diffs.length; x++) { if (diffs[x][0] !== DIFF_INSERT) { // Equality or deletion. chars1 += diffs[x][1].length; } if (diffs[x][0] !== DIFF_DELETE) { // Equality or insertion. chars2 += diffs[x][1].length; } if (chars1 > loc) { // Overshot the location. break; } last_chars1 = chars1; last_chars2 = chars2; } if (diffs.length != x && diffs[x][0] === DIFF_DELETE) { return last_chars2; } return last_chars2 + (loc - last_chars1); }; diff_match_patch.prototype.diff_prettyHtml = function(diffs) { var html = []; var pattern_amp = /&/g; var pattern_lt = //g; var pattern_para = /\n/g; for (var x = 0; x < diffs.length; x++) { var op = diffs[x][0]; // Operation (insert, delete, equal) var data = diffs[x][1]; // Text of change. var text = data.replace(pattern_amp, '&').replace(pattern_lt, '<') .replace(pattern_gt, '>').replace(pattern_para, '¶
'); switch (op) { case DIFF_INSERT: html[x] = '' + text + ''; break; case DIFF_DELETE: html[x] = '' + text + ''; break; case DIFF_EQUAL: html[x] = '' + text + ''; break; } } return html.join(''); }; diff_match_patch.prototype.diff_text1 = function(diffs) { var text = []; for (var x = 0; x < diffs.length; x++) { if (diffs[x][0] !== DIFF_INSERT) { text[x] = diffs[x][1]; } } return text.join(''); }; diff_match_patch.prototype.diff_text2 = function(diffs) { var text = []; for (var x = 0; x < diffs.length; x++) { if (diffs[x][0] !== DIFF_DELETE) { text[x] = diffs[x][1]; } } return text.join(''); }; diff_match_patch.prototype.diff_levenshtein = function(diffs) { var levenshtein = 0; var insertions = 0; var deletions = 0; for (var x = 0; x < diffs.length; x++) { var op = diffs[x][0]; var data = diffs[x][1]; switch (op) { case DIFF_INSERT: insertions += data.length; break; case DIFF_DELETE: deletions += data.length; break; case DIFF_EQUAL: levenshtein += Math.max(insertions, deletions); insertions = 0; deletions = 0; break; } } levenshtein += Math.max(insertions, deletions); return levenshtein; }; diff_match_patch.prototype.diff_toDelta = function(diffs) { var text = []; for (var x = 0; x < diffs.length; x++) { switch (diffs[x][0]) { case DIFF_INSERT: text[x] = '+' + encodeURI(diffs[x][1]); break; case DIFF_DELETE: text[x] = '-' + diffs[x][1].length; break; case DIFF_EQUAL: text[x] = '=' + diffs[x][1].length; break; } } return text.join('\t').replace(/%20/g, ' '); }; diff_match_patch.prototype.diff_fromDelta = function(text1, delta) { var diffs = []; var diffsLength = 0; // Keeping our own length var is faster in JS. var pointer = 0; // Cursor in text1 var tokens = delta.split(/\t/g); for (var x = 0; x < tokens.length; x++) { var param = tokens[x].substring(1); switch (tokens[x].charAt(0)) { case '+': try { diffs[diffsLength++] = [DIFF_INSERT, decodeURI(param)]; } catch (ex) { throw new Error('Illegal escape in diff_fromDelta: ' + param); } break; case '-': case '=': var n = parseInt(param, 10); if (isNaN(n) || n < 0) { throw new Error('Invalid number in diff_fromDelta: ' + param); } var text = text1.substring(pointer, pointer += n); if (tokens[x].charAt(0) == '=') { diffs[diffsLength++] = [DIFF_EQUAL, text]; } else { diffs[diffsLength++] = [DIFF_DELETE, text]; } break; default: if (tokens[x]) { throw new Error('Invalid diff operation in diff_fromDelta: ' + tokens[x]); } } } if (pointer != text1.length) { throw new Error('Delta length (' + pointer + ') does not equal source text length (' + text1.length + ').'); } return diffs; }; diff_match_patch.prototype.match_main = function(text, pattern, loc) { if (text == null || pattern == null || loc == null) { throw new Error('Null input. (match_main)'); } loc = Math.max(0, Math.min(loc, text.length)); if (text == pattern) { return 0; } else if (!text.length) { return -1; } else if (text.substring(loc, loc + pattern.length) == pattern) { return loc; } else { return this.match_bitap_(text, pattern, loc); } }; diff_match_patch.prototype.match_bitap_ = function(text, pattern, loc) { if (pattern.length > this.Match_MaxBits) { throw new Error('Pattern too long for this browser.'); } var s = this.match_alphabet_(pattern); var dmp = this; // 'this' becomes 'window' in a closure. function match_bitapScore_(e, x) { var accuracy = e / pattern.length; var proximity = Math.abs(loc - x); if (!dmp.Match_Distance) { return proximity ? 1.0 : accuracy; } return accuracy + (proximity / dmp.Match_Distance); } var score_threshold = this.Match_Threshold; var best_loc = text.indexOf(pattern, loc); if (best_loc != -1) { score_threshold = Math.min(match_bitapScore_(0, best_loc), score_threshold); best_loc = text.lastIndexOf(pattern, loc + pattern.length); if (best_loc != -1) { score_threshold = Math.min(match_bitapScore_(0, best_loc), score_threshold); } } var matchmask = 1 << (pattern.length - 1); best_loc = -1; var bin_min, bin_mid; var bin_max = pattern.length + text.length; var last_rd; for (var d = 0; d < pattern.length; d++) { bin_min = 0; bin_mid = bin_max; while (bin_min < bin_mid) { if (match_bitapScore_(d, loc + bin_mid) <= score_threshold) { bin_min = bin_mid; } else { bin_max = bin_mid; } bin_mid = Math.floor((bin_max - bin_min) / 2 + bin_min); } bin_max = bin_mid; var start = Math.max(1, loc - bin_mid + 1); var finish = Math.min(loc + bin_mid, text.length) + pattern.length; var rd = Array(finish + 2); rd[finish + 1] = (1 << d) - 1; for (var j = finish; j >= start; j--) { var charMatch = s[text.charAt(j - 1)]; if (d === 0) { // First pass: exact match. rd[j] = ((rd[j + 1] << 1) | 1) & charMatch; } else { // Subsequent passes: fuzzy match. rd[j] = (((rd[j + 1] << 1) | 1) & charMatch) | (((last_rd[j + 1] | last_rd[j]) << 1) | 1) | last_rd[j + 1]; } if (rd[j] & matchmask) { var score = match_bitapScore_(d, j - 1); if (score <= score_threshold) { score_threshold = score; best_loc = j - 1; if (best_loc > loc) { start = Math.max(1, 2 * loc - best_loc); } else { break; } } } } if (match_bitapScore_(d + 1, loc) > score_threshold) { break; } last_rd = rd; } return best_loc; }; diff_match_patch.prototype.match_alphabet_ = function(pattern) { var s = {}; for (var i = 0; i < pattern.length; i++) { s[pattern.charAt(i)] = 0; } for (var i = 0; i < pattern.length; i++) { s[pattern.charAt(i)] |= 1 << (pattern.length - i - 1); } return s; }; diff_match_patch.prototype.patch_addContext_ = function(patch, text) { if (text.length == 0) { return; } var pattern = text.substring(patch.start2, patch.start2 + patch.length1); var padding = 0; while (text.indexOf(pattern) != text.lastIndexOf(pattern) && pattern.length < this.Match_MaxBits - this.Patch_Margin - this.Patch_Margin) { padding += this.Patch_Margin; pattern = text.substring(patch.start2 - padding, patch.start2 + patch.length1 + padding); } padding += this.Patch_Margin; var prefix = text.substring(patch.start2 - padding, patch.start2); if (prefix) { patch.diffs.unshift([DIFF_EQUAL, prefix]); } var suffix = text.substring(patch.start2 + patch.length1, patch.start2 + patch.length1 + padding); if (suffix) { patch.diffs.push([DIFF_EQUAL, suffix]); } patch.start1 -= prefix.length; patch.start2 -= prefix.length; patch.length1 += prefix.length + suffix.length; patch.length2 += prefix.length + suffix.length; }; diff_match_patch.prototype.patch_make = function(a, opt_b, opt_c) { var text1, diffs; if (typeof a == 'string' && typeof opt_b == 'string' && typeof opt_c == 'undefined') { text1 = /** @type {string} */(a); diffs = this.diff_main(text1, /** @type {string} */(opt_b), true); if (diffs.length > 2) { this.diff_cleanupSemantic(diffs); this.diff_cleanupEfficiency(diffs); } } else if (a && typeof a == 'object' && typeof opt_b == 'undefined' && typeof opt_c == 'undefined') { diffs = /** @type {!Array.} */(a); text1 = this.diff_text1(diffs); } else if (typeof a == 'string' && opt_b && typeof opt_b == 'object' && typeof opt_c == 'undefined') { text1 = /** @type {string} */(a); diffs = /** @type {!Array.} */(opt_b); } else if (typeof a == 'string' && typeof opt_b == 'string' && opt_c && typeof opt_c == 'object') { text1 = /** @type {string} */(a); diffs = /** @type {!Array.} */(opt_c); } else { throw new Error('Unknown call format to patch_make.'); } if (diffs.length === 0) { return []; // Get rid of the null case. } var patches = []; var patch = new diff_match_patch.patch_obj(); var patchDiffLength = 0; // Keeping our own length var is faster in JS. var char_count1 = 0; // Number of characters into the text1 string. var char_count2 = 0; // Number of characters into the text2 string. var prepatch_text = text1; var postpatch_text = text1; for (var x = 0; x < diffs.length; x++) { var diff_type = diffs[x][0]; var diff_text = diffs[x][1]; if (!patchDiffLength && diff_type !== DIFF_EQUAL) { patch.start1 = char_count1; patch.start2 = char_count2; } switch (diff_type) { case DIFF_INSERT: patch.diffs[patchDiffLength++] = diffs[x]; patch.length2 += diff_text.length; postpatch_text = postpatch_text.substring(0, char_count2) + diff_text + postpatch_text.substring(char_count2); break; case DIFF_DELETE: patch.length1 += diff_text.length; patch.diffs[patchDiffLength++] = diffs[x]; postpatch_text = postpatch_text.substring(0, char_count2) + postpatch_text.substring(char_count2 + diff_text.length); break; case DIFF_EQUAL: if (diff_text.length <= 2 * this.Patch_Margin && patchDiffLength && diffs.length != x + 1) { patch.diffs[patchDiffLength++] = diffs[x]; patch.length1 += diff_text.length; patch.length2 += diff_text.length; } else if (diff_text.length >= 2 * this.Patch_Margin) { if (patchDiffLength) { this.patch_addContext_(patch, prepatch_text); patches.push(patch); patch = new diff_match_patch.patch_obj(); patchDiffLength = 0; prepatch_text = postpatch_text; char_count1 = char_count2; } } break; } if (diff_type !== DIFF_INSERT) { char_count1 += diff_text.length; } if (diff_type !== DIFF_DELETE) { char_count2 += diff_text.length; } } if (patchDiffLength) { this.patch_addContext_(patch, prepatch_text); patches.push(patch); } return patches; }; diff_match_patch.prototype.patch_deepCopy = function(patches) { var patchesCopy = []; for (var x = 0; x < patches.length; x++) { var patch = patches[x]; var patchCopy = new diff_match_patch.patch_obj(); patchCopy.diffs = []; for (var y = 0; y < patch.diffs.length; y++) { patchCopy.diffs[y] = patch.diffs[y].slice(); } patchCopy.start1 = patch.start1; patchCopy.start2 = patch.start2; patchCopy.length1 = patch.length1; patchCopy.length2 = patch.length2; patchesCopy[x] = patchCopy; } return patchesCopy; }; diff_match_patch.prototype.patch_apply = function(patches, text) { if (patches.length == 0) { return [text, []]; } patches = this.patch_deepCopy(patches); var nullPadding = this.patch_addPadding(patches); text = nullPadding + text + nullPadding; this.patch_splitMax(patches); var delta = 0; var results = []; for (var x = 0; x < patches.length; x++) { var expected_loc = patches[x].start2 + delta; var text1 = this.diff_text1(patches[x].diffs); var start_loc; var end_loc = -1; if (text1.length > this.Match_MaxBits) { start_loc = this.match_main(text, text1.substring(0, this.Match_MaxBits), expected_loc); if (start_loc != -1) { end_loc = this.match_main(text, text1.substring(text1.length - this.Match_MaxBits), expected_loc + text1.length - this.Match_MaxBits); if (end_loc == -1 || start_loc >= end_loc) { start_loc = -1; } } } else { start_loc = this.match_main(text, text1, expected_loc); } if (start_loc == -1) { results[x] = false; delta -= patches[x].length2 - patches[x].length1; } else { results[x] = true; delta = start_loc - expected_loc; var text2; if (end_loc == -1) { text2 = text.substring(start_loc, start_loc + text1.length); } else { text2 = text.substring(start_loc, end_loc + this.Match_MaxBits); } if (text1 == text2) { text = text.substring(0, start_loc) + this.diff_text2(patches[x].diffs) + text.substring(start_loc + text1.length); } else { var diffs = this.diff_main(text1, text2, false); if (text1.length > this.Match_MaxBits && this.diff_levenshtein(diffs) / text1.length > this.Patch_DeleteThreshold) { results[x] = false; } else { this.diff_cleanupSemanticLossless(diffs); var index1 = 0; var index2; for (var y = 0; y < patches[x].diffs.length; y++) { var mod = patches[x].diffs[y]; if (mod[0] !== DIFF_EQUAL) { index2 = this.diff_xIndex(diffs, index1); } if (mod[0] === DIFF_INSERT) { // Insertion text = text.substring(0, start_loc + index2) + mod[1] + text.substring(start_loc + index2); } else if (mod[0] === DIFF_DELETE) { // Deletion text = text.substring(0, start_loc + index2) + text.substring(start_loc + this.diff_xIndex(diffs, index1 + mod[1].length)); } if (mod[0] !== DIFF_DELETE) { index1 += mod[1].length; } } } } } } text = text.substring(nullPadding.length, text.length - nullPadding.length); return [text, results]; }; diff_match_patch.prototype.patch_addPadding = function(patches) { var paddingLength = this.Patch_Margin; var nullPadding = ''; for (var x = 1; x <= paddingLength; x++) { nullPadding += String.fromCharCode(x); } for (var x = 0; x < patches.length; x++) { patches[x].start1 += paddingLength; patches[x].start2 += paddingLength; } var patch = patches[0]; var diffs = patch.diffs; if (diffs.length == 0 || diffs[0][0] != DIFF_EQUAL) { diffs.unshift([DIFF_EQUAL, nullPadding]); patch.start1 -= paddingLength; // Should be 0. patch.start2 -= paddingLength; // Should be 0. patch.length1 += paddingLength; patch.length2 += paddingLength; } else if (paddingLength > diffs[0][1].length) { var extraLength = paddingLength - diffs[0][1].length; diffs[0][1] = nullPadding.substring(diffs[0][1].length) + diffs[0][1]; patch.start1 -= extraLength; patch.start2 -= extraLength; patch.length1 += extraLength; patch.length2 += extraLength; } patch = patches[patches.length - 1]; diffs = patch.diffs; if (diffs.length == 0 || diffs[diffs.length - 1][0] != DIFF_EQUAL) { diffs.push([DIFF_EQUAL, nullPadding]); patch.length1 += paddingLength; patch.length2 += paddingLength; } else if (paddingLength > diffs[diffs.length - 1][1].length) { var extraLength = paddingLength - diffs[diffs.length - 1][1].length; diffs[diffs.length - 1][1] += nullPadding.substring(0, extraLength); patch.length1 += extraLength; patch.length2 += extraLength; } return nullPadding; }; diff_match_patch.prototype.patch_splitMax = function(patches) { var patch_size = this.Match_MaxBits; for (var x = 0; x < patches.length; x++) { if (patches[x].length1 <= patch_size) { continue; } var bigpatch = patches[x]; patches.splice(x--, 1); var start1 = bigpatch.start1; var start2 = bigpatch.start2; var precontext = ''; while (bigpatch.diffs.length !== 0) { var patch = new diff_match_patch.patch_obj(); var empty = true; patch.start1 = start1 - precontext.length; patch.start2 = start2 - precontext.length; if (precontext !== '') { patch.length1 = patch.length2 = precontext.length; patch.diffs.push([DIFF_EQUAL, precontext]); } while (bigpatch.diffs.length !== 0 && patch.length1 < patch_size - this.Patch_Margin) { var diff_type = bigpatch.diffs[0][0]; var diff_text = bigpatch.diffs[0][1]; if (diff_type === DIFF_INSERT) { patch.length2 += diff_text.length; start2 += diff_text.length; patch.diffs.push(bigpatch.diffs.shift()); empty = false; } else if (diff_type === DIFF_DELETE && patch.diffs.length == 1 && patch.diffs[0][0] == DIFF_EQUAL && diff_text.length > 2 * patch_size) { patch.length1 += diff_text.length; start1 += diff_text.length; empty = false; patch.diffs.push([diff_type, diff_text]); bigpatch.diffs.shift(); } else { diff_text = diff_text.substring(0, patch_size - patch.length1 - this.Patch_Margin); patch.length1 += diff_text.length; start1 += diff_text.length; if (diff_type === DIFF_EQUAL) { patch.length2 += diff_text.length; start2 += diff_text.length; } else { empty = false; } patch.diffs.push([diff_type, diff_text]); if (diff_text == bigpatch.diffs[0][1]) { bigpatch.diffs.shift(); } else { bigpatch.diffs[0][1] = bigpatch.diffs[0][1].substring(diff_text.length); } } } precontext = this.diff_text2(patch.diffs); precontext = precontext.substring(precontext.length - this.Patch_Margin); var postcontext = this.diff_text1(bigpatch.diffs) .substring(0, this.Patch_Margin); if (postcontext !== '') { patch.length1 += postcontext.length; patch.length2 += postcontext.length; if (patch.diffs.length !== 0 && patch.diffs[patch.diffs.length - 1][0] === DIFF_EQUAL) { patch.diffs[patch.diffs.length - 1][1] += postcontext; } else { patch.diffs.push([DIFF_EQUAL, postcontext]); } } if (!empty) { patches.splice(++x, 0, patch); } } } }; diff_match_patch.prototype.patch_toText = function(patches) { var text = []; for (var x = 0; x < patches.length; x++) { text[x] = patches[x]; } return text.join(''); }; diff_match_patch.prototype.patch_fromText = function(textline) { var patches = []; if (!textline) { return patches; } var text = textline.split('\n'); var textPointer = 0; var patchHeader = /^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/; while (textPointer < text.length) { var m = text[textPointer].match(patchHeader); if (!m) { throw new Error('Invalid patch string: ' + text[textPointer]); } var patch = new diff_match_patch.patch_obj(); patches.push(patch); patch.start1 = parseInt(m[1], 10); if (m[2] === '') { patch.start1--; patch.length1 = 1; } else if (m[2] == '0') { patch.length1 = 0; } else { patch.start1--; patch.length1 = parseInt(m[2], 10); } patch.start2 = parseInt(m[3], 10); if (m[4] === '') { patch.start2--; patch.length2 = 1; } else if (m[4] == '0') { patch.length2 = 0; } else { patch.start2--; patch.length2 = parseInt(m[4], 10); } textPointer++; while (textPointer < text.length) { var sign = text[textPointer].charAt(0); try { var line = decodeURI(text[textPointer].substring(1)); } catch (ex) { throw new Error('Illegal escape in patch_fromText: ' + line); } if (sign == '-') { patch.diffs.push([DIFF_DELETE, line]); } else if (sign == '+') { patch.diffs.push([DIFF_INSERT, line]); } else if (sign == ' ') { patch.diffs.push([DIFF_EQUAL, line]); } else if (sign == '@') { break; } else if (sign === '') { } else { throw new Error('Invalid patch mode "' + sign + '" in: ' + line); } textPointer++; } } return patches; }; diff_match_patch.patch_obj = function() { this.diffs = []; this.start1 = null; this.start2 = null; this.length1 = 0; this.length2 = 0; }; diff_match_patch.patch_obj.prototype.toString = function() { var coords1, coords2; if (this.length1 === 0) { coords1 = this.start1 + ',0'; } else if (this.length1 == 1) { coords1 = this.start1 + 1; } else { coords1 = (this.start1 + 1) + ',' + this.length1; } if (this.length2 === 0) { coords2 = this.start2 + ',0'; } else if (this.length2 == 1) { coords2 = this.start2 + 1; } else { coords2 = (this.start2 + 1) + ',' + this.length2; } var text = ['@@ -' + coords1 + ' +' + coords2 + ' @@\n']; var op; for (var x = 0; x < this.diffs.length; x++) { switch (this.diffs[x][0]) { case DIFF_INSERT: op = '+'; break; case DIFF_DELETE: op = '-'; break; case DIFF_EQUAL: op = ' '; break; } text[x + 1] = op + encodeURI(this.diffs[x][1]) + '\n'; } return text.join('').replace(/%20/g, ' '); }; exports.diff_match_patch = diff_match_patch; exports.DIFF_DELETE = DIFF_DELETE; exports.DIFF_INSERT = DIFF_INSERT; exports.DIFF_EQUAL = DIFF_EQUAL; }); define("plugins/c9.ide.collab/ot/operations",[], function(require, exports, module) { "use strict"; var DMP = require("../../c9.ide.threewaymerge/diff_match_patch_amd"); var diff_match_patch = DMP.diff_match_patch; var DIFF_EQUAL = DMP.DIFF_EQUAL; var DIFF_INSERT = DMP.DIFF_INSERT; var DIFF_DELETE = DMP.DIFF_DELETE; function operation(fromText, toText) { var dmp = new diff_match_patch(); var diffs = dmp.diff_main(fromText, toText); dmp.diff_cleanupSemantic(diffs); var d, type, val; var op = []; for (var i = 0; i < diffs.length; i++) { d = diffs[i]; type = d[0]; val = d[1]; switch (type) { case DIFF_EQUAL: op.push("r" + val.length); break; case DIFF_INSERT: op.push("i" + val); break; case DIFF_DELETE: op.push("d" + val); break; } } return op; } function insert(chars) { return "i" + chars; } function del(chars) { return "d" + chars; } function retain(n) { return "r" + String(n); } function type(edit) { switch (edit[0]) { case "r": return "retain"; case "d": return "delete"; case "i": return "insert"; default: throw new TypeError("Unknown type of edit: ", edit); } } function val(edit) { return type(edit) === "retain" ? ~~edit.slice(1) : edit.slice(1); } function length(edit) { return type(edit) === "retain" ? ~~edit.slice(1) : edit.length - 1; } function split(edit, idx) { if (type(edit) === "retain") { var rCount = ~~edit.slice(1); return [ "r" + idx, "r" + (rCount - idx) ]; } else { return [ edit[0] + edit.substring(1, idx + 1), edit[0] + edit.substring(idx + 1) ]; } } function pack(op) { var packed = op.slice(); var i = 0; while (i < packed.length - 1) { if (packed[i][0] === packed[i + 1][0]) packed.splice(i, 2, packed[i][0] + (val(packed[i]) + val(packed[i + 1]))); else i++; } return packed; } function inverse(op) { var edit, t, v, inversed = new Array(op.length); for (var i = 0, el = op.length; i < el; i++) { edit = op[i]; t = type(edit); v = val(edit); switch (t) { case "retain": inversed[i] = op[i]; break; case "insert": inversed[i] = del(v); break; case "delete": inversed[i] = insert(v); break; } } return inversed; } module.exports = { insert: insert, del: del, retain: retain, type: type, val: val, length: length, split: split, pack: pack, operation: operation, inverse: inverse }; }); define("plugins/c9.ide.collab/ot/author_attributes",[], function(require, exports, module) { "use strict"; var operations = require("./operations"); function AuthorAttributes(minKeySize, maxKeySize) { minKeySize = minKeySize || 20; // 4 maxKeySize = maxKeySize || (5 * minKeySize); // 8 function addValue(nodes, index, startI, length, id) { var i = startI; var len = nodes[i]; var val = nodes[i + 1]; if (index < 0 || index > len) throw new Error("Invalid index passed!"); if (val === id) { nodes[i] += length; } else if (index === len) { if (nodes[i + 3] == id) nodes[i + 2] += length; else nodes.splice(i + 2, 0, length, id); } else if (index === 0) { if (nodes[i - 1] == id) nodes[i - 2] += length; else nodes.splice(i, 0, length, id); } else { nodes.splice(i, 2, index, val, length, id, len - index, val); } } function split(parent, nodes, pos) { var splitPos = (nodes.length >> 2) << 1; var leftLen = 0, rightLen = 0; var right = nodes.splice(splitPos, splitPos + 2); for (var i = 0; i < right.length; i += 2) rightLen += right[i]; if (parent) { parent.splice(pos + 2, 0, rightLen, right); parent[pos] -= rightLen; } else { var left = nodes.splice(0, splitPos + 2); for (var i = 0; i < left.length; i += 2) leftLen += left[i]; nodes.push(leftLen, left, rightLen, right); } } function insert(nodes, index, length, id) { if (nodes.length === 0) { nodes.push(length, id); return; } var spilled = _insert(nodes, index, length, id); if (spilled) split(null, nodes, null); } function _insert(nodes, index, length, id) { for (var i = 0; i < nodes.length; i += 2) { var len = nodes[i]; if (index <= len) { var node = nodes[i + 1]; if (Array.isArray(node)) { nodes[i] += length; var spilled = _insert(node, index, length, id); if (spilled) split(nodes, nodes[i + 1], i); } else { addValue(nodes, index, i, length, id); } return nodes.length > maxKeySize; } index -= len; } } function remove(nodes, index, length) { var removedTotal = 0; for (var i = 0; i < nodes.length; i += 2) { var len = nodes[i]; // node.length var ch = nodes[i + 1]; var removed; if (index <= len) { if (Array.isArray(ch)) removed = remove(ch, index, length); else removed = Math.max(0, Math.min(length, len - index)); nodes[i] -= removed; // node.length length -= removed; removedTotal += removed; if (!nodes[i]) { nodes.splice(i, 2); i -= 2; } else if (Array.isArray(ch) && ch.length < minKeySize && (ch.length + nodes.length) <= maxKeySize) { nodes.splice.apply(nodes, [i, 2].concat(ch)); } if (!length) break; index = 0; } else { index -= len; } } for (var j = 0; j < nodes.length - 2; j += 2) { if (!nodes[j] || nodes[j + 1] !== nodes[j + 3]) continue; nodes[j] += nodes[j + 2]; nodes.splice(j + 1, 2); j -= 2; } return removedTotal; } function apply(nodes, op, authPoolId) { authPoolId = authPoolId || 0; var index = 0; var opLen; for (var i = 0; i < op.length; i++) { opLen = operations.length(op[i]); switch (operations.type(op[i])) { case "retain": index += opLen; break; case "insert": insert(nodes, index, opLen, authPoolId); index += opLen; break; case "delete": remove(nodes, index, opLen); break; default: throw new TypeError("Unknown operation: " + operations.type(op[i])); } } } function traverse(nodes, start, end, iterator) { start = start || 0; end = end || 0; if (!end) { for (var i = 0; i < nodes.length; i += 2) end += nodes[i]; } traverseRec(nodes, start, end, 0, iterator); } function traverseRec(nodes, start, end, index, iterator) { for (var i = 0; i < nodes.length && index < end; i += 2) { var len = nodes[i]; if (len > start - index) { var val = nodes[i + 1]; if (Array.isArray(val)) { traverseRec(val, start, end, index, iterator); } else if (index + len > end || index < start) { if (index < start) { len -= start - index; index = start; } len = Math.min(len, end - index); iterator(index, len, val); } else { iterator(index, len, val); } } index += len; } } function valueAtIndex(nodes, idx) { var val; traverseRec(nodes, idx, idx + 1, 0, function (index, length, value) { val = value; }); return val; } function sanityCheck(nodes) { var len = 0; for (var i = 0; i < nodes.length; i += 2) { if (Array.isArray(nodes[i + 1])) { var l1 = sanityCheck(nodes[i + 1]); len += l1; } else { len += nodes[i]; } } return len; } function flatten(nodes, result) { for (var i = 0; i < nodes.length; i += 2) { if (Array.isArray(nodes[i + 1])) { flatten(nodes[i + 1], result); } else { result.push(nodes[i], nodes[i + 1]); } } return result; } return { apply: apply, valueAtIndex: valueAtIndex, traverse: traverse, flatten: flatten, insert: insert, remove: remove }; } module.exports = AuthorAttributes; }); define("plugins/c9.ide.collab/author_layer",[], function(require, module, exports) { main.consumes = ["Plugin", "ace", "settings", "collab.workspace", "collab.util", "ui", "menus"]; main.provides = ["AuthorLayer"]; return main; function main(options, imports, register) { var Plugin = imports.Plugin; var settings = imports.settings; var ui = imports.ui; var ace = imports.ace; var util = imports["collab.util"]; var menus = imports.menus; var workspace = imports["collab.workspace"]; var dom = require("ace/lib/dom"); var event = require("ace/lib/event"); var Range = require("ace/range").Range; var AuthorAttributes = require("./ot/author_attributes")(); var showAuthorInfo = true; var showAuthorInfoKey = "user/collab/@show-author-info"; settings.on("user/collab", function () { showAuthorInfo = settings.getBool(showAuthorInfoKey); }, workspace); ace.on("create", function(e) { showAuthorInfo = settings.getBool(showAuthorInfoKey); initGutterLayer(e.editor.ace); }, workspace); menus.addItemByPath("context/ace-gutter/Gutter Options/Show Authorship Info", new ui.item({ type: "check", checked: showAuthorInfoKey }), 1000, workspace); function AuthorLayer(session) { var plugin = new Plugin("Ajax.org", main.consumes); var marker; function refresh() { if (showAuthorInfo) { session.on("changeEditor", onChangeEditor); marker = session.addDynamicMarker({ update: drawAuthInfos }, false); } else { dispose(); } var doc = session.collabDoc.original; var ace = doc.editor && doc.editor.ace; var aceSession = ace && ace.session; if (aceSession !== session) return; session._emit("changeBackMarker"); onChangeEditor({ editor: ace }); } function dispose() { marker && session.removeMarker(marker.id); session.off("changeEditor", onChangeEditor); } plugin.freezePublicAPI({ get colorPool() { return workspace.colorPool; }, refresh: refresh, dispose: dispose }); return plugin; } function onChangeEditor(e) { var renderer = (e.editor || e.oldEditor).renderer; renderer.$gutterLayer.$padding = null; renderer.$loop.schedule(renderer.CHANGE_GUTTER); if (showAuthorInfo && e.editor) { renderer.$gutterLayer.on("afterRender", decorateGutter); } else { renderer.$gutterLayer.off("afterRender", decorateGutter); clearGutterDecorations(renderer.$gutterLayer); } } function drawAuthInfos(html, markerLayer, session, config) { if (!showAuthorInfo || !util.isRealCollab(workspace)) return; var doc = session.collabDoc; var editorDoc = session.doc; var colorPool = workspace.colorPool; var reversedAuthorPool = workspace.reversedAuthorPool; var firstRow = config.firstRow; var lastRow = config.lastRow; var range = new Range(firstRow, 0, lastRow, editorDoc.getLine(lastRow).length); var cache = createAuthorKeyCache(editorDoc, doc.authAttribs, range); var authKeyCache = cache.authorKeys; var rowScores = cache.rowScores; var fold = session.getNextFoldLine(firstRow); var foldStart = fold ? fold.start.row : Infinity; for (var i = firstRow; i < lastRow; i++) { if (i > foldStart) { i = fold.end.row + 1; fold = session.getNextFoldLine(i, fold); foldStart = fold ? fold.start.row : Infinity; } if (i > lastRow) break; if (!authKeyCache[i] || !rowScores[i]) continue; var rowScore = rowScores[i]; for (var authVal in rowScore) { if (authVal == authKeyCache[i]) continue; var edits = rowScore[authVal].edits; for (var j = 0; j < edits.length; j++) { var edit = edits[j]; var uid = reversedAuthorPool[authVal]; var bgColor = colorPool[uid]; var extraStyle = "position:absolute;border-bottom:solid 2px " + util.formatColor(bgColor) + ";z-index: 2000"; var startPos = session.documentToScreenPosition(edit.pos); markerLayer.drawSingleLineMarker(html, new Range(startPos.row, startPos.column, startPos.row, startPos.column + edit.length), "", config, 0, extraStyle); } } } } function decorateGutter(e, gutter) { var session = gutter.session; var editorDoc = session.doc; var doc = session.collabDoc; var isCollabGutter = doc && showAuthorInfo && util.isRealCollab(workspace); if (!isCollabGutter) return; var config = gutter.config; var range = new Range(config.firstRow, 0, config.lastRow, Number.MAX_VALUE); var authorKeysCache = isCollabGutter && createAuthorKeyCache(editorDoc, doc.authAttribs, range).authorKeys; var colorPool = workspace.colorPool; var reversedAuthorPool = workspace.reversedAuthorPool; var cells = gutter.$lines.cells; for (var i = 0; i < cells.length; i++) { var cell = cells[i]; var authorKey = authorKeysCache[cell.row]; var authorColor = "transparent"; var fullname = null; if (authorKey) { var uid = reversedAuthorPool[authorKey]; authorColor = util.formatColor(colorPool[uid]); var user = workspace.users[uid]; fullname = user && user.fullname; } cell.element.style.borderLeft = "solid 5px " + authorColor; cell.element.setAttribute("uid", fullname ? uid : ""); } } function clearGutterDecorations(gutter) { gutter.$lines.cellCache.length = 0; var cells = gutter.$lines.cells; for (var i = 0; i < cells.length; i++) { var cell = cells[i]; cell.element.style.borderLeft = ""; cell.element.setAttribute("uid", ""); } } function createAuthorKeyCache(editorDoc, authAttribs, range) { var startI = editorDoc.positionToIndex(range.start); var endI = editorDoc.positionToIndex(range.end); var authKeyCache = {}; var rowScores = {}; var lastPos = range.start; function processScore(index, length, value) { var line = editorDoc.getLine(lastPos.row); var rowScore = rowScores[lastPos.row] = rowScores[lastPos.row] || {}; var score = Math.min(line.length - lastPos.column, length); var scoreObj = rowScore[value] = rowScore[value] || { edits: [], score: 0 }; scoreObj.edits.push({ pos: lastPos, length: score }); scoreObj.score += score; var pos = editorDoc.indexToPosition(index + length); if (lastPos.row !== pos.row) { if (value) { for (var i = lastPos.row + 1; i < pos.row; i++) authKeyCache[i] = value; } line = editorDoc.getLine(pos.row); rowScore = rowScores[pos.row] = rowScores[pos.row] || {}; score = pos.column; scoreObj = rowScore[value] = rowScore[value] || { edits: [], score: 0 }; scoreObj.edits.push({ pos: pos, length: score }); scoreObj.score += score; } lastPos = pos; } AuthorAttributes.traverse(authAttribs, startI, endI, processScore); for (var rowNum in rowScores) { var rowScore = rowScores[rowNum]; delete rowScore[null]; delete rowScore[undefined]; delete rowScore[0]; var authorKeys = Object.keys(rowScore); if (authorKeys.length === 0) { delete rowScores[rowNum]; } else if (authorKeys.length === 1) { authKeyCache[rowNum] = parseInt(authorKeys[0], 10); } else { var biggestScore = 0; var authKey; for (var key in rowScore) { if (rowScore[key].score > biggestScore) { biggestScore = rowScore[key].score; authKey = key; } } authKeyCache[rowNum] = parseInt(authKey, 10); } } return { authorKeys: authKeyCache, rowScores: rowScores }; } function getLineAuthorKey(session, authAttribs, row) { var editorDoc = session.doc; var line = editorDoc.getLine(row); var lineStart = editorDoc.positionToIndex({ row: row, column: 0 }) - 1; var lineEnd = lineStart + line.length + 1; var scores = {}; AuthorAttributes.traverse(authAttribs, lineStart, lineEnd, function (index, length, value) { if (value) scores[value] = (scores[value] || 0) + length; }); var authorKeys = Object.keys(scores); if (authorKeys.length === 0) return null; if (authorKeys.length === 1) return parseInt(authorKeys[0], 10); var biggestScore = 0; var authorKey; for (var key in scores) { if (scores[key] > biggestScore) { biggestScore = scores[key]; authorKey = key; } } return parseInt(authorKey, 10); } function initGutterLayer(editor) { if (!editor || editor.$authorGutterInited) return; editor.$authorGutterInited = true; var highlightedCell; var tooltip = editor.tooltip = dom.createElement("div"); tooltip.className = "ace_gutter-tooltip"; tooltip.style.display = "none"; editor.container.appendChild(tooltip); function onGutterMouseout(e) { tooltip.style.display = "none"; highlightedCell = null; } var gutterEl = editor.renderer.$gutter; event.addListener(gutterEl, "mouseout", onGutterMouseout); gutterEl.addEventListener("mousemove", function(e) { if (!showAuthorInfo || !util.isRealCollab(workspace)) return; var target = e.target; if (highlightedCell != target) { var uid = target.getAttribute("uid"); if (uid) { tooltip.style.display = "block"; highlightedCell = target; var user = workspace.users[uid]; tooltip.textContent = user ? user.fullname : ""; } } if (highlightedCell) { tooltip.style.top = e.clientY - 15 + "px"; tooltip.style.left = e.clientX + "px"; } else { onGutterMouseout(); } }); var mousePos; editor.addEventListener("mousemove", function(e) { if (!showAuthorInfo || !util.isRealCollab(workspace)) return; mousePos = { x: e.x, y: e.y }; if (!editor.authorTooltipTimeout) editor.authorTooltipTimeout = setTimeout(updateTooltip, tooltip.style.display === "block" ? 100 : 300); }); editor.renderer.container.addEventListener("mouseout", function(e) { tooltip.style.display = "none"; }); function updateTooltip() { editor.authorTooltipTimeout = null; var session = editor.session; var otDoc = session.collabDoc; if (!otDoc) return; var editorDoc = session.doc; var authAttribs = otDoc.authAttribs; var screenPos = editor.renderer.pixelToScreenCoordinates(mousePos.x, mousePos.y); var docPos = session.screenToDocumentPosition(screenPos.row, screenPos.column); var line = editorDoc.getLine(docPos.row); var hoverIndex = editorDoc.positionToIndex({ row: docPos.row, column: docPos.column }); var authorKey = AuthorAttributes.valueAtIndex(authAttribs, hoverIndex); if (!authorKey || line.length <= screenPos.column || editorDoc.$lines.length < screenPos.row) return tooltip.style.display = "none"; var lineOwnerKey = getLineAuthorKey(session, authAttribs, docPos.row); if (!lineOwnerKey || lineOwnerKey === authorKey) return tooltip.style.display = "none"; var reversedAuthorPool = workspace.reversedAuthorPool; var uid = reversedAuthorPool[authorKey]; var fullname = workspace.users[uid] && workspace.users[uid].fullname; tooltip.style.display = "block"; tooltip.textContent = fullname; tooltip.style.top = mousePos.y + 10 + "px"; tooltip.style.left = mousePos.x + 10 + "px"; } editor.addEventListener("mousewheel", function documentScroll() { clearTimeout(editor.authorTooltipTimeout); delete editor.authorTooltipTimeout; tooltip.style.display = "none"; }); } register(null, { AuthorLayer: AuthorLayer }); } }); define("ace/range_list",[], function(require, exports, module) { "use strict"; var Range = require("./range").Range; var comparePoints = Range.comparePoints; var RangeList = function() { this.ranges = []; }; (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.$insertRight) { } 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.$insertRight) { 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) { r.end.row = startRow; r.end.column = start.column; } if (r.start.row < endRow || r.start.row == endRow && r.start.column <= end.colum) { r.start.row = startRow; r.start.column = start.column; } 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; } } 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; } } } } 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; }); define("plugins/c9.ide.collab/cursor_layer",[], function(require, module, exports) { main.consumes = ["Plugin", "ace", "settings", "tabManager", "collab.util", "collab.workspace", "timeslider", "ui"]; main.provides = ["CursorLayer"]; return main; function main(options, imports, register) { var settings = imports.settings; var Plugin = imports.Plugin; var ace = imports.ace; var ui = imports.ui; var tabs = imports.tabManager; var util = imports["collab.util"]; var workspace = imports["collab.workspace"]; var timeslider = imports.timeslider; var operations = require("./ot/operations"); var Range = require("ace/range").Range; var RangeList = require("ace/range_list").RangeList; ace.on("create", function(e) { initTooltipEvents(e.editor.ace); }, workspace); function CursorLayer(session) { var plugin = new Plugin("Ajax.org", main.consumes); var tsRevNum; var tooltipIsOpen = false; var selections = {}; session.addDynamicMarker({ update: drawTimeSliderOperation }, false); function updateSelections(selecs) { dispose(); for (var clientId in selecs) updateSelection(selecs[clientId]); } function drawCursor(pos, html, markerLayer, session, config, bgColor) { var top = markerLayer.$getTop(pos.row, config); var left = Math.round(markerLayer.$padding + pos.column * config.characterWidth); markerLayer.elt( "ace_collab_cursor", "height:" + config.lineHeight + "px;" + "width:" + 2 + "px;" + "top:" + top + "px;" + "left:" + left + "px;" + "background-color:" + util.formatColor(bgColor) + ";" ); } function drawSelections(html, markerLayer, session, config) { if (timeslider.visible) return; var ranges = this.rangeList.ranges; var screenRanges = []; var bgColor = workspace.colorPool[this.uid]; if (!bgColor) return console.error("[OT] selection can't find user's bg color"); for (var i = 0; i < ranges.length; i++) { var range = ranges[i]; if (range.end.row < config.firstRow) continue; else if (range.start.row > config.lastRow) break; var screenRange = range.toScreenRange(session); screenRanges.push(screenRange); renderRange(html, markerLayer, session, config, screenRange, bgColor); var cursor = screenRange[range.cursor == range.start ? "start" : "end"]; drawCursor(cursor, html, markerLayer, session, config, bgColor); } this.screenRanges = screenRanges; } function drawTimeSliderOperation(html, markerLayer, session, config) { if (!timeslider.visible) return; var revNum = timeslider.sliderPosition; if (!revNum) return; var doc = session.collabDoc; var revision = doc.revisions[revNum]; if (!revision) return; var uid = revision.author; var bgColor; var editorDoc = session.doc; if (uid == 0) bgColor = { r: 150, g: 150, b: 150 }; else bgColor = workspace.colorPool[uid]; if (!bgColor) return console.error("[OT] timeslider can't find user's bg color"); var ops = revision.operation; var index = 0; for (var i = 0; i < ops.length; i++) { var len = operations.length(ops[i]); var type = operations.type(ops[i]); switch (type) { case "retain": index += len; break; case "insert": renderInsert(index, len); index += len; break; case "delete": scrollToEdit(editorDoc.indexToPosition(index)); break; default: throw new TypeError("Unknown operation: " + type); } } function scrollToEdit(pos) { if (tsRevNum === revNum) return; tabs.open({ path: doc.id, document: { ace: { jump: { row: pos.row, column: pos.column } } } }, function () {}); tsRevNum = revNum; } function renderInsert(index, length) { var startPos = editorDoc.indexToPosition(index); scrollToEdit(startPos); var endPos = editorDoc.indexToPosition(index + length); var screenRange = Range.fromPoints(startPos, endPos).toScreenRange(session); renderRange(html, markerLayer, session, config, screenRange, bgColor); } } function renderRange(html, markerLayer, session, config, screenRange, bgColor) { var className = "ace_selection"; var selectStyle = settings.get("user/ace/@selectionStyle"); var selectionStyle = "background-color:" + util.formatColor(bgColor, 0.25) + ";" + "z-index:10;"; if (screenRange.isMultiLine()) { if (selectStyle === "line") markerLayer.drawMultiLineMarker(html, screenRange, className, config, selectionStyle); else markerLayer.drawTextMarker(html, screenRange, className, config, selectionStyle); } else if (!screenRange.isEmpty()) { markerLayer.drawSingleLineMarker(html, screenRange, className, config, 0, selectionStyle); } } function dataToRangeList(data, rangeList) { if (typeof data[0] != "object") data = [data]; rangeList.ranges = data.map(function(d) { var r = new Range(d[0], d[1], d[2], d[3]); r.cursor = r[d[4] ? "start" : "end"]; return r; }); return rangeList; } function updateSelection(data) { if (!session) return; var sel = selections[data.clientId]; if (!sel) { sel = { update: drawSelections, uid: data.userId, clientId: data.clientId, rangeList: new RangeList() }; sel.rangeList.$insertRight = true; sel.rangeList.attach(session); session.addDynamicMarker(sel, false); selections[data.clientId] = sel; } if (data.selection) { dataToRangeList(data.selection, sel.rangeList); session._emit("changeBackMarker"); } } function clearSelection(clientId) { var selection = selections[clientId]; if (!selection) return; if (selection.tooltip) { document.body.removeChild(selection.tooltip); delete selection.tooltip; } if (selection.arrow) { document.body.removeChild(selection.arrow); delete selection.arrow; } if (selection.id) session.removeMarker(selection.id); selection.rangeList.detach(); delete selections[clientId]; } function hideTooltip(selection) { if (!selection || !selection.tooltipIsOpen || !selection.tooltip) return; selection.tooltip.style.display = "none"; selection.arrow.style.display = "none"; selection.tooltipIsOpen = false; } function hideAllTooltips() { for (var clientId in selections) hideTooltip(selections[clientId]); tooltipIsOpen = false; } function drawTooltip(selection, fullname) { var html = ui.buildDom([ ["div", { class: "cool_tooltip_cursor", style: "display:none" }, ["span", { class: "cool_tooltip_cursor_caption" }, fullname] ], ["div", { class: "cool_tooltip_cursor_arrow", style: "display:none" }] ], document.body); selection.tooltip = html[0]; selection.arrow = html[1]; } function showTooltip(selection, user, coords) { if (!selection.tooltip) { var uid = selection.uid; var userObj = workspace.users[uid]; if (!userObj) return; drawTooltip(selection, userObj.fullname); } selection.tooltip.style.display = selection.arrow.style.display = ""; var x = (coords.pageX - 11); var y = (coords.pageY - 15); selection.arrow.style.top = y + "px"; selection.arrow.style.left = x + "px"; selection.tooltip.style.top = (y - 21) + "px"; selection.tooltip.style.left = (coords.pageX - (selection.arrow.offsetHeight ? selection.tooltip.offsetWidth / 2 : 0)) + "px"; var color = session.collabDoc.authorLayer.colorPool[selection.uid]; selection.tooltip.style.backgroundColor = util.formatColor(color); tooltipIsOpen = selection.tooltipIsOpen = true; } function dispose() { for (var clientId in selections) clearSelection(clientId); } function setInsertRight(clientId, val) { var selection = selections[clientId]; if (selection) selection.rangeList.$insertRight = val; } plugin.freezePublicAPI({ get selections() { return selections; }, get tooltipIsOpen() { return tooltipIsOpen; }, updateSelection: updateSelection, updateSelections: updateSelections, clearSelection: clearSelection, setInsertRight: setInsertRight, hideTooltip: hideTooltip, hideAllTooltips: hideAllTooltips, showTooltip: showTooltip, dispose: dispose }); return plugin; } var editorTooltipIsOpen = false; var cursorTooltipTimeout; function initTooltipEvents(editor) { if (editor.$cursorTooltipsInited) return; editor.$cursorTooltipsInited = true; var mousePos; editor.addEventListener("mousemove", function(e) { mousePos = { x: e.x, y: e.y }; if (!cursorTooltipTimeout) cursorTooltipTimeout = setTimeout(updateTooltips, editorTooltipIsOpen ? 100 : 300); }); editor.renderer.container.addEventListener("mouseout", function(e) { mousePos = { x: e.clientX, y: e.clientY }; if (!cursorTooltipTimeout) cursorTooltipTimeout = setTimeout(updateTooltips, 100); }); editor.addEventListener("mousewheel", function() { clearTimeout(cursorTooltipTimeout); cursorTooltipTimeout = null; var collabDoc = editor.session.collabDoc; var cursorLayer = collabDoc && collabDoc.cursorLayer; if (cursorLayer && cursorLayer.tooltipIsOpen) cursorLayer.hideAllTooltips(); }); function updateTooltips() { cursorTooltipTimeout = null; var collabDoc = editor.session.collabDoc; if (!collabDoc || !collabDoc.loaded || timeslider.visible) return; var cursorLayer = collabDoc.cursorLayer; var renderer = editor.renderer; var canvasPos = renderer.scroller.getBoundingClientRect(); var screenPos = renderer.pixelToScreenCoordinates(mousePos.x, mousePos.y); function screenToPixelPos(pos) { var x = renderer.$padding + Math.round(pos.column * renderer.characterWidth); var y = pos.row * renderer.lineHeight; x -= renderer.scrollLeft; y -= renderer.scrollTop; x = Math.max(Math.min(x, canvasPos.width), 0); y = Math.max(Math.min(y, canvasPos.height), 0); return { pageX: canvasPos.left + x, pageY: canvasPos.top + y }; } function findTooltipPos(range) { var start = range.start; var end = range.end; if (range.isEmpty()) { if (screenPos.row != end.row) return; if (Math.abs(screenPos.column - end.column) <= 1) return end; return; } if (screenPos.row > end.row || screenPos.row < start.row) return; if (screenPos.row == end.row && screenPos.column > end.column) return; if (screenPos.row == start.row && screenPos.column < start.column) return; var d1 = screenPos.row - start.row + 0.8 * Math.abs(screenPos.column - start.column); var d2 = - screenPos.row + end.row + 0.8 * Math.abs(screenPos.column - end.column); return d1 < d2 ? start : end; } var clientId, tooltipIsOpen; var selections = cursorLayer ? cursorLayer.selections : {}; for (clientId in selections) { var selection = selections[clientId]; var user = workspace.users[selection.uid]; if (!selection || !user) continue; if (selection.tooltipIsOpen && onTooltip(selection.tooltip, mousePos)) { tooltipIsOpen = true; continue; } var tooltipPos; var screenRanges = selection.screenRanges || []; for (var i = screenRanges.length; i--;) { tooltipPos = findTooltipPos(screenRanges[i]); if (tooltipPos) break; } if (tooltipPos) { tooltipIsOpen = true; cursorLayer.showTooltip(selection, user, screenToPixelPos(tooltipPos)); } else if (selection.tooltipIsOpen) { cursorLayer.hideTooltip(selection); } } editorTooltipIsOpen = tooltipIsOpen; } function onTooltip(tooltipNode, coords) { if (!tooltipNode) return false; var pos = apf.getAbsolutePosition(tooltipNode); if (coords.x < pos[0] || coords.y < pos[1] || coords.x > tooltipNode.offsetWidth + pos[0] - 10 || coords.y > tooltipNode.offsetHeight + pos[1] + 25) return false; return true; } } function selectionToData(selection) { var data; if (selection.rangeCount) { data = selection.rangeList.ranges.map(function(r) { return [r.start.row, r.start.column, r.end.row, r.end.column, r.cursor == r.start]; }); } else { var r = selection.getRange(); data = [r.start.row, r.start.column, r.end.row, r.end.column, selection.isBackwards()]; } return data; } CursorLayer.selectionToData = selectionToData; register(null, { CursorLayer: CursorLayer }); } }); define("plugins/c9.ide.collab/ot/xform",[], function(require, exports, module) { "use strict"; var ops = require("./operations"); // // // var xformTable = {}; function join (a, b) { return a + "," + b; } function defXformer (typeA, typeB, xformer) { xformTable[join(typeA, typeB)] = xformer; } defXformer("retain", "retain", function (editA, editB, k) { var retainBoth = Math.min(ops.val(editA), ops.val(editB)); k(ops.retain(retainBoth), ops.retain(retainBoth), retainBoth, retainBoth); }); defXformer("delete", "delete", function (editA, editB, k) { var valA = ops.val(editA); var valB = ops.val(editB); var toDelete; if (valA.length <= valB.length && valB.substring(0, valA.length) === valA) toDelete = valA.length; else if (valB.length < valA.length && valA.substring(0, valB.length) === valB) toDelete = valB.length; if (toDelete) k(null, null, toDelete, toDelete); else throw new TypeError("Document state mismatch: delete(" + valA + ") !== delete(" + valB + ")"); }); defXformer("insert", "insert", function (editA, editB, k) { var lenA = editA.length - 1; k(editA, ops.retain(lenA), lenA, 0); }); defXformer("retain", "delete", function (editA, editB, k) { var lenA = ops.val(editA); var lenB = editB.length - 1; if (lenA < lenB) k(null, ops.del(editB.substring(1, lenA + 1)), lenA, lenA); else k(null, editB, lenB, lenB); }); defXformer("delete", "retain", function (editA, editB, k) { var lenA = editA.length - 1; var lenB = ops.val(editB); if (lenB < lenA) k(ops.del(editA.substring(1, lenB + 1)), null, lenB, lenB); else k(editA, null, lenA, lenA); }); defXformer("insert", "retain", function (editA, editB, k) { var lenA = editA.length - 1; k(editA, ops.retain(lenA), lenA, 0); }); defXformer("retain", "insert", function (editA, editB, k) { var lenB = editB.length - 1; k(ops.retain(lenB), editB, 0, lenB); }); defXformer("insert", "delete", function (editA, editB, k) { var lenA = editA.length - 1; k(editA, ops.retain(lenA), lenA, 0); }); defXformer("delete", "insert", function (editA, editB, k) { var lenB = editB.length - 1; k(ops.retain(lenB), editB, 0, lenB); }); module.exports = function (operationA, operationB, k) { var operationAPrime = []; var operationBPrime = []; var opIndexA = 0; var opIndexB = 0; var editA = operationA[0]; var editB = operationB[0]; var xformer; function kk (aPrime, bPrime, addIndexA, addIndexB) { editA = ops.split(editA, addIndexA)[1]; if (!ops.length(editA)) editA = operationA[++opIndexA]; editB = ops.split(editB, addIndexB)[1]; if (!ops.length(editB)) editB = operationB[++opIndexB]; if (aPrime) operationAPrime.push(aPrime); if (bPrime) operationBPrime.push(bPrime); } while (editA && editB) { xformer = xformTable[join(ops.type(editA), ops.type(editB))]; if (xformer) xformer(editA, editB, kk); else throw new TypeError("Unknown combination to transform: " + join(ops.type(editA), ops.type(editB))); } while (editA) { operationAPrime.push(editA); operationBPrime.push(ops.retain(ops.length(editA))); editA = operationA[++opIndexA]; } while (editB) { operationBPrime.push(editB); operationAPrime.push(ops.retain(ops.length(editB))); editB = operationB[++opIndexB]; } return k(ops.pack(operationAPrime), ops.pack(operationBPrime)); }; }); define("plugins/c9.ide.collab/ot/apply",[], function(require, exports, module) { "use strict"; var operations = require("./operations"); var Range = require("ace/range").Range; function OTError(expected, actual) { var err = new Error("OT removed text mismatch"); err.expected = expected; err.actual = actual; err.code = "EMISMATCH"; return err; } exports.applyContents = function(op, doc) { var val, newDoc = ""; for (var i = 0, len = op.length; i < len; i += 1) { val = op[i].slice(1); switch (op[i][0]) { case "r": // retain val = Number(val); if (doc.length < val) throw new Error("Could not call retain in ApplyContents doc length: " + doc.length + ", retain length: " + val); newDoc += doc.slice(0, val); doc = doc.slice(val); break; case "i": // insert newDoc += val; break; case "d": // delete if (doc.indexOf(val) !== 0) throw new OTError(val, doc.slice(0, 10)); else doc = doc.slice(val.length); break; default: throw new TypeError("Unknown operation: " + operations.type(op[i])); } } return newDoc; }; exports.applyAce = function(op, editorDoc) { var i, len, index = 0, text = ""; for (i = 0, len = op.length; i < len; i += 1) { switch (operations.type(op[i])) { case "retain": index += operations.val(op[i]); break; case "insert": text = operations.val(op[i]); editorDoc.insert(editorDoc.indexToPosition(index, false, true), text); index += text.length; break; case "delete": text = operations.val(op[i]); var startDel = editorDoc.indexToPosition(index, false, true); var endDel = editorDoc.indexToPosition(index + text.length, false, true); var range = Range.fromPoints(startDel, endDel); var docText = editorDoc.getTextRange(range); if (docText !== text) { throw new OTError(text, docText); } editorDoc.remove(range); break; default: throw new TypeError("Unknown operation: " + operations.type(op[i])); } } }; }); define("plugins/c9.ide.collab/ot/index_cache",[], function(require, exports, module) { "use strict"; function IndexCache(doc) { if (doc.indexToPositionSlow) return; doc.icache = []; doc.rcache = []; doc.on("change", function(delta) { var row = delta.start.row; doc.icache.splice(row, doc.icache.length); for (var i = doc.rcache.length; i--;) { if (doc.rcache[i].row >= row) doc.rcache.splice(i, 1); } }, true); doc.indexToPositionSlow = doc.indexToPosition; doc.indexToPosition = function(index, startRow, check) { if (startRow) return doc.indexToPositionSlow(index, startRow); var startIndex = 0; startRow = 0; var rcache = doc.rcache; for (var i = rcache.length; i--;) { if (rcache[i].index <= index && doc.rcache[i].row > startRow) { startRow = rcache[i].row; startIndex = rcache[i].index; } } var pos = doc.indexToPositionSlow(index - startIndex, startRow); if (startRow - pos.row > 10) rcache.push({ row: pos.row, index: index - pos.column }); if (rcache.length > 20) rcache.unshift(); if (check) { var slowPos = doc.indexToPositionSlow(index); if (slowPos.row !== pos.row && slowPos.column !== pos.column) reportError("Inconsistency in indexToPosition"); return slowPos; } return pos; }; doc.positionToIndexSlow = doc.positionToIndex; doc.positionToIndex = function(pos, startRow, check) { if (startRow) return doc.positionToIndexSlow(pos, startRow); return this.rowToIndex(pos.row, check) + pos.column; }; doc.rowToIndex = function(row, check) { var lines = this.$lines || this.getAllLines(); var newlineLength = this.getNewLineCharacter().length; var index = 0; var icache = this.icache; row = Math.min(row, lines.length); for (var i = row - 1; i >= 0; i--) { if (icache[i]) { index += icache[i]; break; } index += lines[i].length + newlineLength; } if (row > 0)icache[row - 1] = index; if (check) { var slowIndex = doc.positionToIndexSlow({ row: row, column: 0 }); if (slowIndex !== index) reportError("Inconsistency in rowToIndex"); return slowIndex; } return index; }; function reportError(exception) { if (!exception.stack) exception = new Error(exception); setTimeout(function() { throw exception; }); } } module.exports = IndexCache; }); define("plugins/c9.ide.collab/ot/document",[], function(require, module, exports) { main.consumes = [ "Plugin", "ace", "util", "apf", "collab.connect", "collab.util", "collab.workspace", "timeslider", "CursorLayer", "AuthorLayer", "error_handler", "vfs.log" ]; main.provides = ["OTDocument"]; return main; function main(options, imports, register) { var Plugin = imports.Plugin; var connect = imports["collab.connect"]; var c9Util = imports.util; var collabUtil = imports["collab.util"]; var apf = imports.apf; var workspace = imports["collab.workspace"]; var timeslider = imports.timeslider; var CursorLayer = imports.CursorLayer; var AuthorLayer = imports.AuthorLayer; var errorHandler = imports.error_handler; var logger = imports["vfs.log"]; var lang = require("ace/lib/lang"); var xform = require("./xform"); var operations = require("./operations"); var apply = require("./apply"); var applyContents = apply.applyContents; var applyAce = apply.applyAce; var IndexCache = require("./index_cache"); var applyAuthorAttributes = require("./author_attributes")().apply; var MIN_DELAY = options.minDelay; var MAX_DELAY = options.maxDelay; var MAX_COMMIT_TRIALS = 20; var COLLAB_SAVE_FILE_TIMEOUT = 5000; var MAX_OP_SIZE = 1024 * 1024; function OTDocument(docId, c9Document) { var plugin = new Plugin("Ajax.org", main.consumes); var emit = plugin.getEmitter(); var cloneObject = c9Util.cloneObject; var debug = connect.debug; var doc, session; var docStream, revStream; var cursorLayer, authorLayer; var revCache, rev0Cache; var revisions, starRevNums; var latestRevNum, lastSel; var commitTrials; var sendTimer, cursorTimer, saveTimer; var incoming, outgoing; var ignoreChanges; var packedCs; var loaded, loading, inited; var state; var stateWhenSaveCalled, saveStateDebugging; // Debug variables, for tracking down errors in prod var pendingSave; var readonly; var reqId; var rejoinReason; resetState(); function resetState() { if (session) { session.off("change", handleUserChanges); session.off("changeEditor", onChangeEditor); session.selection.off("changeCursor", onCursorChange); session.selection.off("changeSelection", onCursorChange); session.selection.off("addRange", onCursorChange); } if (inited) { cursorLayer.dispose(); authorLayer.dispose(); } docStream = revStream = undefined; revCache = rev0Cache = lastSel = undefined; clearTimeout(sendTimer); clearTimeout(cursorTimer); endSaveWatchDog(); sendTimer = cursorTimer = undefined; commitTrials = 0; incoming = []; outgoing = []; packedCs = []; revisions = []; starRevNums = []; loaded = loading = inited = ignoreChanges = false; state = "IDLE"; emit.unsticky("joined"); } function setSession(aceSession) { if (!aceSession) return console.warn("[OT] setSession null aceSession!"); if (session) return console.warn("[OT] Ace's session previously set!"); session = aceSession; session.collabDoc = plugin; var aceDoc = session.doc; IndexCache(aceDoc); aceDoc.oldSetValue = aceDoc.oldSetValue || aceDoc.setValue; aceDoc.setValue = patchedSetValue; aceDoc.getNewLineCharacter = patchedGetNewLineCharacter; if (loaded) joinWithSession(); incoming.forEach(handleMessage); incoming = []; session.on("change", handleUserChanges); session.on("changeEditor", onChangeEditor); session.selection.on("changeCursor", onCursorChange); session.selection.on("changeSelection", onCursorChange); session.selection.on("addRange", onCursorChange); } function patchedSetValue(text) { var prev = this.getValue(); if (!prev) return this.oldSetValue(text); text = collabUtil.normalizeTextLT(text); applyAce(operations.operation(prev, text), this); } function patchedGetNewLineCharacter() { return "\n"; } function handleUserChanges(delta) { session._emit("changeBackMarker"); if (!inited || ignoreChanges) return; try { var aceDoc = session.doc; packedCs = handleUserChanges2(aceDoc, packedCs, delta); scheduleSend(); } catch (ex) { reportError(ex, { data: delta }); rejoin("E_EDIT_UPDATE"); } } function handleUserChanges2(aceDoc, packedCs, delta) { packedCs = packedCs.slice(); var nlCh = "\n"; var startOff = aceDoc.positionToIndex(delta.start, false, true); var offset = startOff, opOff = 0; var op = packedCs[0]; while (op) { if (operations.type(op) === "delete") ; // process next op else if (offset < operations.length(op)) break; else offset -= operations.length(op); op = packedCs[++opOff]; } if (op && offset !== 0) { var splitted = operations.split(op, offset); packedCs.splice(opOff, 1, splitted[0], splitted[1]); opOff++; } var authorI; if (delta.action === "insert") { var newText = delta.lines.join(nlCh); authorI = workspace.authorPool[workspace.myUserId]; packedCs.splice(opOff, 0, "i" + newText); applyAuthorAttributes(doc.authAttribs, ["r" + startOff, "i" + newText], authorI); } else if (delta.action === "remove") { var removedText = delta.lines.join(nlCh); var remainingText = removedText; var opIdx = opOff; var nextOp = packedCs[opIdx]; while (remainingText.length) { if (!nextOp) { reportError(new Error("Collab: failed to remove text past end of document; rejoining"), { data: delta }); return rejoin(); } var opLen = operations.length(nextOp); var toRem = Math.min(remainingText.length, opLen); switch (operations.type(nextOp)) { case "retain": packedCs[opIdx] = "d" + remainingText.substring(0, toRem); if (opLen > remainingText.length) packedCs.splice(opIdx + 1, 0, "r" + (opLen - remainingText.length)); remainingText = remainingText.substring(toRem); opIdx++; break; case "insert": packedCs.splice(opIdx, 1); if (opLen > remainingText.length) packedCs.splice(opIdx, 0, operations.split(nextOp, toRem)[1]); remainingText = remainingText.substring(toRem); break; case "delete": opIdx++; break; } nextOp = packedCs[opIdx]; } applyAuthorAttributes(doc.authAttribs, ["r" + startOff, "d" + removedText], authorI); } return operations.pack(packedCs); } function calculateDelay() { var delay = MAX_DELAY; var selections = cursorLayer ? cursorLayer.selections : {}; var aceEditor = (c9Document.editor || "").ace; if (!aceEditor || aceEditor.session != session) return MAX_DELAY; var config = aceEditor.renderer.layerConfig; for (var clientId in selections) { delay -= 3000; var ranges = selections[clientId].screenRanges || []; for (var i = 0; i < ranges.length; i++) { var range = ranges[i]; var cursorPos = range.start; // range.cursor if (config.firstRow <= cursorPos.row && cursorPos.row <= config.lastRow) delay = MIN_DELAY; } } delay = Math.max(MIN_DELAY, delay); return delay; } function scheduleSend() { if (sendTimer) return; var delay = (pendingSave || commitTrials > 0) ? 0 : calculateDelay(); sendTimer = setTimeout(function () { doSend(); sendTimer = null; }, delay); } function addOutgoingEdit() { var uiDoc = session.getValue(); var msg = { docId: docId, op: operations.pack(packedCs) }; clearCs(uiDoc.length); outgoing.push(msg); } function doSend() { if (state !== "IDLE") return; if (sendTimer) { clearTimeout(sendTimer); sendTimer = null; } var st = new Date(); if (!outgoing.length && !isPackedUnity()) addOutgoingEdit(); if (outgoing.length) { state = "COMMITTING"; commitTrials++; var top = outgoing[0]; top.revNum = latestRevNum + 1; top.selection = lastSel = CursorLayer.selectionToData(session.selection); if (top.op.filter(function(o) { return o.length > MAX_OP_SIZE; }).length) { connect.send("LARGE_DOC", { docId: top.docId }); emit("largeDocument"); return leave(); } connect.send("EDIT_UPDATE", top); emit("send", { revNum: top.revNum }); } else { onCursorChange(); } if (debug) console.log("[OT] send took", new Date() - st, "ms"); } function setValue(contents, reset, bookmark, callback) { var state = c9Document.getState(); state.value = contents; c9Document.setState(state); clearCs(contents.length); lang.delayedCall(function() { if (reset) c9Document.undoManager.reset(); if (bookmark) c9Document.undoManager.bookmark(); callback && callback(); }).schedule(); } var lastData, chunkError; // for debugging function joinData(data) { var st = new Date(); loaded = false; if (data.reqId && reqId !== data.reqId) return console.log("Ignored unrequested join data"); var err = data.err; if (err) { if (err.code != "ENOENT" && err.code != "ELARGE") console.error("JOIN_DOC Error:", docId, err); if (err.code == "ELARGE") emit("largeDocument"); loading = false; reportError(new Error("Couldn't join to document"), err); return emit.sticky("joined", { err: err }); } var copiedData = { userId: data.userId, clientId: data.clientId, docId: data.docId, reqId: data.reqId, chunkNum: data.chunkNum, chunksLength: data.chunksLength }; if (!lastData && copiedData.chunkNum != 1 || copiedData.chunkNum == 1 && docStream || copiedData.chunkNum != (lastData && lastData.chunkNum || 0) + 1 || lastData && lastData.reqId != copiedData.reqId && copiedData.chunkNum != 1 || typeof data.chunk != "string" || !data.chunk ) { chunkError = { lastData: lastData, newData: copiedData, hasDocStream: typeof docStream != "string" && docStream, chunk: typeof data.chunk != "string" && data.chunk }; } lastData = copiedData; if (data.chunkNum === 1) docStream = ""; docStream += data.chunk; var complete = data.chunkNum === data.chunksLength; if (!c9Document.hasValue()) emit("joinProgress", { loaded: data.chunkNum, total: data.chunksLength, complete: complete }); if (!complete) return; try { doc = JSON.parse(docStream); } catch (e) { var error = typeof docStream == "string" ? { startCh: docStream.slice(0, 10), endCh: docStream.slice(-10) } : { docStream: docStream, type: typeof docStream }; error.copiedData = copiedData; error.chunk = typeof data.chunk != "string" && data.chunk; error.chunkError = chunkError; return rejoin("E_JOIN"); } finally { lastData = null; docStream = null; chunkError = null; } if (docId !== data.docId) reportError(new Error("docId mismatch"), { serverDocId: data.docId }); revisions = []; starRevNums = []; revCache = { revNum: doc.revNum, contents: doc.contents, authAttribs: cloneObject(doc.authAttribs) }; state = "IDLE"; outgoing = []; incoming = []; if (pendingSave) { saveWatchDog(true); save(pendingSave.silent); } delete doc.selections[workspace.myOldClientId]; // in case of being away delete doc.selections[workspace.myClientId]; // in case of a rejoin (can also be restored, if existing) if (session) joinWithSession(); if (debug) console.log("[OT] init took", new Date() - st, "ms"); loaded = true; loading = false; emit.sticky("joined", { contents: doc.contents, metadata: doc.metadata }); } function joinWithSession() { var clean = doc.fsHash === doc.docHash; if (!clean) console.log("[OT] doc latest state fs diff", docId); var clientContents = session.getValue(); var serverContents = doc.contents; var clientRevNum = latestRevNum; var serverRevNum = doc.revNum; latestRevNum = serverRevNum; var otherMembersNums = Object.keys(doc.selections).length; if (clientRevNum === serverRevNum || (!otherMembersNums && clientContents)) { packedCs = operations.operation(serverContents, clientContents); scheduleSend(); if (!clientRevNum) { var authorI = workspace.authorPool[workspace.myUserId]; applyAuthorAttributes(doc.authAttribs, packedCs, authorI); } } else if (!clientRevNum) { if (rejoinReason && clientContents && clientContents !== serverContents) { reportError(new Error("Collab: reverting local changes on uninited document"), { rejoinReason: rejoinReason, serverRevNum: serverRevNum, clientContents: clientContents, serverContents: serverContents }); logger.log("Collab: reverting local changes on document " + doc.path + " rev: " + serverRevNum + " rejoin reason: " + rejoinReason); } setValue(serverContents, clean, clean); // reset and bookmark if clean } else { if (clientRevNum > serverRevNum) { reportError(new Error("Collab: clientRevNum is higher than serverRevNum"), { rejoinReason: rejoinReason, clientRevNum: clientRevNum, serverRevNum: serverRevNum, clientContents: clientContents, serverContents: serverContents }); logger.log("Collab: clientrevNum is higher than serverRevNum " + doc.path + " clientRev: " + clientRevNum + " serverRev: " + serverRevNum + " rejoin reason: " + rejoinReason); } if (rejoinReason && clientContents && clientContents !== serverContents) { reportError(new Error("Collab: reverting local changes on collaborative document"), { rejoinReason: rejoinReason, clientRevNum: clientRevNum, serverRevNum: serverRevNum, clientContents: clientContents, serverContents: serverContents }); logger.log("Collab: reverting local changes on collaborative document " + doc.path + " clientRev: " + clientRevNum + " serverRev: " + serverRevNum + " rejoin reason: " + rejoinReason); } setValue(serverContents, clean, clean); // reset and bookmark } if (doc.newLineChar) { setAceNewLineMode(doc.newLineChar); } else if (doc.newLineChar === undefined) { reportError(new Error("doc.newLineChar is undefined")); var nlCh = collabUtil.detectNewLineType(doc.contents || ""); doc.permanentNlCh = nlCh; setAceNewLineMode(nlCh); } else { console.log("[OT] doc.newLineChar empty for ", docId, "new file? ok - syncing newline mode to collab server"); onChangeNewLineMode(); } rejoinReason = undefined; cursorTimer = setTimeout(changedSelection, 500); cursorLayer && cursorLayer.dispose(); cursorLayer = new CursorLayer(session, workspace); cursorLayer.updateSelections(doc.selections); authorLayer && authorLayer.dispose(); authorLayer = new AuthorLayer(session, workspace); authorLayer.refresh(); inited = true; } function setAceNewLineMode(lineEndChar) { if (!session || !session.doc) return; var mode; switch (lineEndChar) { case "\r\n": mode = "windows"; break; case "\n": case undefined: mode = "unix"; break; default: reportError(new Error("Warning: unexpected newLine mode: " + lineEndChar)); mode = "unix"; } session.doc.off("changeNewLineMode", onChangeNewLineMode); session.doc.$fsNewLine = lineEndChar; session.doc.setNewLineMode(mode); session.doc.on("changeNewLineMode", onChangeNewLineMode); } function onChangeNewLineMode() { var mode = session.doc.getNewLineMode(); var nlCh = mode == "windows" ? "\r\n" : "\n"; if (doc.permanentNlCh) { nlCh = doc.permanentNlCh; setAceNewLineMode(nlCh); } session.doc.$fsNewLine = nlCh; connect.send("UPDATE_NL_CHAR", { docId: docId, newLineChar: nlCh }); } function reportError(exception, details) { details = details || {}; details.state = state; details.session = !!session; details.newLineMode = session && session.doc && session.doc.getNewLineMode(); details.docId = docId; details.latestRevNum = latestRevNum; details.onlineCount = workspace.onlineCount; details.rejoinReason = rejoinReason; errorHandler.reportError(exception, details, ["collab"]); } function isPackedUnity() { return !packedCs.length || (packedCs.length === 1 && packedCs[0][0] === "r"); } function clearCs(len) { if (!len) packedCs = []; else packedCs = ["r" + len]; } function xformEach(outgoing, inMsg) { var ops = inMsg.op; var msg; function k(aPrime, bPrime) { msg.op = aPrime; ops = bPrime; } for (var i = 0, len = outgoing.length; i < len; i++) { msg = outgoing[i]; xform(msg.op, ops, k); } inMsg.op = ops; } function isOurOutgoing(msg, top) { return !msg.op && msg.docId === top.docId && msg.revNum === top.revNum; } function handleIncomingEdit(msg) { if (msg.revNum !== latestRevNum + 1) { reportError(new Error("Collab: Incoming edit revNum mismatch"), { serverRevNum: msg.revNum, latestRevNum: latestRevNum }); return; } var st = new Date(); if (outgoing.length && isOurOutgoing(msg, outgoing[0])) { commitTrials = 0; msg.op = outgoing[0].op; outgoing.shift(); addRevision(msg); state = "IDLE"; if (pendingSave && --pendingSave.outLen === 0) doSaveFile(pendingSave.silent); scheduleSend(); } else { addRevision(msg); if (msg.sync) { c9Document.tab.meta.$lastCollabChange = Date.now(); if (c9Document.tab.meta.$collabChangeRegistered) { clearTimeout(c9Document.tab.meta.$collabChangeRegistered); delete c9Document.tab.meta.$collabChangeRegistered; } var path = msg.path || msg.docId; logger.log("Collab: Received new document, discarding any pending changes " + path + " msg: ", msg, " latestRevNum: " + latestRevNum); try { revertMyPendingChanges(msg.userId); } catch (e) { var cause = e.message; e.message = "Collab: unable to revert pending changes, reloading"; reportError(e, { cause: cause }); return rejoin("E_REVERT"); } pendingSave = null; } else { outgoing.push({ op: packedCs }); xformEach(outgoing, msg); packedCs = outgoing.pop().op; } var sel = session.selection; cursorLayer.setInsertRight(msg.clientId, false); sel.anchor.$insertRight = sel.lead.$insertRight = true; var rev = session.$undoManager.startNewGroup(); applyEdit(msg, session.doc); session.$undoManager.markIgnored(rev); sel.anchor.$insertRight = sel.lead.$insertRight = false; cursorLayer.setInsertRight(msg.clientId, true); if (msg.sync) { flagFileSaved(msg, true, true); clearCs(session.getValue().length); } } latestRevNum = msg.revNum; if (msg.selection) cursorLayer.updateSelection(msg); if (debug) console.log("[OT] handleIncomingEdit took", new Date() - st, "ms", latestRevNum); } function applyEdit(msg, aceDoc, revertData) { if (timeslider.visible) return; var err; ignoreChanges = true; try { applyAce(msg.op, aceDoc); applyAuthorAttributes(doc.authAttribs, msg.op, workspace.authorPool[msg.userId]); } catch (e) { var oldMessage = e.message; if (e.code === "EMISMATCH") { e.message = // distinguish different error categories based on state !revertData ? "Mismatch applying client-side OT operation" : revertData.userId ? "Mismatch applying client-side OT operation, revert with userId" : "Mismatch applying client-side OT operation, revert without userId"; } reportError(e, { cause: e.message !== oldMessage ? oldMessage : undefined, msg: msg, revertData: revertData }); err = e; } finally { authorLayer.refresh(); if (msg.revNum) doc.revNum = msg.revNum; ignoreChanges = false; if (err) rejoin("E_APPLYEDIT"); } } function changedSelection() { if (!session || !session.selection) return; cursorTimer = null; var currentSel = CursorLayer.selectionToData(session.selection); if (lastSel && lastSel.join('') === currentSel.join('')) return; lastSel = currentSel; connect.send("CURSOR_UPDATE", { docId: docId, selection: lastSel }); if (cursorLayer && cursorLayer.tooltipIsOpen) cursorLayer.hideAllTooltips(); } function onChangeEditor(e) { var oldEditor = e.oldEditor; if (oldEditor) { if (readonly) oldEditor.setReadOnly(false); } if (e.editor && readonly) { e.editor.setReadOnly(true); } } function onCursorChange() { if (!loaded || ignoreChanges || cursorTimer) return; cursorTimer = setTimeout(changedSelection, 200); } function addRevision(msg) { if (!msg.op.length) reportError(new Error("Empty rev operation should never happen!"), { msg: msg }); revisions[msg.revNum] = { operation: msg.op, revNum: msg.revNum, author: msg.userId, updated_at: msg.updated_at || Date.now() }; if (isActiveTimesliderDocument()) timeslider.sliderLength = msg.revNum; } function isActiveTimesliderDocument() { return timeslider.visible && timeslider.activeDocument === plugin; } function getDetailedRevision(revNum, contentsOnly) { if (!rev0Cache && !contentsOnly) { rev0Cache = createFirstRevisionViaInverseOperations(); revCache = null; } if (!revCache || revCache.revNum > revNum) { revCache = cloneObject(rev0Cache); } var contents = revCache.contents; var authAttribs = cloneObject(revCache.authAttribs); for (var i = revCache.revNum + 1; i <= revNum; i++) { contents = applyContents(revisions[i].operation, contents); applyAuthorAttributes(authAttribs, revisions[i].operation, workspace.authorPool[revisions[i].author]); } var rev = cloneObject(revisions[revNum]); if (!rev) return null; rev.contents = contents; rev.authAttribs = authAttribs; revCache.contents = contents; revCache.authAttribs = cloneObject(authAttribs); revCache.revNum = revNum; return rev; } function createFirstRevisionViaInverseOperations() { var i; var rev0Contents = revCache.contents; for (i = revCache.revNum; i > 0; i--) { var op = operations.inverse(revisions[i].operation); try { rev0Contents = applyContents(op, rev0Contents); } catch (e) { reportError(new Error("Revision history is not working for document"), { applyContentsError: e.message, revNum: i }); break; } } var originalRevision = { revNum: i, // this is the last revision we could get to, should be 0, but could be higher if revision history is broken contents: rev0Contents, authAttribs: [rev0Contents.length, null] }; return originalRevision; } function getRevisionContents(revNum) { var rev = getDetailedRevision(revNum, true); return rev && rev.contents; } function historicalSearch(query) { var searchString = lang.escapeRegExp(query); var revNums = revisions.length; var result = { revNums: revNums }; for (var revNo = 0; revNo < revNums; revNo++) { var rev = getDetailedRevision(revNo); var count = 0; if (rev.contents.match(new RegExp(searchString, 'i'))) { count = rev.contents.match(new RegExp(searchString, 'gi')).length; result[revNo] = count; } } return result; } function isReadOnly() { return readonly || (c9Document.editor && c9Document.editor.ace && c9Document.editor.ace.getReadOnly()); } function updateToRevision(revNum) { if (!revisions[0]) return console.warn("[OT] revisions may haven't yet been loaded!"); if (!isReadOnly()) return console.error("[OT] Can't updateToRevNum while editing!"); if (typeof revNum === "undefined") revNum = revisions.length - 1; if (debug) console.log("[OT] REV:", revNum); if (doc.revNum === revNum) return; var rev = getDetailedRevision(revNum); timeslider.updateTimer(rev.updated_at); ignoreChanges = true; var resetAndBookmark = starRevNums.indexOf(revNum) !== -1; setValue(rev.contents, resetAndBookmark, resetAndBookmark); doc.authAttribs = rev.authAttribs; authorLayer.refresh(); doc.revNum = revNum; ignoreChanges = false; } function revertToRevision(revNum) { var latestRev = getDetailedRevision(revisions.length - 1); var revertToRev = getDetailedRevision(revNum); ignoreChanges = true; setValue(revertToRev.contents, false, false); // don't reset or bookmark to keep the doc changed var op = operations.operation(latestRev.contents, revertToRev.contents); var authAttribs = latestRev.authAttribs; var authorI = workspace.authorPool[workspace.myUserId]; applyAuthorAttributes(authAttribs, op, authorI); doc.authAttribs = authAttribs; authorLayer.refresh(); packedCs = op; scheduleSend(); ignoreChanges = false; } function revertMyPendingChanges(userId) { if (!isPackedUnity()) outgoing.push({ op: packedCs }); if (!outgoing.length) return; var doc = session.doc || {}; reportError(new Error("Collab: reverting pending changes to document because of server sync commit"), { outgoing: outgoing, doc: doc }); logger.log("Collab: reverting pending chagnes to document because of server sync commit " + doc.path + " revNum: " + doc.revNum); userId = userId || workspace.myUserId; for (var i = outgoing.length - 1; i >= 0; i--) { applyEdit( { op: operations.inverse(outgoing[i].op), userId: userId }, session.doc, { outgoing: outgoing, userId: userId } ); } outgoing = []; } function handleMessage(event) { if (inited && !doc) reportError(new Error("Weird state: inited, but no document")); if (!inited || !doc) return incoming.push(event); var data = event.data; switch (event.type) { case "EDIT_UPDATE": handleIncomingEdit(data); break; case "UPDATE_NL_CHAR": setAceNewLineMode(data.newLineChar); break; case "SYNC_COMMIT": handleSyncCommit(data); break; case "CURSOR_UPDATE": cursorLayer && cursorLayer.updateSelection(data); break; case "FILE_SAVED": handleFileSaved(data); break; case "FILE_LOCKING": saveStateDebugging = "LOCKING"; break; case "FILE_LOCKED": saveStateDebugging = "LOCKED"; break; case "FILE_RETRIEVED": saveStateDebugging = "RETRIEVED"; break; case "DATA_WRITTEN": saveStateDebugging = "DATAWRITTEN"; break; case "GET_REVISIONS": receiveRevisions(data); break; default: reportError(new Error("Unknown OT document event type:" + event.type + " " + JSON.stringify(event))); } } function handleSyncCommit(data) { state = "IDLE"; if (data.code == "VERSION_E" && latestRevNum !== data.revNum) { reportError(new Error("Collab: OT version inconsistency"), { serverRevNum: data.revNum, latestRevNum: latestRevNum }); latestRevNum = data.revNum; } if (data.code == "OT_E" || commitTrials > MAX_COMMIT_TRIALS) { console.warn("[OT] Local document inconsistent with server; attempting rejoin -- SYNC_COMMIT", data.reason, data.code); logger.log("[OT] Local document inconsistent with server; attempting rejoin -- SYNC_COMMIT", data.reason, data.code); rejoin("OT_E"); } else { console.warn("Collab: [OT] Local document inconsistent with server; reapplying changes -- SYNC_COMMIT", data.reason, data.code); logger.log("Collab: [OT] Local document inconsistent with server; reapplying changes -- SYNC_COMMIT", data.reason, data.code); scheduleSend(); } } function handleFileSaved(data) { endSaveWatchDog(); var err = data.err; if (err) { console.error("[OT] Failed saving file!", err, docId); return emit("saved", { err: err }); } if (pendingSave) { var value = getRevisionContents(data.revNum); if (value == undefined) { if (plugin.docHash !== data.fsHash) { reportError(new Error("File saved, unable to confirm checksum"), { docHash: plugin.docHash, fsHash: data.fsHash, revNum: data.revNum, docId: docId }); } } else if (apf.crypto.MD5.hex_md5(value) !== data.fsHash) { reportError(new Error("File saving checksum failed; retrying with XHR")); return emit("saved", { err: "Save content mismatch", code: "EMISMATCH" }); } } var isClean = !outgoing.length || latestRevNum === data.revNum; var rev = revisions[data.revNum] || { revNum: data.revNum, updated_at: Date.now() }; flagFileSaved(rev, data.star, isClean); pendingSave = null; } function flagFileSaved(revision, isStar, isClean) { emit("saved", {}); if (isClean) { lang.delayedCall(function() { c9Document.undoManager.bookmark(); }).schedule(); } if (isStar) { starRevNums.push(revision.revNum); if (isActiveTimesliderDocument()) timeslider.addSavedRevision(revision); } } function receiveRevisions(data) { if (data.chunkNum === 1) revStream = ""; revStream += data.chunk; if (data.chunkNum < data.chunksLength) return; var revisionsObj = JSON.parse(revStream); revStream = null; revisions = revisionsObj.revisions; starRevNums = revisionsObj.starRevNums; emit("revisions", { revisions: revisions, stars: starRevNums }); if (isActiveTimesliderDocument()) loadRevisions(); } function loadRevisions() { if (!revisions[0]) { console.log("[OT] Loading revisions ..."); timeslider.loading = true; connect.send("GET_REVISIONS", { docId: docId }); return; } if (!isActiveTimesliderDocument()) return; var numRevs = revisions.length - 1; var lastRev = revisions[numRevs]; var starRevisions = starRevNums.map(function (revNum) { return revisions[revNum]; }); timeslider.loading = false; timeslider.sliderLength = numRevs; timeslider.setSavedRevisions(starRevisions); timeslider.sliderPosition = numRevs; timeslider.updateTimer(lastRev.updated_at); timeslider.sliderLength = numRevs; cursorLayer.hideAllTooltips(); authorLayer.refresh(); } function save(silent) { saveWatchDog(); stateWhenSaveCalled = state; saveStateDebugging = null; var isUnity = isPackedUnity(); if (!isUnity) addOutgoingEdit(); pendingSave = { silent: !!silent, outLen: outgoing.length }; if (state === "IDLE" && isUnity) return doSaveFile(silent); doSend(); } function doSaveFile(silent) { saveWatchDog(); if (!pendingSave) // should be set, but let's make sure pendingSave = { silent: silent }; var event = { docId: docId }; emit("beforeSave", event); saveStateDebugging = "SAVING"; connect.send("SAVE_FILE", { postProcessor: event.postProcessor, docId: docId, silent: !!silent }); } function saveWatchDog(restart, timeout) { if (saveTimer && !restart) return; endSaveWatchDog(); saveTimer = setTimeout(function onSaveTimeout() { saveTimer = pendingSave = null; emit("saved", { err: "File save timeout", code: "ETIMEOUT" }); }, timeout || COLLAB_SAVE_FILE_TIMEOUT); } function endSaveWatchDog() { clearTimeout(saveTimer); saveTimer = null; } function rejoin(reason) { console.log("[OT] rejoining document", docId, "reason: ", reason); resetState(); rejoinReason = reason; var sameSession = session; session = null; setSession(sameSession); doLoad(); } function load() { if (state == "DISCONNECTED") rejoin("DISCONNECTED"); else doLoad(); } function doLoad() { loading = true; reqId = Math.floor(Math.random() * 9007199254740993); connect.send("JOIN_DOC", { docId: docId, reqId: reqId }); } function leave() { if (connect.connected) connect.send("LEAVE_DOC", { docId: docId }); resetState(); } function disconnect() { resetState(); state = "DISCONNECTED"; logger.log("[OT] document", docId, "disconnected"); } function clientLeave(clientId) { cursorLayer && cursorLayer.clearSelection(clientId); } function isChanged () { var lastRev = revisions[revisions.length - 1]; return !isPackedUnity() || (revisions.length > 1 && starRevNums.indexOf(lastRev.revNum) === -1); } plugin.freezePublicAPI({ _events: [ "joined", "joinProgress", "saved", "revisions", "send", ], get id() { return docId; }, get rejoinReason() { return rejoinReason; }, get path() { return docId; }, get state() { return state; }, get stateWhenSaveCalled() { return stateWhenSaveCalled; }, get saveStateDebugging() { return saveStateDebugging; }, get session() { return session; }, get original() { return c9Document; }, get loading() { return loading; }, get loaded() { return loaded; }, get inited() { return inited; }, get fsHash() { return doc && doc.fsHash; }, get docHash() { return doc && doc.docHash; }, get authAttribs() { return doc ? doc.authAttribs : []; }, get revisions() { return revisions; }, get cursorLayer() { return cursorLayer; }, get authorLayer() { return authorLayer; }, get latestRevNum() { return latestRevNum; }, get changed() { return isChanged(); }, get pendingUpdates() { return packedCs.length > 1; }, get readonly() { return isReadOnly(); }, set readonly(r) { readonly = r; c9Document.tab.editor.setOption("readOnly", r); }, load: load, setSession: setSession, leave: leave, dispose: resetState, disconnect: disconnect, clientLeave: clientLeave, loadRevisions: loadRevisions, sendNow: doSend, updateToRevision: updateToRevision, revertToRevision: revertToRevision, save: save, historicalSearch: historicalSearch, joinData: joinData, handleMessage: handleMessage }); return plugin; } register(null, { "OTDocument": OTDocument }); } }); define("plugins/c9.ide.collab/util",[], function(require, exports, module) { main.consumes = ["Plugin"]; main.provides = ["collab.util"]; return main; function main(options, imports, register) { var Plugin = imports.Plugin; var plugin = new Plugin("Ajax.org", main.consumes); var HTML_ENTITY_MAP = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/' }; var HTML_CHARACTERS_EXPRESSION = /[&"'<>\/]/gm; function escapeHTML(text) { return text && text.replace(HTML_CHARACTERS_EXPRESSION, function (c) { return HTML_ENTITY_MAP[c] || c; }); } var HTML_ATTRIBUTE_CHARACTERS_EXPRESSION = /[\x00-\x2F\x3A-\x40\x5B-\x60\x7B-\xFF]/gm; function escapeHTMLAttribute(text) { return text && text.replace(HTML_ATTRIBUTE_CHARACTERS_EXPRESSION, function (c) { return HTML_ENTITY_MAP[c] || "&#x" + ('00' + c.charCodeAt(0).toString(16)).slice(-2) + ";"; }); } function findURLs(text) { var _REGEX_WORDCHAR = /[\u0030-\u0039\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u1FFF\u3040-\u9FFF\uF900-\uFDFF\uFE70-\uFEFE\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFDC]/; var _REGEX_URLCHAR = new RegExp('(' + /[-:@a-zA-Z0-9_.,~%+\/?=&#;()$]/.source + '|' + _REGEX_WORDCHAR.source + ')'); var _REGEX_URL = new RegExp(/(?:(?:https?|s?ftp|ftps|file|smb|afp|nfs|(x-)?man|gopher|txmt):\/\/|mailto:)/.source + _REGEX_URLCHAR.source + '*(?![:.,;])' + _REGEX_URLCHAR.source, 'g'); function _findURLs(text) { _REGEX_URL.lastIndex = 0; var urls = null; var execResult; while ((execResult = _REGEX_URL.exec(text))) { urls = (urls || []); var startIndex = execResult.index; var url = execResult[0]; urls.push([startIndex, url]); } return urls; } return _findURLs(text); } function escapeHtmlWithClickableLinks(text, target) { var idx = 0; var pieces = []; var urls = findURLs(text); function advanceTo(i) { if (i > idx) { pieces.push(escapeHTML(text.substring(idx, i))); idx = i; } } if (urls) { for (var j = 0; j < urls.length; j++) { var startIndex = urls[j][0]; var href = urls[j][1]; advanceTo(startIndex); pieces.push(''); advanceTo(startIndex + href.length); pieces.push(''); } } advanceTo(text.length); return pieces.join(''); } function formatColor(rgb, alpha) { if (!rgb) return "transparent"; if (alpha) return ["rgba(", rgb.r, ",", rgb.g, ",", rgb.b, ",", alpha, ")"].join(""); else return ["rgb(", rgb.r, ",", rgb.g, ",", rgb.b, ")"].join(""); } function reverseObject(obj) { var reversed = {}; for (var auth in obj) reversed[obj[auth]] = auth; return reversed; } function isRealCollab(workspace) { var users = workspace.users; var numUsers = Object.keys(users).length; if (users["Anonymous"]) numUsers--; return numUsers > 1; } function normalizeTextLT(text) { return text.replace(/\r\n?/g, "\n"); } function detectNewLineType(text) { var match = text.match(/^.*?(\r\n|\r|\n)/m); return match ? match[1] : "\n"; } plugin.freezePublicAPI({ detectNewLineType: detectNewLineType, normalizeTextLT: normalizeTextLT, escapeHtmlWithClickableLinks: escapeHtmlWithClickableLinks, escapeHTML: escapeHTML, formatColor: formatColor, reverseObject: reverseObject, isRealCollab: isRealCollab }); register(null, { "collab.util": plugin }); } }); define("plugins/c9.ide.collab/workspace",[], function(require, exports, module) { main.consumes = ["Plugin", "collab.util", "api", "pubsub", "info", "dialog.alert"]; main.provides = ["collab.workspace"]; return main; function main(options, imports, register) { var Plugin = imports.Plugin; var util = imports["collab.util"]; var api = imports.api; var pubsub = imports.pubsub; var info = imports["info"]; var showAlert = imports["dialog.alert"].show; var plugin = new Plugin("Ajax.org", main.consumes); var emit = plugin.getEmitter(); var isAdmin = options.isAdmin; var authorPool = {}; var colorPool = {}; var users = {}; var clients = {}; var onlineCount = 0; var myUserId = info.getUser().id; var loadedWorkspace = false; var myClientId, myOldClientId, fs; var reversedAuthorPool, chatHistory; var loaded = false; function load() { if (loaded) return; loaded = true; pubsub.on("message", function(message) { if (message.type != "collab") return; console.log("PubSub collab API message", message); var action = message.action; var body = message.body; var uid = body.uid; switch (action) { case "add_member": addCachedMember(body); if (myUserId == uid) { showAlert("Workspace Access Changed", body.acl == "rw" ? "You have been granted read/write access to this workspace." : "You have been granted readonly access to this workspace.", "To continue, Cloud9 will be reloaded.", function() { reloadWorkspace(1000); }); } break; case "update_member_access": updateCachedAccess(uid, body.acl); if (myUserId == uid) { showAlert("Workspace Access Changed", body.acl == "rw" ? "You have been granted read/write access to the workspace." : "You workspace access has been limited to read-only.", "To continue, Cloud9 will be reloaded.", function() { reloadWorkspace(1000); }); } break; case "remove_member": removeCachedMember(uid); if (body.uid == myUserId) { showAlert("Workspace Access Revoked", "You have been removed from the list of members of this workspace.", "To continue, Cloud9 will be reloaded.", function() { reloadWorkspace(1000); }); } break; case "request_access": var notif = { type: "access_request", name: body.name, uid: body.uid, email: body.email }; emit("notification", notif); break; case "accept_request": reloadWorkspace(); break; case "deny_request": reloadWorkspace(); break; default: console.warn("Unhandled pubsub collab action:", action, message); } }); } function reloadWorkspace(afterTimeout) { setTimeout(function() { window.location.reload(); }, afterTimeout || 10); } function syncWorkspace(data) { if (myClientId !== data.myClientId) myOldClientId = myClientId; else myOldClientId = null; myClientId = data.myClientId; fs = data.fs; authorPool = data.authorPool; reversedAuthorPool = util.reverseObject(authorPool); colorPool = data.colorPool; users = data.users; chatHistory = data.chatHistory; loadedWorkspace = true; onlineCount = 0; for (var user in users) onlineCount += user.online ? 1 : 0; onlineCount = Math.max(onlineCount, 1); emit.sticky("sync"); } function leaveClient(uid, clientId) { var user = users[uid]; user.online = Math.max(user.online - 1, 0); if (!user.clients) user.clients = []; var i = user.clients.indexOf(clientId); if (i != -1) user.clients.splice(i, 1); onlineCount--; emit.sticky("sync"); } function joinClient(user, clientId) { var uid = user.uid; var authorId = user.author; users[uid] = user; authorPool[uid] = authorId; reversedAuthorPool[authorId] = uid; colorPool[uid] = user.color; onlineCount++; emit.sticky("sync"); } function updateOpenDocs(data, action) { var user = users[data.userId]; if (!user) return; var client = user.clients[data.clientId]; if (action == "leave" && !client) return; if (!client) { client = user.clients[data.clientId] = { documents: [], active: -1, status: "pending" }; } if (action == "set") { user.clients[data.clientId] = data.fileList; data.fileList.status = "loaded"; emit.sticky("sync"); return; } var tabId = data.tabId || data.docId; if (!tabId) return; var i = client.documents.indexOf(tabId); if (action == "join") { if (i == -1) client.documents.push(tabId); } else if (action == "leave") { if (i != -1) client.documents.splice(i, 1); } else if (action == "activate") { if (i == -1) i = client.documents.push(tabId) - 1; client.active = i; } emit.sticky("sync"); } function updateUserState(uid, state) { users[uid].state = state; emit.sticky("sync"); } var cachedMembers; var cachedInfo; function loadMembers(callback) { if (cachedMembers) { return done(cachedMembers, cachedInfo); } api.collab.get("access_info", function (err, info) { if (err && err.code === 0) { return setTimeout(loadMembers.bind(null, callback), 20000); } if (err) return callback(err); if (!info.member) return done([], info); api.collab.get("members/list?pending=0", function (err, data) { if (err && err.code !== 403) return callback(err); done(!err && data || [], info); }); }); function done(members, info) { cachedMembers = members; cachedInfo = info; callback(); emit.sticky("sync"); } } function addMember(username, access, options, callback) { if (!callback) { callback = options; options = {}; } api.collab.post("members/add", { body: { username: username, access: access }, query: { silent: options.silent } }, function (err, data, res) { if (err) return callback(err); if (!pubsub.connected) // pubsub not working addCachedMember(data, callback); else callback(null, data); }); } function addCachedMember(member, next) { if (!cachedMembers) return console.warn("addCachedMember() - cachedMembers = null !"); cachedMembers = cachedMembers.filter(function (m) { return m.uid != member.uid; }); cachedMembers.push(member); emit.sticky("sync"); next && next(null, member); } function removeMember(uid, callback) { api.collab.delete("members/remove", { body: { uid: uid } }, function (err, data, res) { if (err) return callback(err); if (!pubsub.connected) // pubsub not working removeCachedMember(uid, callback); }); } function removeCachedMember(uid, next) { if (!cachedMembers) return console.warn("removeCachedMember() - cachedMembers = null !"); cachedMembers = cachedMembers.filter(function (member) { return member.uid != uid; }); emit.sticky("sync"); next && next(); } function updateAccess(uid, acl, callback) { api.collab.put("members/update_access", { body: { uid: uid, access: acl } }, function (err, data, res) { if (err) return callback(err); if (!pubsub.connected) // pubsub not working updateCachedAccess(uid, acl, callback); }); } function updateCachedAccess(uid, acl, next) { if (!cachedMembers) return console.warn("updateCachedAccess() - cachedMembers = null !"); (cachedMembers.filter(function (member) { return member.uid == uid; })[0] || {}).acl = acl; emit.sticky("sync"); next && next(); } function getUserState(uid) { var user = users[uid]; if (!user || !user.online) return "offline"; return user.state || "online"; } function addMemberNonPubSub(member) { if (!pubsub.connected) // pubsub not working addCachedMember(member); } plugin.on("load", function() { load(); }); plugin.freezePublicAPI({ _events: [ "sync", ], get users() { return users; }, get authorPool() { return authorPool; }, get reversedAuthorPool() { return reversedAuthorPool; }, get colorPool() { return colorPool; }, get myClientId() { return myClientId; }, get myOldClientId() { return myOldClientId; }, get myUserId() { return myUserId; }, get isReady() { return loadedWorkspace; }, get fs() { return fs; }, get chatHistory() { return chatHistory; }, set chatHistory(history) { chatHistory = history; }, get members() { return cachedMembers || []; }, get onlineCount() { return onlineCount; }, get accessInfo() { return cachedInfo || {}; }, get isAdmin() { return isAdmin; }, addChatMessage: function (msg) { chatHistory.push(msg); }, getUser: function (uid) { return users[uid]; }, getUserColor: function (uid) { return (uid && util.formatColor(colorPool[uid])) || "transparent"; }, getUserState: getUserState, syncWorkspace: syncWorkspace, leaveClient: leaveClient, joinClient: joinClient, updateOpenDocs: updateOpenDocs, updateUserState: updateUserState, loadMembers: loadMembers, updateAccess: updateAccess, removeMember: removeMember, addMember: addMember, addMemberNonPubSub: addMemberNonPubSub, }); register(null, { "collab.workspace": plugin }); } }); define("plugins/c9.ide.collab/collabpanel",[], function(require, module, exports) { main.consumes = ["Plugin", "ui", "collab", "settings"]; main.provides = ["CollabPanel"]; return main; function main(options, imports, register) { var Plugin = imports.Plugin; var ui = imports.ui; var collab = imports.collab; var settings = imports.settings; function CollabPanel(developer, deps, options) { var plugin = new Plugin(developer, deps); var emit = plugin.getEmitter(); emit.setMaxListeners(1000); var caption = options.caption; var index = options.index || 100; var height = options.height || ""; var style = options.style || ""; var amlFrame; plugin.on("load", function() { collab.once("drawPanels", draw, plugin); }); function draw(e) { amlFrame = ui.frame({ buttons: "min", activetitle: "min", "class": "absframe", style: "position:relative;" + (style || ""), textselect: options.textselect, caption: caption }); var aml = e.aml; if (index == 100) aml.insertBefore(amlFrame, aml.firstChild); else aml.appendChild(amlFrame); if (height) amlFrame.setHeight(height); plugin.addElement(amlFrame); emit.sticky("draw", { aml: amlFrame, html: amlFrame.$int }); amlFrame.on("prop.height", function() { emit("resize"); }); amlFrame.on("afterstatechange", function () { if (amlFrame.parentNode) { amlFrame.parentNode.childNodes.forEach(function(n) { n.emit("resize"); }); var closed = amlFrame.state != "normal"; settings.set("state/collab/panel/" + options.name + "/@closed", closed); } }); settings.once("read", function() { var closed = settings.get("state/collab/panel/" + options.name + "/@closed", closed); if (closed) setTimeout(function() {amlFrame.minimize();}, 10); }); collab.on("show", function() { emit("show"); }, plugin); collab.on("hide", function() { emit("hide"); }, plugin); } function show() { collab.show(); amlFrame && amlFrame.restore(); emit("show"); } function hide() { amlFrame.hide(); emit("hide"); } plugin.freezePublicAPI.baseclass(); plugin.freezePublicAPI({ get aml() { return amlFrame; }, _events: [ "draw" ], show: show, hide: hide }); return plugin; } register(null, { CollabPanel: CollabPanel }); } }); define("text!plugins/c9.ide.collab/collab.css",[],""); define("plugins/c9.ide.collab/install",[], function(require, exports, module) { module.exports = function(session, options) { var win32 = options.platform == "win32"; win32 || session.install({ "name": "SQLite", "description": "SQLite Database and NPM module", "cwd": "~/.c9", "optional": true }, [ { "npm": ["sqlite3@3.1.4"] }, { "tar.gz": { "url": "https://raw.githubusercontent.com/c9/install/master/packages/sqlite3/linux/sqlite3.tar.gz", "target": "~/.c9/lib/sqlite3", "dir": "sqlite3" } }, { "symlink": { "source": "~/.c9/lib/sqlite3/sqlite3", "target": "~/.c9/bin/sqlite3" } } ]); session.install({ "name": "Sequelize", "description": "Sequelize NPM module", "cwd": "~/.c9", "optional": true }, { "npm": ["sequelize@2.0.0-beta.0"] }); session.start(); }; module.exports.version = 1; }); define("plugins/c9.ide.collab/collab",[], function(require, exports, module) { "use strict"; main.consumes = [ "Panel", "tabManager", "fs", "metadata", "ui", "apf", "settings", "preferences", "ace", "util", "collab.connect", "collab.workspace", "timeslider", "OTDocument", "notification.bubble", "dialog.error", "dialog.alert", "collab.util", "error_handler", "layout", "menus", "installer", "c9" ]; main.provides = ["collab"]; return main; function main(options, imports, register) { var Panel = imports.Panel; var tabManager = imports.tabManager; var fs = imports.fs; var c9 = imports.c9; var metadata = imports.metadata; var installer = imports.installer; var ui = imports.ui; var apf = imports.apf; var ace = imports.ace; var util = imports.util; var collabUtil = imports["collab.util"]; var settings = imports.settings; var prefs = imports.preferences; var connect = imports["collab.connect"]; var workspace = imports["collab.workspace"]; var bubble = imports["notification.bubble"]; var timeslider = imports.timeslider; var OTDocument = imports.OTDocument; var showAlert = imports["dialog.alert"].show; var showError = imports["dialog.error"].show; var errorHandler = imports.error_handler; var layout = imports.layout; var menus = imports.menus; var css = require("text!./collab.css"); var plugin = new Panel("Ajax.org", main.consumes, { index: 45, width: 250, caption: "Collaborate", buttonCSSClass: "collab", panelCSSClass: "collab-bar", minWidth: 130, where: "right" }); var emit = plugin.getEmitter(); var documents = Object.create(null); var openFallbackTimeouts = Object.create(null); var saveFallbackTimeouts = Object.create(null); var usersLeaving = Object.create(null); var failedSaveAttempts = 0; var OPEN_FILESYSTEM_FALLBACK_TIMEOUT = 6000; var SAVE_FILESYSTEM_FALLBACK_TIMEOUT = 30000; var SAVE_FILESYSTEM_FALLBACK_TIMEOUT_REPEATED = 15000; installer.createSession("c9.ide.collab", require("./install")); var loaded = false; function load() { if (loaded) return; loaded = true; connect.on("message", onMessage); connect.on("connecting", onConnecting); connect.on("connect", onConnectMsg); connect.on("disconnect", onDisconnect); metadata.on("beforeReadFile", beforeReadFile, plugin); fs.on("afterReadFile", afterReadFile, plugin); fs.on("beforeWriteFile", beforeWriteFile, plugin); ace.on("initAceSession", function(e) { var doc = e.doc; var path = doc.tab.path; var otDoc = documents[path]; if (otDoc && !otDoc.session) otDoc.setSession(doc.getSession().session); }); tabManager.on("focusSync", function(e) { var tab = e.tab; var otDoc = documents[tab.path]; if (otDoc && !otDoc.session) { var doc = tab.document; var docSession = doc.getSession(); docSession && otDoc.setSession(docSession.session); } }); tabManager.on("focus", function(e) { var tab = e.tab; if (tab && tab.editor) { var id = getTabId(tab); id && connect.send("MESSAGE", { action: "focus", clientId: workspace.myClientId, userId: workspace.myUserId, tabId: id }); } }); plugin.on("userMessage", function(e) { if (e.action == "focus") { workspace.updateOpenDocs(e, "activate"); } }); ui.insertCss(css, null, plugin); window.addEventListener("unload", function() { leaveAll(); }, false); tabManager.on("open", function(e) { var tab = e.tab; tab.on("setPath", function(e) { onSetPath(tab, e.oldpath, e.path); }); }); tabManager.on("tabDestroy", function(e) { leaveDocument(e.tab.path); }, plugin); var showAuthorInfoKey = "user/collab/@show-author-info"; prefs.add({ "General": { "Collaboration": { "Show Authorship Info": { type: "checkbox", position: 8000, path: showAuthorInfoKey } } } }, plugin); settings.on("read", function () { settings.setDefaults("user/collab", [["show-author-info", true]]); refreshActiveDocuments(); }, plugin); settings.on("user/collab", function () { refreshActiveDocuments(); }, plugin); workspace.on("sync", scheduleUpdateUserBadges); scheduleUpdateUserBadges(); } var drawn = false; function draw(options) { if (drawn) return; drawn = true; var bar = options.aml; var html = bar.$int; emit.sticky("drawPanels", { html: html, aml: bar }); } function onDisconnect() { for (var docId in documents) { var doc = documents[docId]; doc.disconnect(); } emit("disconnect"); } function onConnecting () { } function onConnectMsg(msg) { workspace.syncWorkspace(msg.data); for (var docId in documents) documents[docId].load(); emit("connect"); } function onMessage(msg) { var data = msg.data || {}; var user = data && data.userId && workspace.getUser(data.userId); var type = msg.type; var docId = data.docId; if (docId && "/~".indexOf(docId[0]) === -1) docId = data.docId = "/" + docId; var doc = documents[docId]; if (!connect.connected && type !== "CONNECT") return console.warn("[OT] Not connected - ignoring:", msg); if (data.clientId && data.clientId === workspace.myOldClientId) return console.warn("[OT] Skipping my own 'away' disconnection notifications"); switch (type) { case "CHAT_MESSAGE": data.increment = true; emit("chatMessage", data); break; case "USER_JOIN": user = data.user; if (!user) break; workspace.joinClient(user, data.clientId); notifyUserOnline(user); break; case "USER_LEAVE": workspace.leaveClient(data.userId, data.clientId); notifyUserOffline(user); break; case "LEAVE_DOC": workspace.updateOpenDocs(data, "leave"); doc && doc.clientLeave(data.clientId); break; case "JOIN_DOC": workspace.updateOpenDocs(data, "join"); if (workspace.myClientId !== data.clientId) return; if (!doc) return console.warn("[OT] Received msg for file that is not open - docId:", docId, "open docs:", Object.keys(documents)); doc.joinData(data); break; case "RESOLVE_CONFLICT": emit("resolveConflict", { path: docId }); break; case "LARGE_DOC": doc && doc.leave(); doc && reportLargeDocument(doc, !msg.data.response); delete documents[docId]; break; case "DOC_CHANGED_ON_DISK": reportDocChangedOnDisk(docId); break; case "DOC_HAS_PENDING_CHANGES": reportDocHasPendingChanges(docId); break; case "USER_STATE": workspace.updateUserState(data.userId, data.state); break; case "CLEAR_CHAT": emit("chatClear", data); break; case "MESSAGE": if (emit("userMessage", data) !== false) handleUserMessage(data); break; case "ERROR": errorHandler.log( data.err || new Error("Collab error"), util.extend({}, { users: workspace.users, userId: workspace.myUserId, clientId: workspace.myClientId }, data) ); break; case "POST_PROCESSOR_ERROR": emit("postProcessorError", data); return; case "RESET_DB": showAlert("Uh oh!", "Workspace issue encountered", "Your workspace encountered an issue, but don’t worry, we’ve resolved it. " + "Your data is still intact, however your file revision history may have been lost. " + "Give us just a moment to complete the recovery so you can get back to your project. ", function() { setTimeout(function() { window.location.reload(); }, 1000); } ); break; default: if (!doc) return console.warn("[OT] Received msg for file that is not open", docId, msg); if (doc.loaded) doc.handleMessage(msg); else console.warn("[OT] Doc ", docId, " not yet inited - MSG:", msg); } } function notifyUserOffline(user) { clearTimeout(usersLeaving[user.fullname]); usersLeaving[user.fullname] = setTimeout(function() { if (!user.online) bubbleNotification("went offline", user); delete usersLeaving[user.fullname]; }, 4000); } function notifyUserOnline(user) { if (usersLeaving[user.fullname]) { clearTimeout(usersLeaving[user.fullname]); return; } if (user.online <= 1) bubbleNotification("came online", user); } function joinDocument(docId, doc, progress) { console.log("[OT] Join", docId); var docSession = doc.getSession(); var aceSession = docSession && docSession.session; if (!aceSession) console.warn("[OT] Ace session not ready for:", docId, "- will setSession when ready!"); var otDoc = documents[docId] || new OTDocument(docId, doc); if (aceSession) otDoc.setSession(aceSession); if (progress) setupProgressCallback(otDoc, progress); if (documents[docId]) return console.warn("[OT] Document previously joined -", docId, "STATE: loading:", otDoc.loading, "loaded:", otDoc.loaded, "inited:", otDoc.inited); documents[docId] = otDoc; if (connect.connected) otDoc.load(); return otDoc; } function setupProgressCallback(otDoc, progress) { otDoc.on("joinProgress", function(e) { progress && progress(e.loaded, e.total, e.complete); }); } function leaveDocument(docId) { if (!docId || !documents[docId] || !connect.connected) return; console.log("[OT] Leave", docId); var doc = documents[docId]; doc.leave(); // will also dispose delete documents[docId]; } function reportLargeDocument(doc, forceReadonly) { var docId = doc.id; delete documents[doc.id]; if (workspace.isAdmin && !forceReadonly) { if (workspace.onlineCount === 1) return console.log("File is very large, collaborative editing disabled: " + docId); return showError("File is very large, collaborative editing disabled: " + docId, 5000); } showError("File is very large. Collaborative editing disabled: " + docId, 5000); var tab = tabManager.findTab(docId); if (!tab || !tab.editor) return; tab.classList.add("error"); if (doc.readonly) return; doc.readonly = true; } function reportDocChangedOnDisk(path) { emit("change", { path: path, type: "change", }); } function reportDocHasPendingChanges(path) { var tab = tabManager.findTab(path); if (tab) { setTimeout(function() { tab.document.undoManager.bookmark(-2); }, 50); } } function saveDocument(docId, fallbackFn, fallbackArgs, callback) { var doc = documents[docId]; var joinError; clearTimeout(saveFallbackTimeouts[docId]); saveFallbackTimeouts[docId] = setTimeout(function() { console.warn("[OT] collab saveFallbackTimeout while trying to save file", docId, "- trying fallback approach instead"); fsSaveFallback(); doc.off("saved", onSaved); failedSaveAttempts++; emit("saveFallbackStart", { path: docId }); }, SAVE_FILESYSTEM_FALLBACK_TIMEOUT * Math.pow(2, -Math.min(failedSaveAttempts, 5))); function onSaved(e) { doc.off("saved", onSaved); clearTimeout(saveFallbackTimeouts[docId]); if (e.err) { if ((e.code == "ETIMEOUT" || e.code == "EMISMATCH") && fallbackFn) { console.warn("[OT] collab error:", e.code, "trying to save file", docId, "- trying fallback approach instead"); return fsSaveFallback({ code: e.code, err: e.err }); } else { sendSaveError({ code: e.code, err: e.err }, "Collab saving failed on unexpected error"); } } else { failedSaveAttempts = 0; } callback(e.err); } function fsSaveFallback(attempt) { var message = doc && doc.loaded ? "Warning: using fallback saving on loaded document" : "Warning: using fallback saving on unloaded document"; if (doc && doc.saveStateDebugging) { message = "Warning: using fallback saving due to save timeout"; } console.warn(message, attempt); fallbackFn.apply(null, fallbackArgs); } function sendSaveError(attempt, message) { errorHandler.reportError(new Error(message), { docId: docId, loading: doc && doc.loading, loaded: doc && doc.loaded, inited: doc && doc.inited, rejoinReason: doc && doc.rejoinReason, state: doc && doc.state, stateWhenSaveCalled: doc && doc.stateWhenSaveCalled, saveStateDebugging: doc && doc.saveStateDebugging, joinError: joinError, connected: connect.connected, attempt: attempt, failedSaveAttempts: failedSaveAttempts }, ["collab"]); } if (!doc.loaded || !connect.connected) { if (connect.connected && !doc.loaded && !doc.loading) { clearTimeout(saveFallbackTimeouts[docId]); fsSaveFallback("document not joined and not trying to join"); return; } doc.once("joined", function(e) { joinError = e && e.err; if (e && !e.err) doCollabSave(); }); } else { doCollabSave(); } function doCollabSave() { doc.on("saved", onSaved); doc.save(); } } function leaveAll() { Object.keys(documents).forEach(function(docId) { leaveDocument(docId); }); } function refreshActiveDocuments() { for (var docId in documents) { var doc = documents[docId]; var tab = doc.original.tab; if (tab.pane.activeTab === tab && doc.inited) doc.authorLayer.refresh(); } } function beforeReadFile(e) { var path = e.path; var progress = e.progress; var callback = e.callback; if (!path || e.tab.editorType != "ace") return; var otDoc = documents[path]; if (!otDoc) otDoc = documents[path] = joinDocument(path, e.tab.document, progress); else setupProgressCallback(otDoc, progress); otDoc.on("joined", onJoined); otDoc.on("largeDocument", reportLargeDocument.bind(null, otDoc)); otDoc.on("joinProgress", startWatchDog); otDoc.on("beforeSave", function(e) { emit("beforeSave", e); }); if (!connect.connected) { callback = null; return; } startWatchDog(); var fallbackXhrAbort; return { abort: function() { if (fallbackXhrAbort) fallbackXhrAbort(); else console.log("TODO: [OT] abort joining a document"); } }; function startWatchDog() { clearTimeout(openFallbackTimeouts[path]); openFallbackTimeouts[path] = setTimeout(function() { console.warn("[OT] JOIN_DOC timed out:", path, "- fallback to filesystem, but don't abort"); fsOpenFallback(); otDoc.off("joined", onJoined); }, OPEN_FILESYSTEM_FALLBACK_TIMEOUT); } function onJoined(e) { otDoc.off("joined", onJoined); clearTimeout(openFallbackTimeouts[path]); openFallbackTimeouts[path] = null; if (e.err) { if (e.err.code != "ENOENT" && e.err.code != "ELARGE") console.warn("[OT] JOIN_DOC failed:", path, "- fallback to filesystem"); return fsOpenFallback(); } console.log("[OT] Joined", otDoc.id); callback && callback(e.err, e.contents, e.metadata); } function fsOpenFallback() { var xhr = fs.readFileWithMetadata(path, "utf8", callback || function() {}, progress) || {}; fallbackXhrAbort = ((xhr && xhr.abort) || function() {}).bind(xhr); } } function afterReadFile(e) { var path = e.path; var tab = tabManager.findTab(path); var doc = documents[path]; if (!tab || !doc || doc.loaded) return; var httpLoadedValue = tab.document.value; var normHttpValue = collabUtil.normalizeTextLT(httpLoadedValue); if (httpLoadedValue !== normHttpValue) tab.document.value = normHttpValue; } function beforeWriteFile(e) { var path = e.path; var tab = tabManager.findTab(path); var doc = documents[path]; if (!doc || !tab) return; if (timeslider.visible) return false; var args = e.args.slice(); var progress = args.pop(); var callback = args.pop(); var defaultWriteFile = e.fn; saveDocument(path, defaultWriteFile, e.args, callback); return false; } function onSetPath(tab, oldpath, path) { console.log("[OT] detected rename/save as from", oldpath, "to", path); leaveDocument(oldpath); joinDocument(path, tab.document); documents[path].once("joined", function(e) { if (e.err) { leaveDocument(oldpath); setTimeout(joinDocument(path, tab.document), SAVE_FILESYSTEM_FALLBACK_TIMEOUT_REPEATED); } }); } function bubbleNotification(msg, user) { if (!user) return bubble.popup(msg); var md5Email = user.md5Email; console.log("Collab:", user.fullname, msg); bubble.popup([ ["img", { width: 26, height: 26, class: "gravatar-image", src: "https://secure.gravatar.com/avatar/" + md5Email + "?s=26&d=retro" }], ["span", null, user.fullname, ["span", { class: "notification_sub" }, msg]] ]); } function getTabState(tabId) { var tab; if (tabId) { tabManager.getTabs().some(function(t) { if (getTabId(t) == tabId) { return (tab = t); } }); } else { tab = tabManager.focussedTab; } if (!tab) return; var state = tab.getState(); var doc = state.document; if (doc) { doc.value = doc.undoManager = doc.meta = undefined; if (doc.ace) { doc.ace = { selection: doc.ace.selection }; } } state.className = undefined; return state; } function getTabId(tab) { if (!tab || !tab.document) return; var meta = tab.document.meta; if (meta.preview || meta.newfile) return; if (tab.editorType == "terminal") return "terminal:" + (tab.document.getState().terminal || {}).id; if (tab.editorType == "output") { var state = tab.document.getState().output; var config = state.config || {}; return "run-config:" + (config.name || state.id); } if (tab.editorType == "preview") return tab.name; if (tab.path) return tab.path; } var lastJump; function revealUser(clientId, tabId) { if (clientId == workspace.myClientId) { handleUserMessage({ action: "open", target: clientId, tabState: lastJump }); } else { connect.send("MESSAGE", { source: workspace.myClientId, target: clientId, action: "getTab", tabId: tabId }); } } function listOpenFiles(clientId) { connect.send("MESSAGE", { source: workspace.myClientId, target: clientId, action: "listOpenFiles" }); } function handleUserMessage(data) { if (data.action == "getTab") { if (data.target == workspace.myClientId) { connect.send("MESSAGE", { source: workspace.myClientId, target: data.source, action: "open", tabState: getTabState(data.tabId), }); } } else if (data.action == "open") { if (data.target == workspace.myClientId) { if (data.tabState) { var tabState = getTabState() || {}; if (shouldUpdateLastJump(lastJump, tabState, data.tabState)) lastJump = tabState; data.tabState.focus = true; if (data.tabState.document) delete data.tabState.document.filter; tabManager.open(data.tabState); } } } else if (data.action == "listOpenFiles") { if (data.fileList) { workspace.updateOpenDocs({ clientId: data.source, userId: data.userId, fileList: data.fileList }, "set"); } else if (data.target == workspace.myClientId) { var openFiles = tabManager.getTabs().map(function(tab) { return getTabId(tab); }).filter(Boolean); var active = openFiles.indexOf(getTabId(tabManager.focussedTab)); connect.send("MESSAGE", { userId: workspace.myUserId, source: workspace.myClientId, target: data.source, action: "listOpenFiles", fileList: { active: active, documents: openFiles } }); } } } function shouldUpdateLastJump(prevState, state, newState) { function getSelection(s) { return s && s.document && s.document.ace && s.document.ace.selection; } if (!prevState) return true; if (!newState.name) return false; var prevSel = JSON.stringify(getSelection(prevState)); var sel = JSON.stringify(getSelection(state)); var newSel = JSON.stringify(getSelection(newState)); if (prevState.name == state.name && newSel == sel) { return false; } if (state.name == newState.name && newSel == sel) return false; return true; } function scheduleUpdateUserBadges() { if (scheduleUpdateUserBadges.timer) return; scheduleUpdateUserBadges.timer = setTimeout(function() { scheduleUpdateUserBadges.timer = null; updateUserBadges(); }, 10); } function updateUserBadges() { var users = workspace.users; var myId = workspace.myUserId; Object.keys(users).forEach(function(id) { if (id == myId) return; var user = users[id]; if (!user.online) return menus.remove("user_" + id); if (menus.getMenuId("user_" + id)) return; addButton(id, user.fullname, user.md5Email); }); function addButton(uid, name, md5Email) { menus.remove("user_" + uid); var parent = layout.getElement("barExtras"); var mnuUser = new ui.menu(); plugin.addElement(mnuUser); var icon = util.getGravatarUrl(md5Email, 32, ""); menus.addItemByPath("user_" + uid + "/", mnuUser, 110000, plugin); var c = 500; menus.addItemByPath("user_" + uid + "/Open Active File", new ui.item({ onclick: function() { var user = workspace.users[uid]; revealUser(user.clients[0]); } }), c += 100, plugin); var button = menus.get("user_" + uid).item; button.setAttribute("class", "btnName"); button.setAttribute("icon", icon); button.setAttribute("iconsize", "16px 16px"); button.setAttribute("tooltip", name); if (options.showFullNameInMenuBar) { button.setAttribute("caption", name); } if (button.$ext) button.$ext.style.color = collabUtil.formatColor(workspace.colorPool[uid]); ui.insertByIndex(parent, button, 550, plugin); } } plugin.on("newListener", function(event, listener) { if (event == "connect" && connect.connected) listener(); }); plugin.on("load", function() { load(); }); plugin.on("draw", function(e) { draw(e); }); plugin.on("unload", function() { loaded = false; drawn = true; }); plugin.freezePublicAPI({ _events: [ "drawPanels", "connect", "chatMessage", "beforeSave", "message" ], get documents() { return util.cloneObject(documents); }, get connected() { return connect.connected; }, get debug() { return connect.debug; }, getDocument: function (path) { return documents[path]; }, send: function(type, message) { connect.send(type, message); }, revealUser: revealUser, listOpenFiles: listOpenFiles, leaveDocument: leaveDocument, joinDocument: joinDocument, }); register(null, { "collab": plugin }); } }); define("plugins/c9.ide.collab/connect",[], function(require, exports, module) { main.consumes = [ "c9", "Plugin", "ext", "vfs", "dialog.question", "installer" ]; main.provides = ["collab.connect"]; return main; function main(options, imports, register) { var Plugin = imports.Plugin; var c9 = imports.c9; var ext = imports.ext; var vfs = imports.vfs; var installer = imports.installer; var question = imports["dialog.question"]; var plugin = new Plugin("Ajax.org", main.consumes); var emit = plugin.getEmitter(); var clientId; var debug = options.debug; var collab; var collabInstalled = !options.isSSH; var connecting = false; var connected = false; var isMaster = null; var fatalError = false; var CONNECT_TIMEOUT = 30000; // 30 seconds var IDLE_PERIOD = 300000; // 5 minutes var connectMsg; var connectTimeout; var stream; var focussed = true; var reportedIdle = false; var idleTimeout; var loaded = false; function load() { if (!installer.isInstalled("c9.ide.collab", function() { load(); })) return; if (loaded) return; loaded = true; if (c9.connected) connect(); window.addEventListener("focus", updateIdleWithFocus); window.addEventListener("blur", updateIdleWithBlur); c9.on("connect", connect); c9.on("disconnect", onDisconnect); } function updateIdleWithFocus() { focussed = true; clearTimeout(idleTimeout); if (!connected || !reportedIdle) return; send("USER_STATE", { state: "online" }); reportedIdle = false; } function updateIdleWithBlur() { focussed = false; if (reportedIdle) return; clearTimeout(idleTimeout); idleTimeout = setTimeout(function() { if (!connected) return; reportedIdle = true; send("USER_STATE", { state: "idle" }); }, IDLE_PERIOD); } function updateIdleStatus() { if (document.hasFocus()) updateIdleWithFocus(); else updateIdleWithBlur(); } var extended = false; function extendCollab(callback) { if (collab) return callback(); var t = debug && Date.now(); if (extended) return plugin.once("available", callback); extended = true; ext.loadRemotePlugin("collab", { file: "c9.ide.collab/server/collab-server.js" }, function(err, api) { if (!api) { extended = false; return callback(err); } if (debug) console.log("loaded collab server in ", Date.now() - t, "ms"); collab = api; emit.sticky("available"); callback(); }); } function onDisconnect() { if (connected || connecting) emit("disconnect"); else console.log("Collab already disconnected"); connecting = connected = extended = false; emit.unsticky("available"); collab = null; if (stream) { stream.$close(); stream = null; } clearTimeout(connectTimeout); } function connect() { if (fatalError) return; if (connected) { console.log("Collab already connected, ignoring reconnection attempt"); return; } if (connecting) return; connecting = true; console.log("Collab connecting"); emit("connecting"); connectTimeout = setTimeout(function() { if (stream) { stream.$close(); stream = null; } connecting = false; if (!connected) { console.warn("[OT] Collab connect timed out ! - retrying ..."); connect(); } }, CONNECT_TIMEOUT); extendCollab(function(err) { if (err) return console.error("COLLAB CONNECT ERR", err); if (collabInstalled) return doConnect(); }); } function doConnect() { clientId = vfs.id; collab.connect({ basePath: options.basePath, clientId: clientId }, function (err, meta) { if (err) { fatalError = err.code === "EFATAL"; console.error("COLLAB connect failed", err); if (fatalError) promptInstaller(err); return; } stream = meta.stream; var isClosed = false; stream.once("data", onConnect); stream.once("end", function () { console.log("COLLAB STREAM END"); onClose(); }); stream.once("close", function() { console.log("COLLAB STREAM CLOSE"); onClose(); }); stream.$close = onClose; function onData(data) { data = JSON.parse(data); if (debug) console.log("[OT] RECEIVED FROM SERVER", data); emit("message", data); } function onConnect(data) { if (isClosed || !collab) return onClose(); data = JSON.parse(data); if (debug) console.log("[OT] RECEIVED FROM SERVER", data); if (data.type !== "CONNECT") return console.log("[OT] Waiting for connect event, skipping message", data); connected = true; connecting = false; isMaster = meta.isMaster; connectMsg = data; console.log("COLLAB connected -", meta.isMaster ? "MASTER" : "SLAVE"); emit("connect", data); stream.on("data", onData); clearTimeout(connectTimeout); updateIdleStatus(); } function onClose() { if (isClosed) return; if (stream) { stream.off("data", onData); stream.destroy(); } isClosed = true; onDisconnect(); setTimeout(function() { c9.connected && connect(); }, 1000); } }); } function send(msg) { if (typeof arguments[0] !== "object") msg = { type: arguments[0], data: arguments[1] }; if (!connected) return console.log("Collab not connected - SKIPPING ", msg); if (debug) console.log("[OT] SENDING TO SERVER", msg); collab.send(clientId, msg); } function promptInstaller(err) { question.show("Missing collab dependencies", err.message, "Cloud9 detected you are missing one or more collab dependencies." + " Would you like to open the installer to update to the latest version?", function() { // Yes installer.reinstall("c9.ide.collab"); }, function() { // No }, { yes: "Update", no: "Not now" } ); } plugin.on("load", function() { load(); }); plugin.on("enable", function() { }); plugin.on("disable", function() { }); plugin.on("unload", function() { loaded = false; }); plugin.on("newListener", function(event, listener) { if (event == "connect" && connected && connectMsg) listener(null, connectMsg); else if (event == "connecting" && connecting) listener(); }); plugin.freezePublicAPI({ _events: [ "available", "connect", "connecting", "disconnect", "message" ], get debug() { return debug; }, get connected() { return connected; }, get connecting() { return connecting; }, get isMaster() { return isMaster; }, send: send }); register(null, { "collab.connect": plugin }); } }); define("plugins/c9.ide.language.jsonalyzer/mock_collab",[], function(require, exports, module) { "use strict"; main.consumes = ["Plugin"]; main.provides = ["collab", "collab.connect", "collab.workspace"]; return main; function main(options, imports, register) { var Plugin = imports.Plugin; var plugin = new Plugin("Ajax.org", main.consumes); plugin.freezePublicAPI({ get isMaster() { return true; }, get isAdmin() { return true; } }); register(null, { collab: plugin, "collab.connect": plugin, "collab.workspace": plugin, }); } }); define("plugins/c9.ide.services/linked-services-mock",[], function(require, exports, module) { "use strict"; main.consumes = ["Plugin"]; main.provides = ["linked-services"]; return main; function main(options, imports, register) { var Plugin = imports.Plugin; var plugin = new Plugin("Ajax.org", main.consumes); function getServices(callback) { setTimeout(function() { callback(null, options.services || { "github": { "visible": true, "hasRepositories": true, "service": "github", "title": "GitHub", "accounts": [], "maxAccounts": 1, "maxProjects": 100 } }); }, 0); } function getAccessToken(serviceId, callback) { callback(new Error("Not Implemented")); } plugin.freezePublicAPI({ getServices: getServices, getAccessToken: getAccessToken }); register(null, { "linked-services": plugin }); } }); define("plugins/c9.ide.analytics/mock_analytics",[], function(require, exports, module) { "use strict"; main.consumes = ["Plugin"]; main.provides = ["c9.analytics"]; return main; function main(options, imports, register) { var Plugin = imports.Plugin; var plugin = new Plugin("Ajax.org", main.consumes); plugin.freezePublicAPI({ log: function() {}, updateTraits: function() {}, alias: function() {}, identify: function() {}, track: function() {}, page: function() {} }); register(null, { "c9.analytics": plugin }); } }); define("plugins/c9.ide.errorhandler/simple_error_handler",[], function(require, exports, module) { "use strict"; main.consumes = [ "Plugin", ]; main.provides = ["error_handler"]; return main; function main(options, imports, register) { var Plugin = imports.Plugin; var plugin = new Plugin("Ajax.org", main.consumes); var emit = plugin.getEmitter(); var loaded = false; function load() { if (loaded) return false; loaded = true; if ( location.protocol !== "file:" && location.href.indexOf("dev") === -1 && (location.href.indexOf("c9.io") > -1)) { var oldOnError = window.onerror; window.onerror = function(m, u, l) { var errorInfo = { agent: navigator.userAgent, type: "General Javascript Error", e: [m, u, l], workspaceId: plugin.workspaceId }; emit("error", errorInfo); submitError(errorInfo); if (oldOnError) oldOnError.apply(this, arguments); }; } } function submitError(errorInfo) { } function reportError(exception, customData) { if (customData) console.error(exception, customData); else console.error(exception.stack || exception); submitError(exception); } plugin.on("load", function() { load(); }); plugin.on("unload", function() { loaded = false; }); plugin.freezePublicAPI({ reportError: reportError, log: reportError }); register(null, { "error_handler": plugin }); } }); define("plugins/c9.ide.errorhandler/raygun",[], function(require, exports, module) { (function(window, undefined) { var TraceKit = {}; var _oldTraceKit = window.TraceKit; var _slice = [].slice; var UNKNOWN_FUNCTION = '?'; function _has(object, key) { return Object.prototype.hasOwnProperty.call(object, key); } function _isUndefined(what) { return typeof what === 'undefined'; } TraceKit.noConflict = function noConflict() { window.TraceKit = _oldTraceKit; return TraceKit; }; TraceKit.wrap = function traceKitWrapper(func) { function wrapped() { try { return func.apply(this, arguments); } catch (e) { TraceKit.report(e); throw e; } } return wrapped; }; TraceKit.report = (function reportModuleWrapper() { var handlers = [], lastException = null, lastExceptionStack = null; function subscribe(handler) { handlers.push(handler); } function unsubscribe(handler) { for (var i = handlers.length - 1; i >= 0; --i) { if (handlers[i] === handler) { handlers.splice(i, 1); } } } function notifyHandlers(stack, windowError) { var exception = null; if (windowError && !TraceKit.collectWindowErrors) { return; } for (var i in handlers) { if (_has(handlers, i)) { try { handlers[i].apply(null, [stack].concat(_slice.call(arguments, 2))); } catch (inner) { exception = inner; } } } if (exception) { throw exception; } } var _oldOnerrorHandler = window.onerror; window.onerror = function traceKitWindowOnError(message, url, lineNo, columnNo, errorObj) { var stack = null; if (errorObj) { stack = TraceKit.computeStackTrace(errorObj); } else { if (lastExceptionStack) { errorObj = lastException; TraceKit.computeStackTrace.augmentStackTraceWithInitialElement(lastExceptionStack, url, lineNo, message); stack = lastExceptionStack; lastExceptionStack = null; lastException = null; } else { var location = { 'url': url, 'line': lineNo, 'column': columnNo }; location.func = TraceKit.computeStackTrace.guessFunctionName(location.url, location.line); location.context = TraceKit.computeStackTrace.gatherContext(location.url, location.line); stack = { 'mode': 'onerror', 'message': message, 'url': document.location.href, 'stack': [location], 'useragent': navigator.userAgent }; } } notifyHandlers(stack, 'from window.onerror', { errorObj: errorObj }); if (_oldOnerrorHandler) { return _oldOnerrorHandler.apply(this, arguments); } return false; }; function report(ex) { var args = _slice.call(arguments, 0); if (lastExceptionStack) { if (lastException === ex) { return; // already caught by an inner catch block, ignore } else { var s = lastExceptionStack; lastExceptionStack = null; lastException = null; notifyHandlers.apply(null, [s, null].concat(args)); } } var stack = TraceKit.computeStackTrace(ex); lastExceptionStack = stack; lastException = ex; window.setTimeout(function () { if (lastException === ex) { lastExceptionStack = null; lastException = null; notifyHandlers.apply(null, [stack, null].concat(args)); } }, (stack.incomplete ? 2000 : 0)); throw ex; // re-throw to propagate to the top level (and cause window.onerror) } report.subscribe = subscribe; report.unsubscribe = unsubscribe; return report; }()); TraceKit.computeStackTrace = (function computeStackTraceWrapper() { var debug = false, sourceCache = {}; function loadSource(url) { if (!TraceKit.remoteFetching) { //Only attempt request if remoteFetching is on. return ''; } try { function getXHR() { try { return new window.XMLHttpRequest(); } catch (e) { return new window.ActiveXObject('Microsoft.XMLHTTP'); } } var request = getXHR(); request.open('GET', url, false); request.send(''); return request.responseText; } catch (e) { return ''; } } function getSource(url) { if (!_has(sourceCache, url)) { var source = ''; url = url || ""; if (url.indexOf(document.domain) !== -1) { source = loadSource(url); } sourceCache[url] = source ? source.split('\n') : []; } return sourceCache[url]; } function guessFunctionName(url, lineNo) { var reFunctionArgNames = /function ([^(]*)\(([^)]*)\)/, reGuessFunction = /['"]?([0-9A-Za-z$_]+)['"]?\s*[:=]\s*(function|eval|new Function)/, line = '', maxLines = 10, source = getSource(url), m; if (!source.length) { return UNKNOWN_FUNCTION; } for (var i = 0; i < maxLines; ++i) { line = source[lineNo - i] + line; if (!_isUndefined(line)) { if ((m = reGuessFunction.exec(line))) { return m[1]; } else if ((m = reFunctionArgNames.exec(line))) { return m[1]; } } } return UNKNOWN_FUNCTION; } function gatherContext(url, line) { var source = getSource(url); if (!source.length) { return null; } var context = [], linesBefore = Math.floor(TraceKit.linesOfContext / 2), linesAfter = linesBefore + (TraceKit.linesOfContext % 2), start = Math.max(0, line - linesBefore - 1), end = Math.min(source.length, line + linesAfter - 1); line -= 1; // convert to 0-based index for (var i = start; i < end; ++i) { if (!_isUndefined(source[i])) { context.push(source[i]); } } return context.length > 0 ? context : null; } function escapeRegExp(text) { return text.replace(/[\-\[\]{}()*+?.,\\\^$|#]/g, '\\$&'); } function escapeCodeAsRegExpForMatchingInsideHTML(body) { return escapeRegExp(body).replace('<', '(?:<|<)').replace('>', '(?:>|>)').replace('&', '(?:&|&)').replace('"', '(?:"|")').replace(/\s+/g, '\\s+'); } function findSourceInUrls(re, urls) { var source, m; for (var i = 0, j = urls.length; i < j; ++i) { if ((source = getSource(urls[i])).length) { source = source.join('\n'); if ((m = re.exec(source))) { return { 'url': urls[i], 'line': source.substring(0, m.index).split('\n').length, 'column': m.index - source.lastIndexOf('\n', m.index) - 1 }; } } } return null; } function findSourceInLine(fragment, url, line) { var source = getSource(url), re = new RegExp('\\b' + escapeRegExp(fragment) + '\\b'), m; line -= 1; if (source && source.length > line && (m = re.exec(source[line]))) { return m.index; } return null; } function findSourceByFunctionBody(func) { var urls = [window.location.href], scripts = document.getElementsByTagName('script'), body, code = '' + func, codeRE = /^function(?:\s+([\w$]+))?\s*\(([\w\s,]*)\)\s*\{\s*(\S[\s\S]*\S)\s*\}\s*$/, eventRE = /^function on([\w$]+)\s*\(event\)\s*\{\s*(\S[\s\S]*\S)\s*\}\s*$/, re, parts, result; for (var i = 0; i < scripts.length; ++i) { var script = scripts[i]; if (script.src) { urls.push(script.src); } } if (!(parts = codeRE.exec(code))) { re = new RegExp(escapeRegExp(code).replace(/\s+/g, '\\s+')); } else { var name = parts[1] ? '\\s+' + parts[1] : '', args = parts[2].split(',').join('\\s*,\\s*'); body = escapeRegExp(parts[3]).replace(/;$/, ';?'); // semicolon is inserted if the function ends with a comment.replace(/\s+/g, '\\s+'); re = new RegExp('function' + name + '\\s*\\(\\s*' + args + '\\s*\\)\\s*{\\s*' + body + '\\s*}'); } if ((result = findSourceInUrls(re, urls))) { return result; } if ((parts = eventRE.exec(code))) { var event = parts[1]; body = escapeCodeAsRegExpForMatchingInsideHTML(parts[2]); re = new RegExp('on' + event + '=[\\\'"]\\s*' + body + '\\s*[\\\'"]', 'i'); if ((result = findSourceInUrls(re, urls[0]))) { return result; } re = new RegExp(body); if ((result = findSourceInUrls(re, urls))) { return result; } } return null; } // // // // // function computeStackTraceFromStackProp(ex) { if (!ex.stack) { return null; } var chrome = /^\s*at (?:((?:\[object object\])?\S+) )?\(?((?:file|http|https):.*?):(\d+)(?::(\d+))?\)?\s*$/i, gecko = /^\s*(\S*)(?:\((.*?)\))?@((?:file|http|https).*?):(\d+)(?::(\d+))?\s*$/i, winjs = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:ms-appx|http|https):.*?):(\d+)(?::(\d+))?\)?\s*$/i, lines = ex.stack.split('\n'), stack = [], parts, element, reference = /^(.*) is undefined$/.exec(ex.message); for (var i = 0, j = lines.length; i < j; ++i) { if ((parts = gecko.exec(lines[i]))) { element = { 'url': parts[3], 'func': parts[1] || UNKNOWN_FUNCTION, 'args': parts[2] ? parts[2].split(',') : '', 'line': +parts[4], 'column': parts[5] ? +parts[5] : null }; } else if ((parts = chrome.exec(lines[i]))) { element = { 'url': parts[2], 'func': parts[1] || UNKNOWN_FUNCTION, 'line': +parts[3], 'column': parts[4] ? +parts[4] : null }; } else if ((parts = winjs.exec(lines[i]))) { element = { 'url': parts[2], 'func': parts[1] || UNKNOWN_FUNCTION, 'line': +parts[3], 'column': parts[4] ? +parts[4] : null }; } else { continue; } if (!element.func && element.line) { element.func = guessFunctionName(element.url, element.line); } if (element.line) { element.context = gatherContext(element.url, element.line); } stack.push(element); } if (stack[0] && stack[0].line && !stack[0].column && reference) { stack[0].column = findSourceInLine(reference[1], stack[0].url, stack[0].line); } if (!stack.length) { return null; } return { 'mode': 'stack', 'name': ex.name, 'message': ex.message, 'url': document.location.href, 'stack': stack, 'useragent': navigator.userAgent }; } function computeStackTraceFromStacktraceProp(ex) { var stacktrace = ex.stacktrace; var testRE = / line (\d+), column (\d+) in (?:]+)>|([^\)]+))\((.*)\) in (.*):\s*$/i, lines = stacktrace.split('\n'), stack = [], parts; for (var i = 0, j = lines.length; i < j; i += 2) { if ((parts = testRE.exec(lines[i]))) { var element = { 'line': +parts[1], 'column': +parts[2], 'func': parts[3] || parts[4], 'args': parts[5] ? parts[5].split(',') : [], 'url': parts[6] }; if (!element.func && element.line) { element.func = guessFunctionName(element.url, element.line); } if (element.line) { try { element.context = gatherContext(element.url, element.line); } catch (exc) {} } if (!element.context) { element.context = [lines[i + 1]]; } stack.push(element); } } if (!stack.length) { return null; } return { 'mode': 'stacktrace', 'name': ex.name, 'message': ex.message, 'url': document.location.href, 'stack': stack, 'useragent': navigator.userAgent }; } function computeStackTraceFromOperaMultiLineMessage(ex) { // var lines = ex.message.split('\n'); if (lines.length < 4) { return null; } var lineRE1 = /^\s*Line (\d+) of linked script ((?:file|http|https)\S+)(?:: in function (\S+))?\s*$/i, lineRE2 = /^\s*Line (\d+) of inline#(\d+) script in ((?:file|http|https)\S+)(?:: in function (\S+))?\s*$/i, lineRE3 = /^\s*Line (\d+) of function script\s*$/i, stack = [], scripts = document.getElementsByTagName('script'), inlineScriptBlocks = [], parts, i, len, source; for (i in scripts) { if (_has(scripts, i) && !scripts[i].src) { inlineScriptBlocks.push(scripts[i]); } } for (i = 2, len = lines.length; i < len; i += 2) { var item = null; if ((parts = lineRE1.exec(lines[i]))) { item = { 'url': parts[2], 'func': parts[3], 'line': +parts[1] }; } else if ((parts = lineRE2.exec(lines[i]))) { item = { 'url': parts[3], 'func': parts[4] }; var relativeLine = (+parts[1]); // relative to the start of the