kopia lustrzana https://github.com/c9/core
commit
59eb6c51d6
|
@ -630,7 +630,7 @@ define(function(require, module, exports) {
|
|||
if (!loaded || tab.document.meta.preview)
|
||||
return;
|
||||
|
||||
var lastTab = focussedTab;
|
||||
var lastTab = e.lastTab || focussedTab;
|
||||
|
||||
if (!focussedTab || focussedTab.pane == tab.pane && focussedTab != tab)
|
||||
focusTab(tab, true, true);
|
||||
|
|
|
@ -1,154 +1,201 @@
|
|||
define(function(require, exports, module) {
|
||||
main.consumes = [
|
||||
"Plugin", "c9", "ui", "layout", "tooltip",
|
||||
"anims", "menus", "tabManager", "save",
|
||||
"preferences.experimental"
|
||||
"Plugin", "c9", "settings", "tabManager", "preferences.experimental", "save", "apf"
|
||||
];
|
||||
main.provides = ["autosave"];
|
||||
return main;
|
||||
|
||||
function main(options, imports, register) {
|
||||
var c9 = imports.c9;
|
||||
var Plugin = imports.Plugin;
|
||||
var apf = imports.apf;
|
||||
var save = imports.save;
|
||||
var tooltip = imports.tooltip;
|
||||
var tabs = imports.tabManager;
|
||||
var experimental = imports["preferences.experimental"];
|
||||
var prefs = imports["preferences.experimental"];
|
||||
var Plugin = imports.Plugin;
|
||||
var settings = imports.settings;
|
||||
|
||||
var lang = require("ace/lib/lang");
|
||||
|
||||
/***** Initialization *****/
|
||||
|
||||
var plugin = new Plugin("Ajax.org", main.consumes);
|
||||
|
||||
var INTERVAL = 60000;
|
||||
var CHANGE_TIMEOUT = 500;
|
||||
var CHANGE_TIMEOUT = options.changeTimeout || 1000;
|
||||
var SLOW_CHANGE_TIMEOUT = options.slowChangeTimeout || 30000;
|
||||
var SLOW_SAVE_THRESHOLD = 100 * 1024; // 100KB
|
||||
|
||||
var docChangeTimeout = null;
|
||||
var btnSave, autosave = true, saveInterval;
|
||||
var enabled = options.testing
|
||||
|| experimental.addExperiment("autosave", false, "Files/Auto-Save");
|
||||
var docChangeTimeout;
|
||||
var lastSaveTime = 0;
|
||||
var sessionId;
|
||||
var autosave;
|
||||
var saveWhenIdle;
|
||||
|
||||
var loaded = false;
|
||||
function load() {
|
||||
if (loaded || !enabled) return false;
|
||||
loaded = true;
|
||||
|
||||
// when we're back online we'll trigger an autosave if enabled
|
||||
c9.on("stateChange", function(e) {
|
||||
if (e.state & c9.STORAGE && !(e.last & c9.STORAGE))
|
||||
check();
|
||||
}, plugin);
|
||||
|
||||
save.getElement("btnSave", function(btn) {
|
||||
btnSave = btn;
|
||||
transformButton();
|
||||
});
|
||||
|
||||
tabs.on("tabCreate", function(e) {
|
||||
var tab = e.tab;
|
||||
tab.document.undoManager.on("change", function(e) {
|
||||
if (!autosave || !tab.path)
|
||||
return;
|
||||
|
||||
clearTimeout(docChangeTimeout);
|
||||
docChangeTimeout = setTimeout(function() {
|
||||
saveTab(tab);
|
||||
}, tab.document.meta.$slowSave
|
||||
? SLOW_CHANGE_TIMEOUT
|
||||
: CHANGE_TIMEOUT);
|
||||
}, plugin);
|
||||
}, plugin);
|
||||
|
||||
tabs.on("tabDestroy", function(e) {
|
||||
if (!e.tab.path)
|
||||
return;
|
||||
|
||||
if (tabs.getTabs().length == 1)
|
||||
btnSave.hide();
|
||||
|
||||
saveTab(e.tab);
|
||||
}, plugin);
|
||||
|
||||
save.on("beforeWarn", function(e) {
|
||||
if (autosave && !e.tab.document.meta.newfile) {
|
||||
saveTab(e.tab);
|
||||
return false;
|
||||
prefs.add({
|
||||
"File": {
|
||||
position: 150,
|
||||
"Save": {
|
||||
position: 100,
|
||||
"Auto-Save Files": {
|
||||
type: "dropdown",
|
||||
position: 100,
|
||||
path: "user/general/@autosave",
|
||||
width: 130,
|
||||
items: [
|
||||
{ caption: "Off", value: false },
|
||||
{ caption: "On Focus Change", value: "onFocusChange" },
|
||||
{ caption: "After Delay", value: "afterDelay" },
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
}, plugin);
|
||||
}
|
||||
|
||||
function transformButton() {
|
||||
if (!btnSave) return;
|
||||
if (btnSave.autosave === autosave) return;
|
||||
|
||||
if (autosave) {
|
||||
// Transform btnSave
|
||||
btnSave.setAttribute("caption", "");
|
||||
btnSave.setAttribute("margin", "0 20");
|
||||
btnSave.removeAttribute("tooltip");
|
||||
btnSave.removeAttribute("command");
|
||||
apf.setStyleClass(btnSave.$ext, "btnSave");
|
||||
|
||||
tooltip.add(btnSave, {
|
||||
message: "Changes to your file are automatically saved.<br />\
|
||||
View all your changes through <a href='javascript:void(0)' \
|
||||
onclick='require(\"ext/revisions/revisions\").toggle();' \
|
||||
class='revisionsInfoLink'>the Revision History pane</a>. \
|
||||
Rollback to a previous state, or make comparisons.",
|
||||
width: "250px",
|
||||
hideonclick: true
|
||||
}, plugin);
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
|
||||
btnSave.autosave = autosave;
|
||||
settings.setDefaults("user/general", [["autosave", false]]);
|
||||
settings.on("read", onSettingChange, plugin);
|
||||
settings.on("user/general", onSettingChange, plugin);
|
||||
save.on("beforeWarn", function(e) {
|
||||
if (autosave && saveTab(e.tab))
|
||||
return false;
|
||||
}, plugin);
|
||||
}
|
||||
|
||||
/***** Helpers *****/
|
||||
|
||||
function check() {
|
||||
if (!autosave) return;
|
||||
|
||||
function onSettingChange() {
|
||||
autosave = settings.get("user/general/@autosave");
|
||||
if (autosave == "off" || autosave == "false")
|
||||
autosave = false;
|
||||
|
||||
var pages = tabs.getTabs();
|
||||
for (var tab, i = 0, l = pages.length; i < l; i++) {
|
||||
if ((tab = pages[i]).document.changed && tab.path)
|
||||
disable();
|
||||
if (autosave == "afterDelay")
|
||||
enableDelay();
|
||||
if (autosave)
|
||||
enable();
|
||||
}
|
||||
|
||||
function enableDelay() {
|
||||
saveWhenIdle = lang.delayedCall(function() {
|
||||
var tab = tabs.focussedTab;
|
||||
var ace = tab && tab.editor && tab.editor.ace;
|
||||
if (ace && ace.session && sessionId == ace.session.id) {
|
||||
saveTab(tab);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function enable() {
|
||||
apf.on("movefocus", scheduleCheck);
|
||||
tabs.on("tabAfterActivate", scheduleCheck, plugin);
|
||||
if (saveWhenIdle)
|
||||
tabs.on("focusSync", attachToTab, plugin);
|
||||
window.addEventListener("blur", scheduleCheck);
|
||||
}
|
||||
|
||||
function disable() {
|
||||
sessionId = null;
|
||||
if (saveWhenIdle) {
|
||||
saveWhenIdle.cancel();
|
||||
saveWhenIdle = null;
|
||||
}
|
||||
if (docChangeTimeout) {
|
||||
clearTimeout(docChangeTimeout);
|
||||
docChangeTimeout = null;
|
||||
}
|
||||
apf.off("movefocus", scheduleCheck);
|
||||
tabs.off("tabAfterActivate", scheduleCheck);
|
||||
tabs.off("focusSync", attachToTab);
|
||||
window.removeEventListener("blur", scheduleCheck);
|
||||
}
|
||||
|
||||
function attachToTab(e) {
|
||||
var ace = e.tab && e.tab.editor && e.tab.editor.ace;
|
||||
if (ace)
|
||||
ace.on("beforeEndOperation", beforeEndOperation);
|
||||
}
|
||||
|
||||
function beforeEndOperation(e, ace) {
|
||||
if (!saveWhenIdle)
|
||||
return ace.off("beforeEndOperation", beforeEndOperation);
|
||||
if (!ace.isFocused() && !options.ignoreFocusForTesting)
|
||||
return;
|
||||
sessionId = ace.session.id;
|
||||
if (sessionId && ace.curOp.docChanged && ace.curOp.command.name) {
|
||||
var timeout = Math.min(Math.max(CHANGE_TIMEOUT, lastSaveTime || 0), SLOW_CHANGE_TIMEOUT);
|
||||
saveWhenIdle.delay(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
function scheduleCheck(e) {
|
||||
if (docChangeTimeout)
|
||||
return;
|
||||
var tab;
|
||||
var fromElement = e.fromElement;
|
||||
var toElement = e.toElement;
|
||||
if (e.type == "blur") {
|
||||
tab = tabs.focussedTab;
|
||||
}
|
||||
else if (fromElement) {
|
||||
var fakePage = fromElement.$fake;
|
||||
if (toElement && (toElement == fakePage || fromElement == toElement.$fake)) {
|
||||
fakePage = fromElement.$prevFake || toElement.$prevFake;
|
||||
if (fakePage)
|
||||
return;
|
||||
}
|
||||
|
||||
tab = fromElement.cloud9tab || fakePage && fakePage.cloud9tab;
|
||||
if (!tab || !tab.path)
|
||||
return;
|
||||
while (toElement) {
|
||||
if (/window|menu|item/.test(toElement.localName))
|
||||
return;
|
||||
toElement = toElement.parentNode;
|
||||
}
|
||||
}
|
||||
else if (e.lastTab) {
|
||||
tab = e.lastTab;
|
||||
}
|
||||
if (!tab || !tab.path)
|
||||
return;
|
||||
|
||||
docChangeTimeout = setTimeout(function() {
|
||||
docChangeTimeout = null;
|
||||
var activeElement = apf.document.activeElement;
|
||||
var nodeName = activeElement && activeElement.localName;
|
||||
// do nothing if the tab is still focused, or is a clone of the focussed tab
|
||||
if (nodeName === "page" && tabs.focussedTab && tabs.focussedTab.path === tab.path)
|
||||
return;
|
||||
saveTab(tab);
|
||||
});
|
||||
}
|
||||
|
||||
function saveTab(tab, force) {
|
||||
if (!autosave) return;
|
||||
|
||||
if (!c9.has(c9.STORAGE)) {
|
||||
save.setSavingState(tab, "offline");
|
||||
return;
|
||||
}
|
||||
|
||||
var doc;
|
||||
if (!force && (!tab.path
|
||||
|| !(doc = tab.document).changed
|
||||
|| doc.meta.newfile
|
||||
|| doc.meta.nofs
|
||||
|| doc.meta.error
|
||||
|| doc.meta.$saving))
|
||||
|| doc.meta.$saving
|
||||
|| doc.meta.preview
|
||||
|| !doc.hasValue()))
|
||||
return;
|
||||
|
||||
var value = doc.value;
|
||||
var slow = value.length > SLOW_SAVE_THRESHOLD;
|
||||
if (slow && !doc.meta.$slowSave) {
|
||||
doc.meta.$slowSave = true;
|
||||
|
||||
if (!c9.has(c9.STORAGE)) {
|
||||
save.setSavingState(tab, "offline");
|
||||
return;
|
||||
}
|
||||
doc.meta.$slowSave = slow;
|
||||
|
||||
|
||||
var t = Date.now();
|
||||
save.save(tab, {
|
||||
silentsave: true,
|
||||
timeout: 1,
|
||||
value: value
|
||||
}, function() {});
|
||||
noUi: true,
|
||||
}, function() {
|
||||
lastSaveTime = t - Date.now();
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/***** Lifecycle *****/
|
||||
|
@ -156,27 +203,16 @@ define(function(require, exports, module) {
|
|||
plugin.on("load", function() {
|
||||
load();
|
||||
});
|
||||
plugin.on("enable", function() {
|
||||
autosave = true;
|
||||
transformButton();
|
||||
});
|
||||
plugin.on("disable", function() {
|
||||
autosave = false;
|
||||
transformButton();
|
||||
});
|
||||
plugin.on("unload", function() {
|
||||
if (saveInterval)
|
||||
clearInterval(saveInterval);
|
||||
|
||||
loaded = false;
|
||||
disable();
|
||||
autosave = false;
|
||||
});
|
||||
|
||||
/***** Register and define API *****/
|
||||
|
||||
/**
|
||||
* Implements auto save for Cloud9. When the user enables autosave
|
||||
* the contents of files are automatically saved about 500ms after the
|
||||
* change is made.
|
||||
* the contents of files are automatically saved when the editor is blurred
|
||||
* @singleton
|
||||
**/
|
||||
plugin.freezePublicAPI({ });
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
"use client";
|
||||
|
||||
require(["lib/architect/architect", "lib/chai/chai", "/vfs-root"],
|
||||
function (architect, chai, baseProc) {
|
||||
require(["lib/chai/chai"], function (chai) {
|
||||
var expect = chai.expect;
|
||||
|
||||
document.body.appendChild(document.createElement("div"))
|
||||
|
@ -16,7 +15,6 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root"],
|
|||
debug: true,
|
||||
hosted: true,
|
||||
local: false,
|
||||
davPrefix: "/"
|
||||
},
|
||||
|
||||
"plugins/c9.core/ext",
|
||||
|
@ -37,7 +35,7 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root"],
|
|||
"plugins/c9.ide.editors/undomanager",
|
||||
{
|
||||
packagePath: "plugins/c9.ide.editors/editors",
|
||||
defaultEditor: "texteditor"
|
||||
defaultEditor: "ace"
|
||||
},
|
||||
"plugins/c9.ide.editors/editor",
|
||||
"plugins/c9.ide.editors/tabmanager",
|
||||
|
@ -48,17 +46,17 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root"],
|
|||
"plugins/c9.ide.save/save",
|
||||
{
|
||||
packagePath: "plugins/c9.ide.save/autosave",
|
||||
testing: true
|
||||
ignoreFocusForTesting: true,
|
||||
changeTimeout: 5,
|
||||
},
|
||||
{
|
||||
packagePath: "plugins/c9.vfs.client/vfs_client"
|
||||
packagePath: "plugins/c9.vfs.client/vfs_client_mock",
|
||||
storage: false
|
||||
},
|
||||
"plugins/c9.vfs.client/endpoint",
|
||||
"plugins/c9.ide.auth/auth",
|
||||
"plugins/c9.core/api",
|
||||
{
|
||||
packagePath: "plugins/c9.fs/fs",
|
||||
baseProc: baseProc
|
||||
cli: true
|
||||
},
|
||||
"plugins/c9.fs/fs.cache.xml",
|
||||
|
||||
|
@ -67,27 +65,15 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root"],
|
|||
provides: [],
|
||||
setup: main
|
||||
}
|
||||
], architect);
|
||||
]);
|
||||
|
||||
function main(options, imports, register) {
|
||||
var settings = imports.settings
|
||||
var tabs = imports.tabManager;
|
||||
var fs = imports.fs;
|
||||
var save = imports.save;
|
||||
var autosave = imports.autosave;
|
||||
|
||||
function countEvents(count, expected, done) {
|
||||
if (count == expected)
|
||||
done();
|
||||
else
|
||||
throw new Error("Wrong Event Count: "
|
||||
+ count + " of " + expected);
|
||||
}
|
||||
|
||||
expect.html.setConstructor(function(tab) {
|
||||
if (typeof tab == "object")
|
||||
return tab.pane.aml.getPage("editor::" + tab.editorType).$ext;
|
||||
});
|
||||
|
||||
function changeTab(path, done) {
|
||||
var tab = tabs.findTab(path);
|
||||
tabs.focusTab(tab);
|
||||
|
@ -98,41 +84,114 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root"],
|
|||
return tab;
|
||||
}
|
||||
|
||||
function createAndChangeTab(path, options, done) {
|
||||
if (!done) {
|
||||
done = options;
|
||||
options = {};
|
||||
}
|
||||
fs.writeFile(path, path, function(err) {
|
||||
if (err) throw err;
|
||||
|
||||
options.path = path;
|
||||
tabs.open(options, function() {
|
||||
changeTab(path, done);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
describe('autosave', function() {
|
||||
this.timeout(5000);
|
||||
|
||||
before(function(done) {
|
||||
beforeEach(function(done) {
|
||||
tabs.once("ready", function() {
|
||||
tabs.getPanes()[0].focus();
|
||||
var path = "/autosave1.txt";
|
||||
fs.writeFile(path, path, function(err) {
|
||||
if (err) throw err;
|
||||
|
||||
tabs.openFile(path, function() {
|
||||
setTimeout(done, 50);
|
||||
});
|
||||
tabs.setState(null, function() {
|
||||
tabs.getPanes()[0].focus();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
bar.$ext.style.background = "rgba(220, 220, 220, 0.93)";
|
||||
bar.$ext.style.position = "fixed";
|
||||
bar.$ext.style.left = "20px";
|
||||
bar.$ext.style.right = "20px";
|
||||
bar.$ext.style.bottom = "20px";
|
||||
bar.$ext.style.height = "150px";
|
||||
|
||||
document.body.style.marginBottom = "180px";
|
||||
});
|
||||
|
||||
it('should automatically save a tab that is changed', function(done) {
|
||||
var path = "/autosave1.txt";
|
||||
changeTab(path, function(tab) {
|
||||
it("should not autosave when restoring state", function(done) {
|
||||
settings.set("user/general/@autosave", false);
|
||||
var pane = tabs.getPanes()[0].hsplit(true);
|
||||
|
||||
prepareTabs(testRestoreState);
|
||||
|
||||
function prepareTabs(callback) {
|
||||
createAndChangeTab("/autosave1.txt", function(tab) {
|
||||
expect(tab.document.changed).to.ok;
|
||||
createAndChangeTab("/__proto__", function() {
|
||||
createAndChangeTab("/<h1>", function() {
|
||||
createAndChangeTab("/__lookupSetter__", { pane: pane }, function() {
|
||||
callback();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
function testRestoreState() {
|
||||
settings.set("user/general/@autosave", true);
|
||||
expect(tabs.getTabs().length).to.equal(4);
|
||||
var state = tabs.getState(null, true);
|
||||
tabs.setState(null, function() {
|
||||
expect(tabs.getTabs().length).to.equal(0);
|
||||
setTimeout(function() {
|
||||
tabs.setState(state, function() {
|
||||
expect(tabs.getTabs().length).to.equal(4);
|
||||
expect(tabs.getTabs()[0].document.changed).to.ok;
|
||||
setTimeout(function() {
|
||||
tabs.setState(null, function() {
|
||||
save.off("afterSave", preventSave);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function preventSave() {
|
||||
done(new Error("Save is called"));
|
||||
}
|
||||
save.once("afterSave", preventSave);
|
||||
});
|
||||
|
||||
it("should automatically save a tab that is changed when editor is blurred", function(done) {
|
||||
settings.set("user/general/@autosave", true);
|
||||
var path = "/autosave2.txt";
|
||||
createAndChangeTab(path, function(tab) {
|
||||
expect(tab.document.changed).to.ok;
|
||||
|
||||
createAndChangeTab("/__proto__", function() {
|
||||
});
|
||||
save.once("afterSave", function() {
|
||||
fs.readFile(path, function(err, data) {
|
||||
if (err) throw err;
|
||||
expect(data).to.equal("test" + path);
|
||||
expect(tab.document.changed).to.not.ok;
|
||||
|
||||
fs.unlink(path, function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should automatically save after delay", function(done) {
|
||||
settings.set("user/general/@autosave", "afterDelay");
|
||||
var path = "/autosave2.txt";
|
||||
createAndChangeTab(path, function(tab) {
|
||||
expect(tab.document.changed).to.ok;
|
||||
|
||||
setTimeout(function() {
|
||||
expect(tab.document.changed).to.ok;
|
||||
tab.editor.ace.execCommand("insertstring", "x");
|
||||
}, 10);
|
||||
save.once("afterSave", function() {
|
||||
fs.readFile(path, function(err, data) {
|
||||
if (err) throw err;
|
||||
expect(data).to.equal("testx" + path);
|
||||
expect(tab.document.changed).to.not.ok;
|
||||
|
||||
fs.unlink(path, function() {
|
||||
done();
|
||||
|
|
|
@ -412,7 +412,7 @@ define(function(require, exports, module) {
|
|||
doc.meta.$saveBuffer = true;
|
||||
}
|
||||
|
||||
setSavingState(tab, "saving");
|
||||
setSavingState(tab, "saving", null, options.noUi);
|
||||
|
||||
var bookmark = doc.undoManager.position;
|
||||
var loadStartT = Date.now();
|
||||
|
@ -450,7 +450,7 @@ define(function(require, exports, module) {
|
|||
if (options.path)
|
||||
tab.path = options.path;
|
||||
|
||||
setSavingState(tab, "saved", options.timeout);
|
||||
setSavingState(tab, "saved", options.timeout, options.noUi);
|
||||
settings.save();
|
||||
logger.log("Successfully saved " + path);
|
||||
}
|
||||
|
@ -541,7 +541,7 @@ define(function(require, exports, module) {
|
|||
}
|
||||
|
||||
var stateTimer = null, pageTimers = {};
|
||||
function setSavingState(tab, state, timeout) {
|
||||
function setSavingState(tab, state, timeout, silent) {
|
||||
clearTimeout(stateTimer);
|
||||
clearTimeout(pageTimers[tab.name]);
|
||||
|
||||
|
@ -554,6 +554,12 @@ define(function(require, exports, module) {
|
|||
else
|
||||
delete doc.meta.$saving;
|
||||
|
||||
if (!silent)
|
||||
updateSavingUi();
|
||||
emit("tabSavingState", { tab: tab });
|
||||
}
|
||||
|
||||
function updateSavingUi(tab, state, timeout) {
|
||||
if (state == "saving") {
|
||||
btnSave.show();
|
||||
|
||||
|
@ -621,7 +627,6 @@ define(function(require, exports, module) {
|
|||
btnSave.setCaption("Not saved");
|
||||
tab.classList.add("error");
|
||||
}
|
||||
emit("tabSavingState", { tab: tab });
|
||||
}
|
||||
|
||||
/***** Lifecycle *****/
|
||||
|
|
|
@ -393,6 +393,7 @@ apf.page = function(struct, tagName) {
|
|||
if (this.relPage) {
|
||||
this.relPage.$ext.style.display = "";
|
||||
this.parentNode.$setStyleClass(this.relPage.$ext, "curpage");
|
||||
this.relPage.$prevFake = this.relPage.$fake;
|
||||
this.relPage.$fake = this;
|
||||
|
||||
|
||||
|
@ -604,6 +605,7 @@ apf.page = function(struct, tagName) {
|
|||
if (page && page.type == _self.id) {
|
||||
page.relPage = _self;
|
||||
if (page.$active) {
|
||||
_self.$prevFake = _self.$fake;
|
||||
_self.$fake = page;
|
||||
page.$activate();
|
||||
}
|
||||
|
|
|
@ -10964,16 +10964,9 @@ apf.window = function(){
|
|||
(apf.window.activeElement = amlNode).focus(true, e);
|
||||
|
||||
this.$settingFocus = null;
|
||||
|
||||
apf.dispatchEvent("movefocus", {
|
||||
toElement: amlNode
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
apf.dispatchEvent("movefocus", e);
|
||||
};
|
||||
|
||||
this.$blur = function(amlNode) {
|
||||
|
|
|
@ -349,7 +349,8 @@ define(function(require, exports, module) {
|
|||
"preferences.experimental": {
|
||||
addExperiment: function() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
add: function() {},
|
||||
},
|
||||
"ace.gotoline": {},
|
||||
"ace.stripws": {
|
||||
|
|
Ładowanie…
Reference in New Issue