jsoneditor/src_old/js/appendNodeFactory.js

229 lines
6.1 KiB
JavaScript
Raw Normal View History

'use strict';
var util = require('./util');
var ContextMenu = require('./ContextMenu');
/**
* A factory function to create an AppendNode, which depends on a Node
* @param {Node} Node
*/
function appendNodeFactory(Node) {
/**
* @constructor AppendNode
* @extends Node
* @param {TreeEditor} editor
* Create a new AppendNode. This is a special node which is created at the
* end of the list with childs for an object or array
*/
function AppendNode (editor) {
/** @type {TreeEditor} */
this.editor = editor;
this.dom = {};
}
AppendNode.prototype = new Node();
/**
* Return a table row with an append button.
* @return {Element} dom TR element
*/
AppendNode.prototype.getDom = function () {
// TODO: implement a new solution for the append node
var dom = this.dom;
if (dom.tr) {
return dom.tr;
}
this._updateEditability();
// a row for the append button
var trAppend = document.createElement('tr');
trAppend.node = this;
dom.tr = trAppend;
// TODO: consistent naming
if (this.editor.options.mode === 'tree') {
// a cell for the dragarea column
dom.tdDrag = document.createElement('td');
// create context menu
var tdMenu = document.createElement('td');
dom.tdMenu = tdMenu;
var menu = document.createElement('button');
menu.className = 'jsoneditor-contextmenu';
menu.title = 'Click to open the actions menu (Ctrl+M)';
dom.menu = menu;
tdMenu.appendChild(dom.menu);
}
// a cell for the contents (showing text 'empty')
var tdAppend = document.createElement('td');
var domText = document.createElement('div');
domText.innerHTML = '(empty)';
domText.className = 'jsoneditor-readonly';
tdAppend.appendChild(domText);
dom.td = tdAppend;
dom.text = domText;
this.updateDom();
return trAppend;
};
/**
* Update the HTML dom of the Node
*/
AppendNode.prototype.updateDom = function () {
var dom = this.dom;
var tdAppend = dom.td;
if (tdAppend) {
tdAppend.style.paddingLeft = (this.getLevel() * 24 + 26) + 'px';
// TODO: not so nice hard coded offset
}
var domText = dom.text;
if (domText) {
domText.innerHTML = '(empty ' + this.parent.type + ')';
}
// attach or detach the contents of the append node:
// hide when the parent has childs, show when the parent has no childs
var trAppend = dom.tr;
if (!this.isVisible()) {
if (dom.tr.firstChild) {
if (dom.tdDrag) {
trAppend.removeChild(dom.tdDrag);
}
if (dom.tdMenu) {
trAppend.removeChild(dom.tdMenu);
}
trAppend.removeChild(tdAppend);
}
}
else {
if (!dom.tr.firstChild) {
if (dom.tdDrag) {
trAppend.appendChild(dom.tdDrag);
}
if (dom.tdMenu) {
trAppend.appendChild(dom.tdMenu);
}
trAppend.appendChild(tdAppend);
}
}
};
/**
* Check whether the AppendNode is currently visible.
* the AppendNode is visible when its parent has no childs (i.e. is empty).
* @return {boolean} isVisible
*/
AppendNode.prototype.isVisible = function () {
return (this.parent.childs.length == 0);
};
/**
* Show a contextmenu for this node
* @param {HTMLElement} anchor The element to attach the menu to.
* @param {function} [onClose] Callback method called when the context menu
* is being closed.
*/
AppendNode.prototype.showContextMenu = function (anchor, onClose) {
var node = this;
var titles = Node.TYPE_TITLES;
var items = [
// create append button
{
'text': 'Append',
'title': 'Append a new field with type \'auto\' (Ctrl+Shift+Ins)',
'submenuTitle': 'Select the type of the field to be appended',
'className': 'jsoneditor-insert',
'click': function () {
node._onAppend('', '', 'auto');
},
'submenu': [
{
'text': 'Auto',
'className': 'jsoneditor-type-auto',
'title': titles.auto,
'click': function () {
node._onAppend('', '', 'auto');
}
},
{
'text': 'Array',
'className': 'jsoneditor-type-array',
'title': titles.array,
'click': function () {
node._onAppend('', []);
}
},
{
'text': 'Object',
'className': 'jsoneditor-type-object',
'title': titles.object,
'click': function () {
node._onAppend('', {});
}
},
{
'text': 'String',
'className': 'jsoneditor-type-string',
'title': titles.string,
'click': function () {
node._onAppend('', '', 'string');
}
}
]
}
];
var menu = new ContextMenu(items, {close: onClose});
menu.show(anchor, this.editor.content);
};
/**
* Handle an event. The event is catched centrally by the editor
* @param {Event} event
*/
AppendNode.prototype.onEvent = function (event) {
var type = event.type;
var target = event.target || event.srcElement;
var dom = this.dom;
// highlight the append nodes parent
var menu = dom.menu;
if (target == menu) {
if (type == 'mouseover') {
this.editor.highlighter.highlight(this.parent);
}
else if (type == 'mouseout') {
this.editor.highlighter.unhighlight();
}
}
// context menu events
if (type == 'click' && target == dom.menu) {
var highlighter = this.editor.highlighter;
highlighter.highlight(this.parent);
highlighter.lock();
util.addClassName(dom.menu, 'jsoneditor-selected');
this.showContextMenu(dom.menu, function () {
util.removeClassName(dom.menu, 'jsoneditor-selected');
highlighter.unlock();
highlighter.unhighlight();
});
}
if (type == 'keydown') {
this.onKeyDown(event);
}
};
return AppendNode;
}
module.exports = appendNodeFactory;