fire-ide
Version:
Web-based Integrated Development Environment for fire.js
1,844 lines (1,668 loc) • 51.4 kB
JavaScript
$.ajaxSetup ({
cache: false
});
function EditorNodeTypeEnum() {}
var EditorNodeType = createEnum(EditorNodeTypeEnum, ['root', 'null', 'hash', 'array', 'string', 'true', 'false', 'expression', 'key', 'expressionBlock', 'index' , 'number'])
function EditorNodeModelCollection() {}
EditorNodeModelCollection.prototype.add = function(modelInfo) {
modelInfo.parentNodeTypes = modelInfo.parentNodeTypes || []
modelInfo.canEditTitle = modelInfo.canEditTitle !== undefined ? modelInfo.canEditTitle : true
modelInfo.inlineSingleChild = modelInfo.inlineSingleChild !== undefined ? modelInfo.inlineSingleChild : false
modelInfo.removable = modelInfo.removable !== undefined ? modelInfo.removable : true
modelInfo.multiChild = modelInfo.multiChild !== undefined ? modelInfo.multiChild : false
modelInfo.defaultChildType = modelInfo.defaultChildType !== undefined ? modelInfo.defaultChildType : EditorNodeType.null()
modelInfo.convertFromString = modelInfo.convertFromString || function(node, strVal, hint) { return strVal; }
if(!modelInfo.createDefaultNode) {
modelInfo.createDefaultNode = function(parentNode) {
return parentNode.createNewChild(modelInfo.defaultValue, modelInfo.type)
}
}
modelInfo.serialize = modelInfo.serialize || function(node) { return node.getValue(); }
this[modelInfo.type] = modelInfo
}
EditorNodeModelCollection.prototype.getModel = function(nodeType) {
if(!nodeType)
{
throw "nodeType argument is required"
}
var model = this[nodeType]
if(!model) {
throw "Could't find a model for type '" + nodeType.toString() + "'"
}
return model
}
var EditorNodeModels = new EditorNodeModelCollection()
// root
EditorNodeModels.add({
type: EditorNodeType.root(),
title: "Root",
childs: true,
inlineSingleChild: true,
removable: false,
decorate: function(node) {
return {
title: node.editor.rootNodeTitle || "=",
class: "root"
}
},
defaultValue: "ROOT"
})
var LITERAL_NODE_PARENT_TYPES = [
EditorNodeType.root(),
EditorNodeType.key(),
EditorNodeType.expression(),
EditorNodeType.index()]
// null
EditorNodeModels.add({
type: EditorNodeType.null(),
title: "null",
childs: false,
removable: true,
decorate: function(node) {
return {
title: "null",
class: "null"
}
},
defaultValue: null,
canEditTitle: false,
parentNodeTypes: LITERAL_NODE_PARENT_TYPES
})
// true
EditorNodeModels.add({
type: EditorNodeType.true(),
title: "true",
childs: false,
removable: true,
decorate: function(node) {
return {
title: "true",
class: "bool"
}
},
defaultValue: true,
canEditTitle: false,
parentNodeTypes: LITERAL_NODE_PARENT_TYPES
})
// false
EditorNodeModels.add({
type: EditorNodeType.false(),
title: "false",
childs: false,
removable: true,
decorate: function(node) {
return {
title: "false",
class: "bool"
}
},
defaultValue: true,
canEditTitle: false,
parentNodeTypes: LITERAL_NODE_PARENT_TYPES
})
// string
EditorNodeModels.add({
type: EditorNodeType.string(),
title: "String",
childs: false,
removable: true,
decorate: function(node) {
return {
title: node.getValue(),
class: "str"
}
},
defaultValue: "lorem ipsum dolor sit amet",
parentNodeTypes: LITERAL_NODE_PARENT_TYPES
})
// expression block
EditorNodeModels.add({
type: EditorNodeType.expressionBlock(),
title: "Code",
childs: true,
multiChild: true,
removable: true,
decorate: function(node) {
return {
title: "{",
class: "exp-block"
}
},
defaultValue: {},
canEditTitle: false,
parentNodeTypes: LITERAL_NODE_PARENT_TYPES,
defaultChildType: EditorNodeType.expression(),
serialize: function(node) {
var result = {}
var keys = {}
for(var i = 0;i < node.children.length;i++) {
var child = node.children[i]
var expValue = trimString(child.getValue())
if(!keys[expValue]) {
keys[expValue] = 1
} else {
keys[expValue]++
var prefix = ''
var x = keys[expValue]
while(x > 0) {
prefix+=' '
x--
}
expValue = prefix + expValue
}
result[expValue] = child.serialize()
}
return result
}
})
var ExpressionTags = []
function refreshExpressionTags() {
$.get('/expressions', function(data) {
ExpressionTags = []
data.response.forEach(function(item) {
ExpressionTags.push(item.name)
})
})
}
refreshExpressionTags()
// expression
EditorNodeModels.add({
type: EditorNodeType.expression(),
title: "Expression",
childs: true,
removable: true,
decorate: function(node) {
return {
title: node.getExpressionName(),
hint: getHint(node.getValue()),
class: "exp",
autoComplete: ExpressionTags
}
},
defaultValue: "@return",
parentNodeTypes: [EditorNodeType.expressionBlock()],
convertFromString: function(node, str, hint) {
if(!hint) {
hint = ''
}
if(hint && hint != '') {
return "@" + str + "("+ hint +")"
}
return "@" + str
},
serialize: function(node) {
return node.getFirstChild().serialize()
}
})
// hash
EditorNodeModels.add({
type: EditorNodeType.hash(),
title: "Hash",
childs: true,
multiChild: true,
removable: true,
decorate: function(node) {
return {
title: "{",
class: "hash"
}
},
defaultValue: {},
canEditTitle: false,
parentNodeTypes: LITERAL_NODE_PARENT_TYPES,
defaultChildType: null,
serialize: function(node) {
var result = {}
for(var i = 0;i < node.children.length;i++) {
var child = node.children[i]
result[child.getValue()] = child.serialize()
}
return result
}
})
// property
EditorNodeModels.add({
type: EditorNodeType.key(),
title: "Property",
childs: true,
removable: true,
decorate: function(node) {
return {
title: node.getValue(),
class: "key"
}
},
defaultValue: "name",
parentNodeTypes: [EditorNodeType.hash()],
inlineSingleChild: true,
serialize: function(node) {
return node.getFirstChild().serialize()
}
})
// array
EditorNodeModels.add({
type: EditorNodeType.array(),
title: "Array",
childs: true,
multiChild: true,
removable: true,
decorate: function(node) {
return {
title: "[",
class: "array"
}
},
defaultValue: {},
canEditTitle: false,
parentNodeTypes: LITERAL_NODE_PARENT_TYPES,
defaultChildType: null,
assignChildValue: function(child) {
var index = child.parent.children.indexOf(child)
child.setValue(index)
},
serialize: function(node) {
var result = []
for(var i = 0;i < node.children.length;i++) {
var child = node.children[i]
result[i] = child.serialize()
}
return result
}
})
// index
EditorNodeModels.add({
type: EditorNodeType.index(),
title: "Index",
childs: true,
removable: true,
decorate: function(node) {
return {
title: node.getValue(),
class: "index"
}
},
defaultValue: 0,
canEditTitle: false,
parentNodeTypes: [EditorNodeType.array()],
inlineSingleChild: true,
serialize: function(node) {
return node.getFirstChild().serialize()
}
})
var FIRE_NUMBER_DEFAULT_VALUE = 0
// number
EditorNodeModels.add({
type: EditorNodeType.number(),
title: "Number",
childs: false,
removable: true,
decorate: function(node) {
return {
title: node.getValue(),
class: "number"
}
},
defaultValue: FIRE_NUMBER_DEFAULT_VALUE,
parentNodeTypes: LITERAL_NODE_PARENT_TYPES,
convertFromString: function(node, str) {
var number = parseFloat(str)
if(isNaN(number)) return FIRE_NUMBER_DEFAULT_VALUE
return number
}
})
function getModelForNodeType(nodeType) {
var modelNames = Object.keys(EditorNodeModels)
for(var i = 0;i < modelNames.length;i++) {
var nodeModel = EditorNodeModels[modelNames[i]]
if(nodeType == nodeModel.type) return nodeModel
}
return null
}
function SelectionGroup() {
this.currentTarget = null
}
SelectionGroup.prototype.setSelectedTarget = function(target) {
if(this.currentTarget) {
this.currentTarget.deselect()
}
this.currentTarget = target || null
}
function FireEditor(visualContainer, selectionGroup, rootNodeTitle) {
this.selectionGroup = selectionGroup || new SelectionGroup()
this.rootVisual = visualContainer
this.rootVisual.empty()
this.visualContainer = $('<ul>').appendTo(this.rootVisual)
this.rootEditorNode = null
this.selectedNode = null
this.rootNodeTitle= rootNodeTitle || null
}
FireEditor.prototype.loadDocument = function(jsonDocument) {
this._preLoad()
this.rootEditorNode.createChild(jsonDocument)
this._postLoad()
}
FireEditor.prototype.load = function() {
this._preLoad()
this.rootEditorNode.ensureDefaultChild()
this._postLoad()
}
FireEditor.prototype.serialize = function() {
return this.rootEditorNode.children[0].serialize()
}
FireEditor.prototype._preLoad = function() {
this.setSelectedNode(null)
this.rootEditorNode = new EditorNode(this, null, null, EditorNodeType.root())
}
FireEditor.prototype._postLoad = function() {
this.rootEditorNode.appendToHtml(this.visualContainer)
}
FireEditor.prototype.setSelectedNode = function(node) {
this.selectionGroup.setSelectedTarget(node)
}
var NODE_EDIT_EVENT = "dblclick"
function createEnum(enumType, items) {
items.forEach(function(type) {
enumType.prototype[type] = function() {
return enumType["_" + type]
}
})
enumType.prototype.toString = function() {
return this.val
}
items.forEach(function(type) {
var enumMember = new enumType()
enumMember.val = type
enumType["_" + type] = enumMember
})
return new enumType()
}
function EditorNode(editor, value, parent, type) {
var self = this
this.editor = editor
if(!editor || !(editor instanceof FireEditor)) throw "invalid editor instance"
this.element = jQuery("<li>").addClass('node')
this.element.click(function(event) {
self.select()
event.preventDefault()
event.stopImmediatePropagation()
})
this.element.editorNode = this
this.subNodesList = jQuery("<ul>")
this.children = []
this.titleElement = jQuery('<span>').hide().appendTo(this.element)
this.titleElement.addClass("title").addClass('name')
this.hintElement = jQuery('<span>').hide().appendTo(this.element)
this.hintElement.addClass("title").addClass('hint')
this.toolbarElement = jQuery('<span>').hide().addClass('toolbar').appendTo(this.element)
this.toolbarElement.click(function(event) {
event.preventDefault()
event.stopImmediatePropagation()
})
this.subNodesList.appendTo(this.element)
this.staticType = type
this.dynamicType = null
this.model = null
this.setValue(value)
this.reparent(parent)
if(this.parent) {
this.parent._addChild(this)
this.appendToHtml(this.parent.subNodesList)
}
}
EditorNode.prototype.reparent = function(parent) {
this.parent = parent || null
}
EditorNode.prototype.getFirstChild = function() {
return this.children.length > 0 ? this.children[0] : null
}
EditorNode.prototype.serialize = function() {
return this.model.serialize(this)
}
EditorNode.prototype._addChild = function(node) {
this.children.push(node)
this._ensureChildValues()
return node
}
EditorNode.prototype.getChildIndex = function(node) {
return this.children.indexOf(node)
}
EditorNode.prototype.getType = function() {
return this.staticType || this.dynamicType
}
EditorNode.prototype._removeChild = function(child) {
var i = this.children.indexOf(child)
if(i > -1) {
this.children.splice(i, 1)
}
this._ensureChildValues()
}
EditorNode.prototype.remove = function() {
this.deselect()
this.element.remove()
if(this.parent) {
this.parent._removeChild(this)
}
this.editor = null
this.parent = null
}
/* Removes the current node ensuring the parent keeps it's default structure */
EditorNode.prototype.safeRemove = function() {
var parent = this.parent || null
this.remove()
if(parent) {
parent.ensureDefaultChild()
}
}
EditorNode.prototype.canRemove = function() {
return this.model.removable
}
EditorNode.prototype.copy = function() {
window.localFireIdeClipboard = this._copyCore()
return true
}
EditorNode.prototype._copyCore = function() {
return {
nodeType: this.getType(),
value: this.getValue(),
child: this.serialize()
}
}
EditorNode.prototype.canPaste = function() {
if(!window.localFireIdeClipboard ) return false
var pasteNodeModel = getModelForNodeType(window.localFireIdeClipboard.nodeType)
if(!pasteNodeModel) {
throw "pasting unsupported node type" // say what???
}
return pasteNodeModel.parentNodeTypes.indexOf(this.getType()) != -1
}
EditorNode.prototype.paste = function() {
if(window.localFireIdeClipboard ) {
this._pasteCore(window.localFireIdeClipboard)
}
window.localFireIdeClipboard = null
return true
}
EditorNode.prototype._pasteCore = function(clipboard) {
if(clipboard) {
this.willAddChild()
var pastedNode = this.createChild(clipboard.value, clipboard.nodeType)
//if(typeof(index) === 'undefined') {
// console.log("pasting at last element")
/* } else {
console.log("pasting at index", index)
this.insertChild(pastedNode, index)
}*/
if(pastedNode.model.childs) {
pastedNode.createChild(clipboard.child)
}
}
}
EditorNode.prototype.cut = function() {
this.copy()
this.safeRemove()
return true
}
EditorNode.prototype.canReorderToPrevious = function() {
if(!this.parent) return false
if(this.parent.getChildIndex(this) < 1) return false
return true
}
EditorNode.prototype.clearChildren = function() {
while(this.children.length > 0) {
this.children.pop().remove()
}
this.children = []
this.subNodesList.empty()
}
EditorNode.prototype._ensureChildValues = function() {
if(this.model.assignChildValue) {
for(var i = 0;i < this.children.length;i++) {
var child = this.children[i]
this.model.assignChildValue(child)
}
}
}
EditorNode.prototype.reorderToPrevious = function() {
if(!this.canReorderToPrevious()) return false
var oldIndex = this.parent.getChildIndex(this)
var oldParent = this.parent
var newIndex = oldIndex -1
var childrenCopy = []
for(var i = 0;i < oldParent.children.length;i++) {
var child = oldParent.children[i]
childrenCopy[i] = child
}
childrenCopy.splice(oldIndex, 1) // Remove myself
childrenCopy.splice(newIndex, 0, this) // Insert me in the position
var newChildren = []
for(var i = 0;i < childrenCopy.length;i++) {
var child = childrenCopy[i]
newChildren.push(child._copyCore())
}
oldParent.clearChildren()
for(var i = 0;i < newChildren.length;i++) {
var child = newChildren[i]
oldParent._pasteCore(child)
}
}
EditorNode.prototype._createToolbarButtons = function(buttons) {
var self = this
if(this.canRemove()) {
buttons.push({
tooltip: 'Remove the Value',
id: 'remove',
text: '[ Delete ]',
execute: function() {
self.safeRemove()
}
})
}
buttons.push({
tooltip: 'Copy',
id: 'copy',
text: "[ Copy ]",
execute: function() {
self.deselect()
self.copy()
}
})
buttons.push({
tooltip: 'Cut',
id: 'cut',
text: "[ Cut ]",
execute: function() {
self.deselect()
self.cut()
}
})
if(this.canPaste()) {
buttons.push({
tooltip: 'Paste',
id: 'paste',
text: "[ Paste ]",
execute: function() {
self.deselect()
self.paste()
}
})
}
if(this.canReorderToPrevious()) {
buttons.push({
tooltip: 'Reorder to the previous position',
id: 'reorder',
text: "[ Reorder ]",
execute: function() {
self.deselect()
self.reorderToPrevious()
}
})
}
var childModels = []
Object.keys(EditorNodeModels).forEach(function(nodeTypeName) {
var model = EditorNodeModels[nodeTypeName]
if(model.parentNodeTypes.indexOf(this.model.type) > -1) {
childModels.push(model)
}
}, this)
childModels.forEach(function(childModel) {
buttons.push({
tooltip: '',
id: childModel.type.toString(),
text: childModel.title,
execute: function() {
self.deselect()
self.willAddChild()
childModel.createDefaultNode(self).select().ensureDefaultChild()
}
})
})
}
EditorNode.prototype.toggleToolbar = function() {
var self = this
if(this.isSelected()) {
var commands = []
this._createToolbarButtons(commands)
this.toolbarElement.empty()
commands.forEach(function(cmdInfo) {
var btn = $('<a>').attr('href','#' + cmdInfo.id)
if(cmdInfo.icon) {
$('<img>').attr('src', cmdInfo.icon).appendTo(btn)
} else {
//$('<span>').addClass(cmdInfo.class).text(cmdInfo.text).appendTo(btn)
btn.text(cmdInfo.text)
}
btn.click(function(event) {
event.preventDefault()
event.stopImmediatePropagation()
if(cmdInfo.execute){
cmdInfo.execute()
}
})
this.toolbarElement.append(btn)
}, this)
this.toolbarElement.fadeIn()
} else {
this.toolbarElement.hide()
}
}
EditorNode.prototype.isSelected = function(val) {
return $(this.element).hasClass('selected')
}
EditorNode.prototype.select = function() {
if(!this.isSelected()) {
$(this.element).addClass('selected')
this.editor.setSelectedNode(this)
this.toggleToolbar()
}
return this
}
EditorNode.prototype.focus = function() {
this.element.focus()
$('html, body').animate({ scrollTop: this.element.offset().top }, 500);
return this
}
EditorNode.prototype.editTitleMode = function() {
this.titleElement.trigger(NODE_EDIT_EVENT);
return this
}
EditorNode.prototype.deselect = function(val) {
if(this.isSelected()) {
$(this.element).removeClass('selected')
this.editor.setSelectedNode(null)
this.toggleToolbar()
}
return this
}
EditorNode.prototype.toggleSelection = function(val) {
if(this.isSelected()) {
this.deselect()
} else {
this.select()
}
return this
}
EditorNode.prototype.setValue = function(val) {
this._value = val
this._ensureDynamicType()
this.model = EditorNodeModels.getModel(this.getType())
this._parseChildren()
this.updateUI()
}
EditorNode.prototype.setHint = function(hint) {
if(this.getType() != EditorNodeType.expression()) {
throw "setHint only works on expression nodes"
}
this.replaceValueFromString(this.getExpressionName(), hint)
}
EditorNode.prototype.replaceValueFromString = function(strVal, hint) {
this.setValue(this.model.convertFromString(this, strVal, hint))
}
EditorNode.prototype.getValue = function() {
return this._value
}
EditorNode.prototype.updateUI = function() {
this._updateTitleElement()
this._updateSubNodesElement()
}
EditorNode.prototype._ensureDynamicType = function() {
if(this.staticType) return
var type = null
//console.log("Value= '", this.getValue(), "' type = ", typeof(this.getValue()))
if(this.getValue() === null) {
type = EditorNodeType.null()
}
else if(typeof(this.getValue()) == 'string' && (isSpecialKey(this.getValue()))) {
type = EditorNodeType.expression()
}
else if(this.getValue() && typeof(this.getValue()) == 'object' && hasSpecialKeys(this.getValue())) {
type = EditorNodeType.expressionBlock()
}
else if(this.getValue() && (typeof(this.getValue()) == 'object' && !(this.getValue() instanceof Array))) {
type = EditorNodeType.hash()
}
else if(this.getValue() && (typeof(this.getValue()) == 'object' && (this.getValue() instanceof Array))) {
type = EditorNodeType.array()
}
else if(typeof(this.getValue()) == 'string') {
type = EditorNodeType.string()
}
else if(this.getValue() === true) {
type = EditorNodeType.true()
}
else if(this.getValue() === false) {
type = EditorNodeType.false()
}
else if(typeof(this.getValue()) == 'number') {
type = EditorNodeType.number()
}
if(!type) throw "failed to infer the Dynamic Type"
this.dynamicType = type
}
EditorNode.prototype._updateSubNodesElement = function() {
if(this.model.inlineSingleChild) {
if(this.children.length > 1) {
if(!this.subNodesList.hasClass('multi')) {
this.subNodesList.addClass('multi')
}
} else {
this.subNodesList.removeClass('multi')
this.subNodesList.addClass('single')
}
} else {
if(!this.subNodesList.hasClass('multi')) {
this.subNodesList.addClass('multi')
}
}
}
$.editable.addInputType('autocomplete', {
element : $.editable.types.text.element,
plugin : function(settings, original) {
$('input', this).autocomplete({
autoFocus: true,
source: settings.autocomplete.data,
delay: 50
});
focusEdit(this)
}
});
function focusEdit(target) {
$('input', target).select()
$('input', target).animate({
"min-width":150
}, 200)
}
$.editable.addInputType('autoSelectText', {
element : $.editable.types.text.element,
plugin : function(settings, original) {
focusEdit(this)
}
});
EditorNode.prototype._updateTitleElement = function() {
var self = this
// Remove current class name if necessary
if(this.currentTitleElementClass) {
this.titleElement.removeClass(this.currentTitleElementClass)
}
this.currentTitleElementClass = null
var nodeModel = EditorNodeModels.getModel(this.getType())
var decoration = nodeModel.decorate(this)
var newText = decoration.title
var newHint = decoration.hint
this.currentTitleElementClass = decoration.class
// Update Class
if(this.currentTitleElementClass) {
this.titleElement.addClass(this.currentTitleElementClass)
}
// Update Text
if(newText !== undefined) {
this.titleElement.fadeIn()
this.titleElement.text(newText)
if(this.canEditTitle()) {
if(decoration.autoComplete) {
$(this.titleElement).editable(function(value, settings) {
self.replaceValueFromString(value)
return nodeModel.decorate(self).title;
}, {
type : 'autocomplete',
event: NODE_EDIT_EVENT,
tooltip: '',
placeholder: '',
autocomplete: {
data: decoration.autoComplete,
target: this.titleElement
}
});
} else {
$(this.titleElement).editable(function(value, settings) {
self.replaceValueFromString(value)
return nodeModel.decorate(self).title;
}, {
type : 'autoSelectText',
event: NODE_EDIT_EVENT,
tooltip: '',
placeholder: ''
});
}
} else {
$(this.titleElement).editable('disable')
}
} else {
this.titleElement.hide()
this.titleElement.text('')
}
// Update Hint
if(newHint !== undefined) {
this.hintElement.fadeIn()
this.hintElement.text(newHint)
$(this.hintElement).editable(function(value, settings) {
self.setHint(value)
return value;
}, {
type : 'autoSelectText',
event: NODE_EDIT_EVENT,
tooltip: '',
placeholder: ''
});
} else {
this.hintElement.hide()
this.hintElement.text('')
}
}
EditorNode.prototype.canEditTitle = function() {
return EditorNodeModels.getModel(this.getType()).canEditTitle
}
EditorNode.prototype.appendToHtml = function(targetList) {
if(!targetList) throw "invalid targetList"
targetList.append(this.element)
this.updateUI()
return this
}
EditorNode.prototype.createChild = function(value, staticType) {
return new EditorNode(this.editor, value, this, staticType)
}
EditorNode.prototype.createNewChild = function(value, staticType, autoEdit) {
if(autoEdit === undefined) {
autoEdit = true
}
var newChild = this.createChild(value, staticType)
if(autoEdit) {
if(newChild.canEditTitle()) {
newChild.editTitleMode()
}
}
newChild.resetDefaultChild()
return newChild
}
EditorNode.prototype.removeChildren = function() {
while(this.children.length != 0) {
this.children[0].remove()
}
}
EditorNode.prototype.willAddChild = function() {
if(!this.model.multiChild) {
this.removeChildren()
}
}
EditorNode.prototype.ensureDefaultChild = function(force) {
if(force) {
this.removeChildren()
}
if(this.children.length == 0){
this.resetDefaultChild()
}
return this
}
EditorNode.prototype.resetDefaultChild = function() {
if(this.model.childs && this.model.defaultChildType){
EditorNodeModels.getModel(this.model.defaultChildType).createDefaultNode(this).ensureDefaultChild()
}
return this
}
EditorNode.prototype._parseChildren = function() {
var val = this.getValue()
if(this.getType() == EditorNodeType.expressionBlock()) {
Object.keys(val).forEach(function(propName) {
var propVal = val[propName]
this.createChild(propName, EditorNodeType.expression()).createChild(propVal)
}, this)
} else if(this.getType() == EditorNodeType.hash()) {
Object.keys(val).forEach(function(propName) {
var propVal = val[propName]
this.createChild(propName, EditorNodeType.key()).createChild(propVal)
}, this)
}
else if(this.getType() == EditorNodeType.array()) {
if(val) {
for(var i = 0;i < val.length;i++) {
var indexValue = val[i]
this.createChild(i, EditorNodeType.index()).createChild(indexValue)
}
}
}
}
EditorNode.prototype.createEditorForNode = function(fireNode) {
if(!(fireNode instanceof FireNode)) throw "FireNode instance expected"
var editorNode = new EditorNode(fireNode, this)
editorNode.appendToHtml(this.subNodesList)
}
function hasSpecialKeys(obj) {
var props = Object.keys(obj)
for(var i = 0;i < props.length;i++) {
if(isSpecialKey(props[i])) return true
}
return false
}
EditorNode.prototype.getExpressionName = function() {
var propName = this.getValue()
if(!propName) throw "Can't get the expression name from root"
if(!isSpecialKey(propName)){
throw "Asked to extract special from a key that is not a special key, the key was '" + propName + "'"
}
propName = trimString(propName)
if(keyHasHint(propName)) {
propName = propName.substring(0,propName.indexOf(HINT_START_SYMBOL))
}
return propName.substring(1,propName.length)
}
EditorNode.prototype.getHint = function() {
var val = this.getValue()
if(typeof(val) != 'string') return ''
return getHint(val)
}
var HINT_START_SYMBOL = "("
var HINT_END_SYMBOL = ")"
var SPECIAL_KEY_SYMBOL = "@"
function keyHasHint(propName) {
return propName.indexOf(HINT_START_SYMBOL) > -1
}
function trimString(str) {
if(str == null || str == undefined) return str
return str.replace(/^\s\s*/,'').replace(/\s\s*$/,'')
}
function isSpecialKey(propName) {
var n = trimString(propName)
return n.indexOf(SPECIAL_KEY_SYMBOL) == 0
}
function getHint(propName) {
if(!keyHasHint(propName)) return '';
var hintEndIndex = propName.indexOf(HINT_END_SYMBOL)
if(hintEndIndex > 1) {
return propName.substring(propName.indexOf(HINT_START_SYMBOL) + 1,hintEndIndex)
}
return propName.substring(propName.indexOf(HINT_START_SYMBOL) + 1,propName.length)
}
function FireFileView(visualContainer, fileSelectionCallback) {
this.fileSelectionCallback = fileSelectionCallback
this.visualContainer = visualContainer
this.list = $('ul:first', visualContainer)
var self = this
this.refreshBtn = $('a.btn.refresh', this.visualContainer).click(function(event) {
event.stopImmediatePropagation()
event.preventDefault()
self.refresh()
})
this.backBtn = $('a.btn.back', this.visualContainer).click(function(event) {
event.stopImmediatePropagation()
event.preventDefault()
self.goBack()
}).hide()
this.pathLabel = $('.path:first', this.visualContainer)
this.paths = ['']
this.navigateDir('.')
}
FireFileView.prototype.goBack = function() {
this.paths.pop()
this.refresh()
}
FireFileView.prototype.getCurrentPath = function() {
return this.paths[this.paths.length -1]
}
FireFileView.prototype.navigateDir = function(name) {
this.paths.push(name + "/")
this.refresh()
}
FireFileView.prototype.refresh = function() {
var self = this
if(this.paths.length > 2) {
this.backBtn.fadeIn()
} else {
this.backBtn.fadeOut()
}
this.selectedListItem = null
this.pathLabel.text(this.getCurrentPath())
this.refreshBtn.attr('disabled','disabled')
var currentHeight = this.list.height()
this.list.css("min-height", currentHeight)
$.get('/fs/' + this.getCurrentPath(), function(data, status, xhr) {
self.refreshBtn.removeAttr('disabled')
if(status == 'success') {
self.list.empty()
data.response.forEach(function(file) {
var listItem = $('<li>').appendTo(self.list)
listItem.attr('title', file.path)
$('<a>').attr('href',"/fs/" + file.path).text(file.path).click(function(event) {
event.preventDefault()
event.stopImmediatePropagation()
if(!file.isDirectory && self.fileSelectionCallback) {
if(self.selectedListItem) {
self.selectedListItem.removeClass('selected')
}
self.selectedListItem = listItem
self.selectedListItem.addClass('selected')
self.fileSelectionCallback(file.path)
} else {
self.navigateDir(file.path)
}
}).hide().appendTo(listItem).fadeIn()
})
self.list.animate({
"min-height": null
})
} else {
console.error('Fire IDE file view can not retrieve the list of files')
}
})
}
function FireIde(filesPlaceholder, editorContainer) {
var socket = io.connect(window.location.origin);
window.fireIdeSocket = socket
var self = this
this.editorContainer = editorContainer
this.editorPlaceholder = $('div.editor_placeholder', editorContainer)
this.editorTopbar = $('div.topbar', editorContainer)
this.runBtn = $('a.btn.run')
this.runBtn.click(function(event) {
event.stopImmediatePropagation()
event.preventDefault()
var interval = null
var reloadStream = function() {
$.get('/run/current/stdout', function(data){
var textArea = $('.stdout .stream', self.editorPlaceholder)
textArea.val(data)
textArea.scrollTop(textArea[0].scrollHeight);
})
$.get('/run/current/stderr', function(data){
var textArea = $('.stderr .stream', self.editorPlaceholder)
textArea.val(data)
textArea.scrollTop(textArea[0].scrollHeight);
})
}
var refreshRun = function() {
if(self.currentRunInfo && self.currentRunInfo.running) {
$('.pid', self.editorPlaceholder).text('PID: ' + (self.currentRunInfo.pid || 'Stopped'))
$('.stderr .path', self.editorPlaceholder).text(self.currentRunInfo.stderr)
$('.stdout .path', self.editorPlaceholder).text(self.currentRunInfo.stdout)
$('a.btn.run', self.editorPlaceholder).text('Stop')
} else {
$('.pid', self.editorPlaceholder).text('Not Running')
$('.stderr .path', self.editorPlaceholder).text('')
$('.stdout .path', self.editorPlaceholder).text('')
$('a.btn.run', self.editorPlaceholder).text('Start')
}
}
self.currentEditor = null
self._updateEditorUI()
var reloadCurrentRun = function() {
$.get('/run/current', function(data, status) {
self.currentRunInfo = data.response
refreshRun()
reloadStream()
clearInterval(interval)
if(self.currentRunInfo && self.currentRunInfo.running)
{
interval = setInterval(function(){
reloadStream()
}, DELAY)
}
})
}
var DELAY = 500
self.editorPlaceholder.load('/run', function(data, status) {
var stdoutText = $('.stdout .stream', self.editorPlaceholder)
$('a.btn.run', self.editorPlaceholder).click(function(event) {
event.stopImmediatePropagation()
event.preventDefault()
if(self.currentRunInfo && self.currentRunInfo.running) {
// Stop
$.ajax({
url: '/run/current',
type: "DELETE",
complete: function(jqXHR, status) {
if(status == 'success') {
reloadCurrentRun()
} else {
console.log(status)
}
}
})
} else {
// run
$.post('/run', function(data, status) {
if(status == 'success') {
stdoutText.val('')
reloadCurrentRun()
} else {
console.log(status)
}
})
}
})
socket.on('stdout', function (data) {
//console.log("stdout", data)
stdoutText.val(stdoutText.val() + data)
stdoutText.scrollTop(stdoutText[0].scrollHeight);
});
socket.on('exit', function (data) {
reloadCurrentRun()
});
refreshRun()
})
})
this.deployBtn = $('a.btn.deploy')
this.deployBtn.click(function(event) {
event.stopImmediatePropagation()
event.preventDefault()
self.currentEditor = null
self._updateEditorUI()
self.editorPlaceholder.load('/deploy', function(data, status) {
})
})
this.filesPlaceholder = filesPlaceholder || null
this.currentEditor = null
this.filesView = new FireFileView(this.filesPlaceholder, function(filePath){
var editorRefreshFinished = function() {
}
var fileType = null
if(self.currentEditor && (self.currentEditor.editorProvider.getFileType(filePath) == self.currentEditor.fileType)) {
self.currentEditor.loadFile(filePath, editorRefreshFinished)
self._updateEditorUI()
} else {
self._clearCurrentEditor()
var editorProvider = null
for(var i = 0;i < self.editorProviders.length; i++) {
var provider = self.editorProviders[i]
if(fileType = provider.getFileType(filePath)) {
editorProvider = provider
break
}
}
if(!editorProvider) {
editorProvider = new FireUnsupportedEditorProvider()
}
var editor = new editorProvider.editorType(self.editorPlaceholder)
editor.editorProvider = editorProvider
editor.fileType = fileType
editor.loadFile(filePath, editorRefreshFinished)
if(editorProvider instanceof FireUnsupportedEditorProvider) {
self.currentEditor = null
} else {
self.currentEditor = editor
}
self._updateEditorUI()
}
})
this.editorProviders = [
new FireJSONEditorProvider(),
new JSONFileEditorProvider(),
new JavascriptFileEditorProvider()
]
for(var i = 0; i < this.editorProviders.length; i++) {
this.editorProviders[i].ide = this
}
this.editorSaveButton = $('a.btn.save', this.editorContainer)
this.editorDeleteButton = $('a.btn.delete', this.editorContainer)
this.editorPathLabel = $('span.path', this.editorContainer)
this.editorSaveButton.click(function(event) {
event.stopImmediatePropagation()
event.preventDefault()
self.currentEditor.save()
})
// Delete File Dialog
$( "div.delete-file-dialog" ).dialog({
autoOpen: false,
height: "auto",
width: 350,
modal: true,
buttons: {
"No": function() {
$( this ).dialog( "close" );
},
"Yes": function() {
deleteFileFromDialog()
}
}
});
this.editorDeleteButton.click(function(event) {
event.stopImmediatePropagation()
event.preventDefault()
$('div.delete-file-dialog span.filename').text(self.currentEditor.filePath)
$('div.delete-file-dialog').dialog('open')
})
var createFileFromDialog = function() {
$( "div.create-file-dialog" ).dialog( "close" );
self.createFile(self._getSelectedFileTypeDialog(), self.fileNameInput.val())
}
var deleteFileFromDialog = function() {
$( "div.delete-file-dialog" ).dialog( "close" );
self.currentEditor.delete(function() {
self.filesView.refresh()
})
self.currentEditor = null
self._updateEditorUI()
}
// Create File Dialog
$( "div.create-file-dialog" ).dialog({
autoOpen: false,
height: 250,
width: 350,
modal: true,
buttons: {
"Cancel": function() {
$( this ).dialog( "close" );
},
"Create": function() {
createFileFromDialog()
}
}
});
$( "div.create-file-dialog" ).keydown(function(e){
if (e.keyCode == 13) {
e.stopPropagation()
e.preventDefault()
createFileFromDialog()
}
});
this.fileTypeCombo = $( "div.create-file-dialog select#file-type" )
this.fileTypes = []
this.editorProviders.forEach(function(provider) {
for(var i = 0; i < provider.fileTypes.length; i++) {
self.fileTypes.push(provider.fileTypes[i])
}
})
var providerId = 0
this.fileTypes.forEach(function(fileType) {
self.fileTypeCombo.append($('<option>').attr('value', providerId).text(fileType.description))
providerId++
})
self.fileTypeCombo.change(function() {
var selectedFileType = self._getSelectedFileTypeDialog()
if(selectedFileType && selectedFileType.fixedFileName) {
self.fileNameInput.attr('disabled', 'disabled')
self.fileNameInput.val(selectedFileType.fixedFileName)
} else {
self.fileNameInput.removeAttr('disabled', 'disabled')
}
})
this.fileNameInput = $( "div.create-file-dialog input#file-name" )
// Create File Button
this.createFileButton = $('a.btn.create', this.filesPlaceholder)
this.createFileButton.click(function(event) {
event.stopImmediatePropagation()
event.preventDefault()
self.fileNameInput.val('')
$('div.create-file-dialog').dialog('open')
})
// Finish Initialization
self._updateEditorUI()
}
FireIde.prototype._clearCurrentEditor = function() {
this.editorPlaceholder.empty()
}
FireIde.prototype._getSelectedFileTypeDialog = function() {
return this.fileTypes[parseInt(this.fileTypeCombo.val())]
}
FireIde.prototype.createFile = function(fileType, fileName) {
this._clearCurrentEditor()
var provider = fileType.provider
var self = this
var editor = new provider.editorType(this.editorPlaceholder)
editor.editorProvider = provider
editor.newFile(fileType.addExtensionToFileName(this.filesView.getCurrentPath() + fileName), fileName, fileType, function() {
self.currentEditor = editor
self._updateEditorUI()
self.filesView.refresh()
})
}
FireIde.prototype._updateEditorUI = function() {
if(this.currentEditor) {
this.editorPathLabel.fadeIn()
this.editorPathLabel.text(this.currentEditor.filePath)
this.editorSaveButton.fadeIn()
this.editorDeleteButton.fadeIn()
} else {
this._clearCurrentEditor()
this.editorPathLabel.hide()
this.editorSaveButton.hide()
this.editorDeleteButton.hide()
}
}
function FireIdeEditorProvider() {
this.fileTypes = []
}
FireIdeEditorProvider.prototype.addFileType = function(fileType) {
if(!(fileType instanceof FireIdeEditorFileType)) {
throw "fileType must be instance of FireIdeEditorFileType"
}
fileType.provider = this
this.fileTypes.push(fileType)
}
FireIdeEditorProvider.prototype.getFileType = function(filePath) {
for(var i = 0; i < this.fileTypes.length; i++) {
var fileType = this.fileTypes[i]
var canEdit = fileType.canEdit(filePath)
if(canEdit) return fileType
}
return null
}
FireIdeEditorProvider.prototype.canEdit = function(filePath) {
return this.getFileType(filePath) != null
}
FireIdeEditorProvider.prototype.createEditor = function(editorPlaceholder) {
throw "createEditor, missing implementation"
}
function FireIdeEditorFileType(description, extension, fixedFileName) {
this.extensionRegex = new RegExp("(\\.(" + extension + ")$)", 'i')
this.extension = extension
this.description = description
this.provider = null
this.fixedFileName = fixedFileName
}
FireIdeEditorFileType.prototype.addExtensionToFileName = function(fileName) {
if(this.fixedFileName) {
return fileName
}
return fileName + "." + this.extension
}
FireIdeEditorFileType.prototype.canEdit = function(filePath) {
return this.extensionRegex.test(filePath)
}
FireIdeEditorFileType.prototype.createNewFileContent = function(fileName) {
throw "FireIdeEditorFileType.createNewFileContent, missing implementation"
}
function FireIdeEditor(editorPlaceholder) {
this.editorPlaceholder = editorPlaceholder || null
this.filePath = null
this.fileType = null
this.content = null
}
FireIdeEditor.prototype.loadFile = function(filePath, refreshFinishedCallback) {
this.filePath = filePath
if(!this.fileType) {
this.fileType = this.editorProvider.getFileType(this.filePath)
}
this.reload(refreshFinishedCallback)
}
FireIdeEditor.prototype.reload = function(refreshFinishedCallback) {
var self = this
$.get('/fs/' + this.filePath, function(response, status, xhr) {
self.content = response.response
self.refresh(refreshFinishedCallback)
});
}
FireIdeEditor.prototype.newFile = function(newFilePath, fileName, fileType, finishedCallback) {
this.filePath = newFilePath
this.fileType = this.editorProvider.getFileType(this.filePath)
var self = this
this.content = fileType.createNewFileContent(fileName)
self.refresh(function() {
self.save(finishedCallback)
})
}
FireIdeEditor.prototype.save = function(saveFinishedCallback) {
this.beforeSave()
var self = this
$.ajax({
url: '/fs/' + this.filePath,
type: "POST",
data: {
content: this.content
},
complete: function(response, status, xhr) {
refreshExpressionTags()
if(saveFinishedCallback)
{
saveFinishedCallback()
}
}
});
}
FireIdeEditor.prototype.delete = function(finishedCallback) {
$.ajax({
url: '/fs/' + this.filePath,
type: "DELETE",
complete: function(jqXHR, status) {
finishedCallback()
}
})
}
FireIdeEditor.prototype.beforeSave = function() {
}
FireIdeEditor.prototype.refresh = function() {
throw "FireIdeEditor.refresh, missing implementation"
}
/*
* FireUnsupportedEditorProvider
*/
function FireUnsupportedEditorProvider() {
}
FireUnsupportedEditorProvider.prototype = new FireIdeEditorProvider()
FireUnsupportedEditorProvider.prototype.canEdit = function(fileName) {
return true
}
FireUnsupportedEditorProvider.prototype.editorType = FireUnsupportedEditor
function FireUnsupportedEditor(editorPlaceholder) {
FireIdeEditor.apply(this, arguments)
this._warningContainer = $('<div>').append($('<p>').text('Sorry, there is no editor available for this kind of file')).addClass('unsupported-editor').appendTo(this.editorPlaceholder)
}
FireUnsupportedEditor.prototype = new FireIdeEditor()
FireUnsupportedEditor.prototype.refresh = function(refreshFinishedCallback) {
// booh!
refreshFinishedCallback()
}
function FireIdeToJSONString(value) {
return JSON.stringify(value, null, 2)
}
/*
* FireJSONEditorProvider
*/
function FireJSONEditorProvider() {
var fireJSONFile = new FireIdeEditorFileType("Fire.js JSON Expression(.fjson)", "fjson")
fireJSONFile.createNewFileContent = function(fileName) {
return FireIdeToJSONString({
name: fileName,
json: null
})
}
this.addFileType(fireJSONFile)
}
FireJSONEditorProvider.prototype = new FireIdeEditorProvider()
FireJSONEditorProvider.prototype.editorType = FireJSONEditor
function FireJSONEditor(editorPlaceholder) {
FireIdeEditor.apply(this, arguments)
this.attributesEditorContainer = $('<div>').addClass('attributes').append((this.attributesEditorElement = $('<div>').addClass('editor'))).appendTo(this.editorPlaceholder)
this.bodyEditorContainer = $('<div>').addClass('editor_body').append((this.bodyEditorElement = $('<div>').addClass('editor'))).appendTo(this.editorPlaceholder)
}
FireJSONEditor.prototype = new FireIdeEditor()
FireJSONEditor.prototype.getDocumentParts = function(doc) {
if(doc && typeof(doc) == 'object' && (!(doc instanceof Array))) {
var parts = {
attributes: {},
body: doc.json || null
}
Object.keys(doc).forEach(function(prop) {
if(prop != 'json') {
parts.attributes[prop] = doc[prop]
}
})
return parts
} else {
return {
attributes: {
name: this.filePath
},
body: null
}
}
}
FireJSONEditor.prototype.beforeSave = function() {
var finalDoc = {}
var attributes = this.attributesEditor.serialize()
Object.keys(attributes).forEach(function(prop) {
if(prop != 'json') {
finalDoc[prop] = attributes[prop]
}
})
finalDoc.json = this.bodyEditor.serialize()
this.content = FireIdeToJSONString(finalDoc)
}
FireJSONEditor.prototype.refresh = function(refreshFinishedCallback) {
var docParts = this.getDocumentParts(JSON.parse(this.content))
var editorSelection = new SelectionGroup()
this.attributesEditor = new FireEditor(this.attributesEditorElement, editorSelection, "Attributes")
this.attributesEditorContainer.css("min-height", this.attributesEditorContainer.height())
this.attributesEditor.loadDocument(docParts.attributes)
this.attributesEditorContainer.animate({
"min-height": null
})
this.bodyEditor = new FireEditor(this.bodyEditorElement, editorSelection, "Body")
this.bodyEditorContainer.css("min-height", this.bodyEditorContainer.height())
this.bodyEditor.loadDocument(docParts.body)
this.bodyEditorContainer.animate({
"min-height": null
})
refreshFinishedCallback()
}
/*
* JSONFileEditorProvider
*/
function JSONFileEditorProvider() {
var self = this
var packageFileType = new FireIdeEditorFileType("package.json", "package.json", "package.json")
packageFileType.extensionRegex = /package.json$/i
packageFileType.createNewFileContent = function(fileName) {
return FireIdeToJSONString({
name: "MyApp",
version: "1.0.0"
})
}
packageFileType.createHeaderView = function(editor, elementContainer) {
var packageNameInput = null
var packageInfoContainer = null
var buttons = null
var loaderIcon = null
var npmSearchElementContainer = $('<div>').addClass('npm-search-container').appendTo(elementContainer)
var npmSearchElement = $('<div>').addClass('npm-search')
npmSearchElement.append($('<p>').addClass('title').text('NPM Search')).append(packageNameInput = $('<input type="text">')).append(loaderIcon = $('<img class="loader" src="/images/ajax-loader.gif">').hide()).append(packageInfoContainer = $('<div>').hide()).append(buttons = $('<div class="buttons">').hide())
npmSearchElement.appendTo(npmSearchElementContainer)
$('<span>').addClass('attribute-name').text('Description:').appendTo(packageInfoContainer)
var packageDescriptionLabel = $('<span>').addClass('attribute-value').appendTo(packageInfoContainer)
$('<span>').addClass('attribute-name').text('Version:').appendTo(packageInfoContainer)
var packageVersionLabel = $('<span>').addClass('attribute-value').appendTo(packageInfoContainer)
$('<span>').addClass('attribute-name').text('Author:').appendTo(packageInfoContainer)
var packageAuthorLabel = $('<span>').addClass('attribute-value').appendTo(packageInfoContainer)
$('<span>').addClass('attribute-name').text('fire.js Enabled:').appendTo(packageInfoContainer)
var packageEnabledLabel = $('<span>').addClass('attribute-value').appendTo(packageInfoContainer)
var cancelButton = $('<a class="btn" href="#cancel">').text('Cancel').appendTo(buttons)
var addDependencyButton = $('<a class="btn" href="#addDependency">').text('Add Dependency').appendTo(buttons)
var npmSearchButtons = $('<div class="buttons">').appendTo(npmSearchElementContainer)
var installButton = $('<a class="btn" href="#install">').text('Update Dependencies').appendTo(npmSearchButtons)
cancelButton.click(function(event) {
event.stopPropagation()
event.preventDefault()
packageInfoContainer.hide()
buttons.hide()
packageNameInput.val('')
})
installButton.click(function(event) {
loaderIcon.fadeIn()
event.stopPropagation()
event.preventDefault()
$.get('/npm/install/', function(data) {
editor.reload()
loaderIcon.fadeOut()
refreshExpressionTags()
self.ide.filesView.refresh()
})
})
addDependencyButton.click(function(event) {
loaderIcon.fadeIn()
event.stopPropagation()
event.preventDefault()
$.post('/npm/dependencies',{
name: packageNameInput.val()
}, function(data) {
editor.reload()
loaderIcon.fadeOut()
refreshExpressionTags()
self.ide.filesView.refresh()
})
})
packageNameInput.change(function() {
packageInfoContainer.hide()
buttons.fadeOut()
loaderIcon.show()
$.get('/npm/info/' + $(this).val(), function(data) {
loaderIcon.hide()
if(!data.response) {
} else {
var packageInfo = data.response[Object.keys(data.response)[0]]
packageDescriptionLabel.text(packageInfo.description)
packageVersionLabel.text(packageInfo.version)
packageAuthorLabel.text(packageInfo.author)
var isEnabled = packageInfo.keywords && packageInfo.keywords.indexOf('ignitable') != -1
packageEnabledLabel.text(isEnabled ? "Yes!" : "No")
if(isEnabled) {
packageEnabledLabel.addClass("highlight-value")
} else {
packageEnabledLabel.removeClass("highlight-value")
}
packageInfoContainer.fadeIn()
buttons.fadeIn()
}
})
})
}
this.addFileType(packageFileType)
var manifestFile = new FireIdeEditorFileType("Fire.js Ignition Manifest", ".manifest.json", "ignition.manifest.json")
manifestFile.createNewFileContent = function(fileName) {
return FireIdeToJSONString({
modules: []
})
}
this.addFileType(manifestFile)
var JSONFile = new FireIdeEditorFileType("Plain JSON File(.json)", "json")
JSONFile.createNewFileContent = function(fileName) {
return FireIdeToJSONString({})
}
this.addFileType(JSONFile)
}
JSONFileEditorProvider.prototype = new FireIdeEditorProvider()
JSONFileEditorProvider.prototype.editorType = JSONFileEditor
function JSONFileEditor(editorPlaceholder) {
FireIdeEditor.apply(this, arguments)
this.bodyEditorContainer = $('<div>').addClass('editor_body').append((this.headerEditorContainer = $('<div>').addClass('editor'))).append((this.bodyEditorElement = $('<div>').addClass('editor'))).appendTo(this.editorPlaceholder)
this.headerEditorContainer.hide()
}
JSONFileEditor.prototype = new FireIdeEditor()
JSONFileEditor.prototype.beforeSave = function() {
this.content = FireIdeToJSONString(this.bodyEditor.serialize(),null, 2)
}
JSONFileEditor.prototype.refresh = function(refreshFinishedCallback) {
var doc = JSON.parse(this.content)
var editorSelection = new SelectionGroup()
this.bodyEditor = new FireEditor(this.bodyEditorElement, editorSelection)
this.bodyEditorContainer.css("min-height", this.bodyEditorContainer.height())
this.bodyEditor.loadDocument(doc)
this.bodyEditorContainer.animate({
"min-height": null
})
if(this.fileType.createHeaderView) {
this.headerEditorContainer.empty()
this.headerEditorContainer.show()
this.fileType.createHeaderView(this, this.headerEditorContainer)
} else {
this.headerEditorContainer.empty()
this.headerEditorContainer.hide()
}
if(refreshFinishedCallback) {
refreshFinishedCallback()
}
}
/*
* JavascriptFileEditorProvider
*/
function JavascriptFileEditorProvider() {
var JSFile = new FireIdeEditorFileType("Plain Javascript File(.js)", "js")
JSFile.createNewFileContent = function(fileName) {
return 'console.log("Hello There: ' + fileName + '")'
}
this.addFileType(JSFile)
var FireInitFile = new FireIdeEditorFileType("Fire.js Bootstraper index.js", "js", "index.js")
FireInitFile.createNewFileContent = function(fileName) {
return 'var fire = require("fire")\n\nfire.executeApplication(["package.json"].concat(process.argv.slice(2)))\n\n'
}
this.addFileType(FireInitFile)
var CustomExpressionFile = new FireIdeEditorFileType("Fire.js Javascript Expression(.fjs)", "fjs")
CustomExpressionFile.createNewFileContent = function(fileName) {
var ExpName = fileName.replace(/\./ig, "_") + "_Expression"
return 'var fire =