зеркало из https://github.com/mozilla/FlightDeck.git
removed MooTools dependencies for FDEditor and Ace Editor
This commit is contained in:
Родитель
be4ff9b116
Коммит
0549f127b0
|
@ -385,10 +385,6 @@ module.exports = new Class({
|
||||||
},
|
},
|
||||||
|
|
||||||
setupButtonTooltips: function() {
|
setupButtonTooltips: function() {
|
||||||
if(typeof FloatingTips === 'undefined') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.tips = new FloatingTips('.UI_Editor_Menu .UI_Editor_Menu_Button', {
|
this.tips = new FloatingTips('.UI_Editor_Menu .UI_Editor_Menu_Button', {
|
||||||
position: 'top',
|
position: 'top',
|
||||||
balloon: true
|
balloon: true
|
||||||
|
|
|
@ -5,151 +5,156 @@
|
||||||
* Class: FDEditor
|
* Class: FDEditor
|
||||||
*/
|
*/
|
||||||
var Class = require('shipyard/class/Class'),
|
var Class = require('shipyard/class/Class'),
|
||||||
object = require('shipyard/utils/object'),
|
object = require('shipyard/utils/object'),
|
||||||
ace = require('ace/ace'),
|
log = require('shipyard/utils/log'),
|
||||||
FDEditor = require('./FDEditor');
|
ace = require('ace/ace'),
|
||||||
|
FDEditor = require('./FDEditor');
|
||||||
|
|
||||||
// globals: Spinner
|
var JSMode = require('ace/modes/javascript').Mode,
|
||||||
|
CSSMode = require('ace/modes/css').Mode,
|
||||||
|
HTMLMode = require('ace/modes/html').Mode,
|
||||||
|
TextMode = require('ace/modes/txt').Mode;
|
||||||
|
|
||||||
|
var Modes = {
|
||||||
|
'javascript': new JSMode(),
|
||||||
|
'css': new CSSMode(),
|
||||||
|
'html': new HTMLMode(),
|
||||||
|
'txt': new TextMode()
|
||||||
|
};
|
||||||
|
|
||||||
var stripDeltas = function(stack) {
|
var stripDeltas = function(stack) {
|
||||||
// Change Stack (undo/redo) in Ace is represented as
|
// Change Stack (undo/redo) in Ace is represented as
|
||||||
// [[DeltaObject1], [DeltaObject2], ... ]
|
// [[DeltaObject1], [DeltaObject2], ... ]
|
||||||
// these objects have to be copied - not referenced
|
// these objects have to be copied - not referenced
|
||||||
var deltas = [];
|
var deltas = [];
|
||||||
stack.each(function(single){
|
stack.each(function(single){
|
||||||
deltas.push(object.merge({}, single[0]));
|
deltas.push(object.merge({}, single[0]));
|
||||||
});
|
});
|
||||||
return deltas;
|
return deltas;
|
||||||
};
|
};
|
||||||
|
|
||||||
var buildStack = function(deltas) {
|
var buildStack = function(deltas) {
|
||||||
// Extract stored deltas into the stack
|
// Extract stored deltas into the stack
|
||||||
var stack = [];
|
var stack = [];
|
||||||
deltas.each(function(delta){
|
deltas.each(function(delta){
|
||||||
stack.push([object.merge({}, delta)]);
|
stack.push([object.merge({}, delta)]);
|
||||||
});
|
});
|
||||||
return stack;
|
return stack;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = new Class({
|
module.exports = new Class({
|
||||||
|
|
||||||
Extends: FDEditor,
|
Extends: FDEditor,
|
||||||
|
|
||||||
options: {
|
options: {
|
||||||
element_type: 'div'
|
element_type: 'div'
|
||||||
},
|
},
|
||||||
|
|
||||||
modes: {},
|
modes: {},
|
||||||
|
|
||||||
available_modes: ['js', 'txt', 'html', 'css'],
|
available_modes: ['js', 'txt', 'html', 'css'],
|
||||||
|
|
||||||
default_kind: 'txt',
|
default_kind: 'txt',
|
||||||
|
|
||||||
mode_translate: {
|
mode_translate: {
|
||||||
'js': 'javascript',
|
'js': 'javascript',
|
||||||
'txt': 'text'
|
'txt': 'text'
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize: function(wrapper, options) {
|
initialize: function(wrapper, options) {
|
||||||
this.parent(wrapper, options);
|
this.parent(wrapper, options);
|
||||||
this.editor = ace.edit(this.element);
|
this.editor = ace.edit(this.element.getNode());
|
||||||
this.editor.getSession().setUseWorker(false);
|
this.editor.getSession().setUseWorker(false);
|
||||||
this.spinner = new Spinner(this.element.getElement('.ace_scroller'), {
|
this.spinner = this.element.getElement('.ace_scroller');
|
||||||
maskBorder: false
|
|
||||||
});
|
|
||||||
var that = this;
|
|
||||||
|
|
||||||
['blur', 'focus'].each(function(ev) {
|
|
||||||
that.editor.on(ev, function(){
|
|
||||||
that.fireEvent(ev);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
addMode: function(mode) {
|
var that = this;
|
||||||
var name;
|
|
||||||
var Mode;
|
['blur', 'focus'].each(function(ev) {
|
||||||
if (!this.modes[mode]) {
|
that.editor.on(ev, function(){
|
||||||
name = mode;
|
that.emit(ev);
|
||||||
if (this.mode_translate[mode]) {
|
});
|
||||||
name = this.mode_translate[mode];
|
});
|
||||||
}
|
},
|
||||||
//TODO: explicitly require the modes we plan to use up
|
|
||||||
//above, so that they can be bundled with `shipyard build`
|
|
||||||
Mode = require('ace/mode/' + name).Mode;
|
|
||||||
this.modes[mode] = new Mode();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setEditable: function() {
|
setEditable: function() {
|
||||||
this.editor.setReadOnly(false);
|
this.editor.setReadOnly(false);
|
||||||
this.hookChangeIfNeeded();
|
this.hookChangeIfNeeded();
|
||||||
},
|
},
|
||||||
|
|
||||||
setReadOnly: function() {
|
setReadOnly: function() {
|
||||||
this.editor.setReadOnly(true);
|
this.editor.setReadOnly(true);
|
||||||
if (this.change_hooked) {
|
if (this.change_hooked) {
|
||||||
this.unhookChange();
|
this.unhookChange();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
hookChange: function(){
|
hookChange: function(){
|
||||||
// hook to onChange Event
|
// hook to onChange Event
|
||||||
this.editor.getSession().on('change', this.boundWhenItemChanged);
|
this.editor.getSession().on('change', this.boundWhenItemChanged);
|
||||||
this.change_hooked = true;
|
this.change_hooked = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
unhookChange: function(){
|
unhookChange: function(){
|
||||||
// unhook the onChange Event
|
// unhook the onChange Event
|
||||||
this.editor.getSession().removeEventListener('change', this.boundWhenItemChanged);
|
this.editor.getSession().removeEventListener('change', this.boundWhenItemChanged);
|
||||||
this.change_hooked = false;
|
this.change_hooked = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
getContent: function(){
|
getContent: function(){
|
||||||
var value = this.editor.getSession().getValue();
|
var value = this.editor.getSession().getValue();
|
||||||
return value;
|
return value;
|
||||||
},
|
},
|
||||||
|
|
||||||
_setContent: function(value){
|
_setContent: function(value){
|
||||||
this.editor.getSession().setValue(value);
|
this.editor.getSession().setValue(value);
|
||||||
var cursor = this.current.cursorPos || { row: 0, column: 0 };
|
var cursor = this.current.cursorPos || { row: 0, column: 0 };
|
||||||
this.editor.selection.moveCursorTo(cursor.row, cursor.column);
|
this.editor.selection.moveCursorTo(cursor.row, cursor.column);
|
||||||
},
|
},
|
||||||
|
|
||||||
getUndoRedoStack: function() {
|
getUndoRedoStack: function() {
|
||||||
var current_manager = this.editor.getSession().getUndoManager();
|
var current_manager = this.editor.getSession().getUndoManager();
|
||||||
return {
|
return {
|
||||||
redoDeltas: stripDeltas(current_manager.$redoStack),
|
redoDeltas: stripDeltas(current_manager.$redoStack),
|
||||||
undoDeltas: stripDeltas(current_manager.$undoStack)
|
undoDeltas: stripDeltas(current_manager.$undoStack)
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
setUndoRedoStack: function(obj){
|
setUndoRedoStack: function(obj){
|
||||||
var current_manager = this.editor.getSession().getUndoManager();
|
var current_manager = this.editor.getSession().getUndoManager();
|
||||||
current_manager.$redoStack = buildStack(obj.redoDeltas);
|
current_manager.$redoStack = buildStack(obj.redoDeltas);
|
||||||
current_manager.$undoStack = buildStack(obj.undoDeltas);
|
current_manager.$undoStack = buildStack(obj.undoDeltas);
|
||||||
},
|
},
|
||||||
|
|
||||||
dumpCurrent: function() {
|
dumpCurrent: function() {
|
||||||
// dump undo buffers
|
// dump undo buffers
|
||||||
this.current.undo_manager = this.getUndoRedoStack();
|
this.current.undo_manager = this.getUndoRedoStack();
|
||||||
this.current.cursorPos = this.editor.selection.getCursor();
|
this.current.cursorPos = this.editor.selection.getCursor();
|
||||||
this.parent();
|
this.parent();
|
||||||
},
|
},
|
||||||
|
|
||||||
activateItem: function(item) {
|
activateItem: function(item) {
|
||||||
this.parent(item);
|
this.parent(item);
|
||||||
// load undo buffers
|
// load undo buffers
|
||||||
if (this.current.undo_manager) {
|
if (this.current.undo_manager) {
|
||||||
this.setUndoRedoStack(this.current.undo_manager);
|
this.setUndoRedoStack(this.current.undo_manager);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
setSyntax: function(kind){
|
setSyntax: function(kind){
|
||||||
if (!this.available_modes.contains(kind)) {
|
if (this.available_modes.indexOf(kind) === -1) {
|
||||||
kind = this.default_kind;
|
log.info('Mode (%s) not found. Using txt mode.', kind);
|
||||||
}
|
kind = this.default_kind;
|
||||||
this.addMode(kind);
|
} else if (this.mode_translate[kind]) {
|
||||||
this.editor.getSession().setMode(this.modes[kind]);
|
kind = this.mode_translate[kind];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Modes[kind]) {
|
||||||
|
// This should only ever be the case if above is broken.
|
||||||
|
// ie, available_modes and mode_translate aren't in sync
|
||||||
|
// with Modes at the top.
|
||||||
|
log.warn('Mode (%s) not found. Bad.');
|
||||||
|
kind = this.default_kind;
|
||||||
|
}
|
||||||
|
this.editor.getSession().setMode(Modes[kind]);
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,49 +7,48 @@
|
||||||
* Otherwise standard textarea will be used.
|
* Otherwise standard textarea will be used.
|
||||||
*/
|
*/
|
||||||
var Class = require('shipyard/class/Class'),
|
var Class = require('shipyard/class/Class'),
|
||||||
Events = require('shipyard/class/Events'),
|
Events = require('shipyard/class/Events'),
|
||||||
Options = require('shipyard/class/Options'),
|
Options = require('shipyard/class/Options'),
|
||||||
object = require('shipyard/utils/object');
|
dom = require('shipyard/dom'),
|
||||||
|
object = require('shipyard/utils/object'),
|
||||||
|
log = require('shipyard/utils/log');
|
||||||
|
|
||||||
// globals: Element, Spinner, fd
|
var LOADING_CLASS = 'loading';
|
||||||
|
|
||||||
var FDEditor = module.exports = new Class({
|
var FDEditor = module.exports = new Class({
|
||||||
|
|
||||||
Implements: [Options, Events],
|
Implements: [Options, Events],
|
||||||
|
|
||||||
options: {
|
options: {
|
||||||
element_type: 'textarea'
|
element_type: 'textarea'
|
||||||
},
|
},
|
||||||
|
|
||||||
$name: 'FlightDeckEditor',
|
|
||||||
|
|
||||||
items: {},
|
items: {},
|
||||||
|
|
||||||
current: false,
|
current: false,
|
||||||
|
|
||||||
initialize: function(wrapper, options) {
|
initialize: function(wrapper, options) {
|
||||||
this.setOptions(options);
|
this.setOptions(options);
|
||||||
|
wrapper = this.spinner = dom.$(wrapper);
|
||||||
// create empty editor
|
// create empty editor
|
||||||
this.element = new Element(this.options.element_type,{
|
this.element = new dom.Element(this.options.element_type,{
|
||||||
'text': '',
|
'text': '',
|
||||||
'class': 'UI_Editor_Area'
|
'class': 'UI_Editor_Area'
|
||||||
});
|
});
|
||||||
this.element.inject(wrapper);
|
wrapper.appendChild(this.element);
|
||||||
this.spinner = new Spinner('editor-wrapper');
|
this.changed = false;
|
||||||
this.changed = false;
|
|
||||||
// prepare change events
|
// prepare change events
|
||||||
this.boundWhenItemChanged = this.whenItemChanged.bind(this);
|
this.boundWhenItemChanged = this.whenItemChanged.bind(this);
|
||||||
this.boundSetContent = this.setContent.bind(this);
|
this.boundSetContent = this.setContent.bind(this);
|
||||||
this.addEvent('setContent', function(c) {
|
this.emit('setContent', function(c) {
|
||||||
this.switching = false;
|
this.switching = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
registerItem: function(uid, item){
|
registerItem: function(uid, item){
|
||||||
this.items[uid] = item;
|
this.items[uid] = item;
|
||||||
var editor = this;
|
var editor = this;
|
||||||
item.observe('uid', function(updated, old) {
|
item.observe('uid', function(updated, old) {
|
||||||
$log('uid changed for registed item:' + updated);
|
|
||||||
editor.items[updated] = item;
|
editor.items[updated] = item;
|
||||||
delete editor[old];
|
delete editor[old];
|
||||||
});
|
});
|
||||||
|
@ -60,7 +59,7 @@ var FDEditor = module.exports = new Class({
|
||||||
},
|
},
|
||||||
|
|
||||||
deactivateCurrent: function(){
|
deactivateCurrent: function(){
|
||||||
// deactivate and store changes
|
// deactivate and store changes
|
||||||
this.current.active = false;
|
this.current.active = false;
|
||||||
// store changes
|
// store changes
|
||||||
this.dumpCurrent();
|
this.dumpCurrent();
|
||||||
|
@ -72,10 +71,10 @@ var FDEditor = module.exports = new Class({
|
||||||
this.current = item;
|
this.current = item;
|
||||||
this.current.active = true;
|
this.current.active = true;
|
||||||
if (!this.current.isLoaded()) {
|
if (!this.current.isLoaded()) {
|
||||||
this.spinner.show();
|
this.spinner.addClass(LOADING_CLASS);
|
||||||
this.setContent('', true);
|
this.setContent('', true);
|
||||||
this.current.loadContent(function(content) {
|
this.current.loadContent(function(content) {
|
||||||
if (item == editor.current) {
|
if (item === editor.current) {
|
||||||
editor.setContent(content);
|
editor.setContent(content);
|
||||||
editor.spinner.hide();
|
editor.spinner.hide();
|
||||||
}
|
}
|
||||||
|
@ -83,7 +82,7 @@ var FDEditor = module.exports = new Class({
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.setContent(this.current.get('content'));
|
this.setContent(this.current.get('content'));
|
||||||
this.spinner.hide();
|
this.spinner.removeClass(LOADING_CLASS);
|
||||||
}
|
}
|
||||||
if (this.current.get('readonly')) {
|
if (this.current.get('readonly')) {
|
||||||
this.setReadOnly();
|
this.setReadOnly();
|
||||||
|
@ -94,13 +93,13 @@ var FDEditor = module.exports = new Class({
|
||||||
},
|
},
|
||||||
|
|
||||||
switchTo: function(uid){
|
switchTo: function(uid){
|
||||||
$log('FD: DEBUG: FDEditor.switchTo ' + uid);
|
log.debug('FDEditor.switchTo ' + uid);
|
||||||
var self = this;
|
var self = this;
|
||||||
this.switching = true;
|
this.switching = true;
|
||||||
var item = this.getItem(uid);
|
var item = this.getItem(uid);
|
||||||
if (!item) {
|
if (!item) {
|
||||||
//this.registerItem(item);
|
//this.registerItem(item);
|
||||||
$log('no item wtf');
|
log.error('No item found in Editor with uid:', uid);
|
||||||
}
|
}
|
||||||
if (this.current) {
|
if (this.current) {
|
||||||
this.deactivateCurrent();
|
this.deactivateCurrent();
|
||||||
|
@ -122,8 +121,8 @@ var FDEditor = module.exports = new Class({
|
||||||
},
|
},
|
||||||
|
|
||||||
setEditable: function() {
|
setEditable: function() {
|
||||||
if (this.element.get('readonly')) {
|
if (this.element.get('readonly')) {
|
||||||
this.element.erase('readonly');
|
this.element.set('readonly', null);
|
||||||
}
|
}
|
||||||
this.hookChangeIfNeeded();
|
this.hookChangeIfNeeded();
|
||||||
},
|
},
|
||||||
|
@ -149,21 +148,21 @@ var FDEditor = module.exports = new Class({
|
||||||
},
|
},
|
||||||
|
|
||||||
hookChange: function(){
|
hookChange: function(){
|
||||||
this.element.addEvent('keyup', this.boundWhenItemChanged);
|
this.element.addListener('keyup', this.boundWhenItemChanged);
|
||||||
this.change_hooked = true;
|
this.change_hooked = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
unhookChange: function(){
|
unhookChange: function(){
|
||||||
this.element.removeEvent('keyup', this.boundWhenItemChanged);
|
this.element.removeEvent('keyup', this.boundWhenItemChanged);
|
||||||
this.change_hooked = false;
|
this.change_hooked = false;
|
||||||
$log('FD: INFO: No longer following changes');
|
log.info('No longer following changes');
|
||||||
},
|
},
|
||||||
|
|
||||||
whenItemChanged: function() {
|
whenItemChanged: function() {
|
||||||
if (!this.switching && this.getContent() != this.current.original_content) {
|
if (!this.switching && this.getContent() !== this.current.original_content) {
|
||||||
this.current.setChanged(true);
|
this.current.setChanged(true);
|
||||||
this.fireEvent('change');
|
this.emit('change');
|
||||||
$log('DEBUG: changed, code is considered dirty and will remain'+
|
log.debug('changed, code is considered dirty and will remain'+
|
||||||
'be treated as such even if changes are reverted');
|
'be treated as such even if changes are reverted');
|
||||||
this.unhookChange();
|
this.unhookChange();
|
||||||
} else if (!this.switching && this.current.changed) {
|
} else if (!this.switching && this.current.changed) {
|
||||||
|
@ -171,19 +170,21 @@ var FDEditor = module.exports = new Class({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getContent: function() {
|
getContent: function() {
|
||||||
return this.element.value;
|
return this.element.value;
|
||||||
},
|
},
|
||||||
|
|
||||||
setContent: function(value, quiet) {
|
setContent: function(value, quiet) {
|
||||||
this._setContent(value);
|
this._setContent(value);
|
||||||
if (!quiet) this.fireEvent('setContent', value);
|
if (!quiet) {
|
||||||
return this;
|
this.emit('setContent', value);
|
||||||
},
|
}
|
||||||
|
return this;
|
||||||
_setContent: function(value) {
|
},
|
||||||
this.element.set('value', value);
|
|
||||||
},
|
_setContent: function(value) {
|
||||||
|
this.element.set('value', value);
|
||||||
|
},
|
||||||
|
|
||||||
isChanged: function() {
|
isChanged: function() {
|
||||||
return this.items.some(function(item) {
|
return this.items.some(function(item) {
|
||||||
|
@ -192,14 +193,14 @@ var FDEditor = module.exports = new Class({
|
||||||
},
|
},
|
||||||
|
|
||||||
setSyntax: function(){},
|
setSyntax: function(){},
|
||||||
|
|
||||||
focus: function() {
|
focus: function() {
|
||||||
this.editor.focus();
|
this.editor.focus();
|
||||||
this.fireEvent('focus');
|
this.emit('focus');
|
||||||
},
|
},
|
||||||
|
|
||||||
blur: function() {
|
blur: function() {
|
||||||
this.editor.blur();
|
this.editor.blur();
|
||||||
this.fireEvent('blur');
|
this.emit('blur');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Загрузка…
Ссылка в новой задаче