')
line.prepend(content)
options.transform(value.text, content)
line.prepend($('
'))
line.prepend($('
▶'))
el.prepend(line)
return el;
}
/**
* @param {Element} rootElement
* @param rootData
*/
function render(rootElement, rootData) {
trigger('rendering')
let first = 0;
let last = rootData.length();
let elements = $(rootElement).children('div.list-item');
let $enter = elements.slice(first, last);
let enterData = rootData.slice(first, $enter.length);
let exitData = rootData.slice($enter.length);
let $exitEl = elements.slice($enter.length)
let hideLevel = 99999;
$enter.each(function (index, li) {
let storeId = enterData[index]
let value = rootData.value(storeId)
let hasChildren = false;
if (index + 1 < last) {
let next = rootData.afterValue(storeId)
hasChildren = next && (value.indented < next.indented)
}
let $li = $(li).data('id', value.id)
.toggleClass('selected', cursor.atPosition(index))
.toggleClass('selection-first', selection.isSelectedFirst(index))
.toggleClass('selection-last', selection.isSelectedLast(index))
.toggleClass('selection', selection.isSelected(index))
.toggleClass('hidden', value.indented >= hideLevel)
.toggleClass('border', value.indented >= 1)
.css('margin-left', (value.indented * 32) + 'px')
.find('.content')
value.hidden = value.indented >= hideLevel
options.transform(value.text, $li)
if (value.indented < hideLevel) {
if (value.fold !== 'open') {
hideLevel = value.indented + 1
} else {
hideLevel = 99999;
}
}
$('.fold', $(li))
.toggleClass('open', value.fold === 'open')
.toggleClass('no-children', !hasChildren)
$(li).toggleClass('no-children', !hasChildren)
.toggleClass('open', value.fold === 'open')
});
_.each(exitData, function (storeId, index) {
let value = rootData.value(storeId)
let $li = newItem(value)
.css('margin-left', (value.indented * 32) + 'px')
.toggleClass('selection-first', selection.isSelectedFirst(index))
.toggleClass('selection-last', selection.isSelectedLast(index))
.toggleClass('selection', selection.isSelected(index))
.toggleClass('selected', cursor.atPosition(index + $enter.length))
.toggleClass('border', value.indented >= 1)
.toggleClass('hidden', value.indented >= hideLevel);
value.hidden = value.indented >= hideLevel
let hasChildren = false;
if (enterData.length + index + 1 < last) {
let next = rootData.afterValue(storeId)
hasChildren = next && (value.indented < next.indented)
}
if (value.indented < hideLevel) {
if (value.fold === 'open') {
hideLevel = 99999;
} else {
hideLevel = value.indented + 1
}
}
$('.fold', $li)
.toggleClass('open', value.fold === 'open')
.toggleClass('no-children', !hasChildren)
$li.toggleClass('no-children', !hasChildren)
.toggleClass('open', value.fold === 'open')
$(rootElement).append($li)
})
$exitEl.remove()
trigger('rendered')
}
function disableDragging(drake) {
if (drake) drake.destroy();
}
function enableDragging(rootElement) {
let drake = dragula([rootElement], {
moves: function (el, container, handle) {
return handle.classList.contains('marker')
}
});
let start = -1;
let startID = null;
drake.on('drag', function (el, source) {
startID = $(el).data('id')
})
drake.on('drop', function (el, target, source, sibling) {
let stopID = $(sibling).data('id')
if (startID === stopID) {
return
}
let id = store.moveBefore(startID, stopID)
let position = store.index(id);
cursor.set(position)
selection.selectOne(position, store)
trigger('change')
})
return drake;
}
function stopEditing(rootElement, store, element) {
if (!editing) return
if (element === null) {
editing = false
currentEditor = null
return
}
let text = element.val()
$(element).closest('.list-item').removeClass('editor');
store.update(element.data('id'), (value) => {
return _.merge(value, {
text: text
})
})
if (store.hasChanged()) {
trigger('change')
store.clearChanged()
}
let $span = $('
');
options.transform(text, $span)
element.replaceWith($span);
trigger('stop-editing', currentEditor[0])
editing = false
currentEditor = null
$(root).focus()
}
/**
* @param {Element} rootElement
* @param {Store} store
* @param cursor
* @returns {jQuery|HTMLElement}
*/
function startEditing(rootElement, store, cursor) {
if (editing) return
editing = true
let elements = $(rootElement).children('div.list-item');
let $textarea = $('