|
(() => { |
|
//observing the dom enables the fix on situations other than manually resizing the panes, |
|
//but it is slower as it will observe changes in the dom often |
|
const observer_enabled = true; |
|
|
|
//sometimes the "maximum" class is not added to .monaco-sash, |
|
//so the .split-view-view height or width has to be tested |
|
//use -1 to not test |
|
const minimum_height = 70; |
|
const minimum_width = 220; |
|
|
|
//set to true and run the script again to only disable events/observer |
|
const script_disable = false; |
|
|
|
//end of settings |
|
|
|
//check height/width |
|
const minimum_height_or_width = minimum_height !== -1 || minimum_width !== -1; |
|
|
|
//store for event functions and observer to be able to remove them if ran again |
|
const data_ob_key = 'fix_for_125997'; |
|
window[data_ob_key] = window[data_ob_key] || {}; |
|
const data_ob = window[data_ob_key]; |
|
|
|
//clear previous events and observer |
|
if (data_ob.event_on_mousedown) { |
|
document.removeEventListener('mousedown', data_ob.event_on_mousedown, {capture: true}); |
|
delete data_ob.event_on_mousedown; |
|
} |
|
if (data_ob.event_on_mouseup) { |
|
document.removeEventListener('mouseup', data_ob.event_on_mouseup, {capture: true}); |
|
delete data_ob.event_on_mouseup; |
|
} |
|
if (data_ob.observer) { |
|
data_ob.observer.disconnect(); |
|
delete data_ob.observer; |
|
} |
|
|
|
//script disabled |
|
if (script_disable) { |
|
delete window[data_ob_key]; |
|
return; |
|
} |
|
|
|
//prevent mutation observer from reacting if sash manually moved recently |
|
const sash_mmoved = { |
|
recent: false, |
|
time: 600, |
|
timer: undefined, |
|
done: () => { |
|
if (!observer_enabled) { return; } |
|
sash_mmoved.recent = true; |
|
clearTimeout(sash_mmoved.timer); |
|
sash_mmoved.timer = setTimeout(() => sash_mmoved.recent = false, sash_mmoved.time); |
|
} |
|
}; |
|
|
|
//mouse events/data |
|
let doc_is_mousedown = false; |
|
let doc_mousedown_on_sash = false; |
|
let gvc_sash_simulated_moving = false; |
|
data_ob.event_on_mousedown = e => { |
|
if (gvc_sash_simulated_moving) { return; } |
|
if (e.target.classList.contains('monaco-sash') && !e.target.classList.contains('disabled')) { |
|
doc_mousedown_on_sash = true; |
|
} |
|
doc_is_mousedown = true; |
|
}; |
|
data_ob.event_on_mouseup = () => { |
|
if (gvc_sash_simulated_moving) { return; } |
|
doc_is_mousedown = false; |
|
if (doc_mousedown_on_sash) { |
|
doc_mousedown_on_sash = false; |
|
//mark sash as moved recently |
|
sash_mmoved.done(); |
|
//fix |
|
fix_min_max_timed(); |
|
} |
|
}; |
|
document.addEventListener('mousedown', data_ob.event_on_mousedown, {capture: true, passive: true}); |
|
document.addEventListener('mouseup', data_ob.event_on_mouseup, {capture: true, passive: true}); |
|
|
|
//simulate resize |
|
const simulate_ev = (el, {opts = {}, type = 'mousemove'} = {}) => { |
|
const ev = new MouseEvent(type, Object.assign({bubbles: true, cancelable: false}, opts)); |
|
el.dispatchEvent(ev); |
|
}; |
|
const simulate_resize = (el, {x = 0, y = 0} = {}) => { |
|
if (!x && !y) { return; } |
|
simulate_ev(el, {type: 'mousedown', opts: {clientX: 0, clientY: 0}}); |
|
simulate_ev(el, {type: 'mousemove', opts: {clientX: x, clientY: y}}); |
|
simulate_ev(el, {type: 'mouseup', opts: {clientX: x, clientY: y}}); |
|
}; |
|
|
|
//fix |
|
const grid_view_container = document.querySelector('.grid-view-container'); |
|
const arr_sort_pos = (arr, is_vertical) => { |
|
const pos_prop = is_vertical ? 'top' : 'left'; |
|
arr.sort((a, b) => (parseInt(b.style[pos_prop], 10) - parseInt(a.style[pos_prop], 10))); |
|
return arr; |
|
}; |
|
const dom_child_match = (parent_el, sel) => { |
|
for (const el of parent_el.children) { |
|
if (el.matches(sel)) { return el; } |
|
} |
|
return null; |
|
}; |
|
const dom_children_match = (parent_el, sel) => { |
|
const ret = []; |
|
for (const el of parent_el.children) { |
|
if (el.matches(sel)) { ret.push(el); } |
|
} |
|
return ret; |
|
}; |
|
const dom_lineal_match = (parent_el, sel_arr) => { |
|
let pel_tmp = parent_el; |
|
for (const sel of sel_arr) { |
|
pel_tmp = dom_child_match(pel_tmp, sel); |
|
if (!pel_tmp) { break; } |
|
} |
|
return pel_tmp; |
|
}; |
|
|
|
const fix_min_max_get_els_list = (split_view, arr, { |
|
data_split_view_parent = false, lvl = 0, el_sash = false |
|
} = {}) => { |
|
let el_tmp = dom_lineal_match(split_view, ['.monaco-grid-branch-node', '.monaco-split-view2.separator-border']); |
|
const is_vertical = el_tmp && el_tmp.classList.contains('vertical'); |
|
const sash_cont = el_tmp && dom_child_match(el_tmp, '.sash-container'); |
|
el_tmp = el_tmp && dom_lineal_match(el_tmp, ['.monaco-scrollable-element', '.split-view-container']); |
|
el_tmp = el_tmp && dom_children_match(el_tmp, '.split-view-view.visible'); |
|
//found |
|
const split_view_children = el_tmp || []; |
|
if (!split_view_children.length || !sash_cont) { return; } |
|
const sashes = dom_children_match(sash_cont, '.monaco-sash'); |
|
if (!sashes.length) { return; } |
|
arr_sort_pos(sashes, is_vertical); |
|
arr_sort_pos(split_view_children, is_vertical); |
|
//save |
|
if (!arr[lvl]) { arr[lvl] = []; } |
|
const data_split_view = { |
|
data_split_view_parent, el: split_view, el_sash, |
|
is_vertical, sash_cont, sashes, views: split_view_children |
|
}; |
|
arr[lvl].push(data_split_view); |
|
//do children views |
|
for (let i = 0; i < split_view_children.length; i++) { |
|
const split_view_child = split_view_children[i]; |
|
let child_el_sash = sashes[i]; |
|
let child_el_sash_is_first = false; |
|
if (!child_el_sash) { |
|
child_el_sash = sashes.slice(-1)[0]; |
|
child_el_sash_is_first = true; |
|
} |
|
fix_min_max_get_els_list(split_view_child, arr, { |
|
data_split_view_parent: data_split_view, |
|
el_sash: child_el_sash, el_sash_is_first: child_el_sash_is_first, |
|
lvl: lvl + 1 |
|
}); |
|
} |
|
}; |
|
const fix_min_max_get_split_views = () => { |
|
const split_views_arr = []; |
|
fix_min_max_get_els_list( |
|
dom_child_match(grid_view_container, '.monaco-grid-view'), |
|
split_views_arr |
|
); |
|
split_views_arr.reverse(); |
|
return split_views_arr; |
|
}; |
|
|
|
const fix_min_max_expand = item => { |
|
const px_add = item.is_maximum ? -1 : 1; |
|
const opts = item.is_vertical ? {y: px_add} : {x: px_add}; |
|
simulate_resize(item.el, opts); |
|
}; |
|
const fix_min_max_expand_ancestor = ( |
|
data_split_view, sash_first_is_vertical, sash_count |
|
) => { |
|
let data_split_view_ancestor = data_split_view; |
|
while (data_split_view_ancestor) { |
|
const {el_sash} = data_split_view_ancestor; |
|
//find ancestor view sash with same orientation |
|
if (el_sash) { |
|
const el_sash_is_vertical = el_sash.classList.contains('vertical'); |
|
if (sash_first_is_vertical === el_sash_is_vertical) { |
|
//resize non disabled |
|
if (!el_sash.classList.contains('disabled')) { |
|
const {el_sash_is_first} = data_split_view_ancestor; |
|
const px_add = (sash_count + 1) * (el_sash_is_first ? 1 : -1); |
|
const opts = el_sash_is_vertical ? {x: px_add} : {y: px_add}; |
|
simulate_resize(el_sash, opts); |
|
} |
|
//stop |
|
break; |
|
} |
|
} |
|
data_split_view_ancestor = data_split_view_ancestor.data_split_view_parent; |
|
} |
|
}; |
|
|
|
let fix_min_max_timer; |
|
let fix_min_max_pending; |
|
const fix_min_max_time = 50; |
|
const fix_min_max_timed = (delay = fix_min_max_time) => { |
|
fix_min_max_pending = true; |
|
clearTimeout(fix_min_max_timer); |
|
fix_min_max_timer = setTimeout(() => { |
|
fix_min_max(); |
|
fix_min_max_pending = false; |
|
}, delay); |
|
}; |
|
const fix_min_max = () => { |
|
gvc_sash_simulated_moving = true; |
|
//split view data, by level: deeper first, sorted by arr_sort_pos |
|
const split_views_arr = fix_min_max_get_split_views(); |
|
for (const split_views_lvl_arr of split_views_arr) { |
|
for (const data_split_view of split_views_lvl_arr) { |
|
const {is_vertical, sashes, views} = data_split_view; |
|
const items_to_fix = []; |
|
for (let sash_i = 0; sash_i < sashes.length; sash_i++) { |
|
const sash = sashes[sash_i]; |
|
//disabled, expand ancestor |
|
let is_disabled = sash.classList.contains('disabled'); |
|
if (is_disabled) { |
|
fix_min_max_expand_ancestor( |
|
data_split_view, sash.classList.contains('vertical'), sashes.length |
|
); |
|
} |
|
//still disabled, keep going |
|
is_disabled = sash.classList.contains('disabled'); |
|
if (is_disabled) { continue; } |
|
//by class |
|
const is_minimum = sash.classList.contains('minimum'); |
|
let is_maximum = sash.classList.contains('maximum'); |
|
//by size |
|
if (!is_maximum && !is_minimum) { |
|
const view_prev = views[sash_i]; |
|
if ( |
|
minimum_height_or_width && (is_vertical ? minimum_height : minimum_width) !== -1 && |
|
view_prev && view_prev.style[is_vertical ? 'height' : 'width'] === `${ |
|
is_vertical ? minimum_height : minimum_width |
|
}px` |
|
) { |
|
is_maximum = true; |
|
} |
|
} |
|
//can/needs to be fixed |
|
if (is_minimum !== is_maximum) { |
|
items_to_fix[is_maximum ? 'push' : 'unshift']({el: sash, is_maximum, is_vertical}); |
|
} |
|
} |
|
for (const item of items_to_fix) { fix_min_max_expand(item); } |
|
} |
|
} |
|
gvc_sash_simulated_moving = false; |
|
}; |
|
|
|
//observer |
|
if (observer_enabled) { |
|
data_ob.observer = new MutationObserver(records => { |
|
//mouse is down, sash moved recently, fix pending |
|
if (doc_is_mousedown || sash_mmoved.recent || fix_min_max_pending) { |
|
return; |
|
} |
|
//search records |
|
let fix_it = false; |
|
for (const record of records) { |
|
const target = record.target; |
|
//added/removed nodes |
|
if (record.type === 'childList') { |
|
if ( |
|
(record.addedNodes.length || record.removedNodes.length) && |
|
target.matches('.split-view-container, .sash-container') |
|
) { |
|
fix_it = true; |
|
break; |
|
} |
|
} |
|
else if (record.type === 'attributes') { |
|
//class |
|
if (record.attributeName === 'class') { |
|
if ( |
|
target.classList.contains('monaco-sash') && !target.classList.contains('disabled') && |
|
target.className !== record.oldValue && |
|
!target.classList.contains('hover') && |
|
!record.oldValue.match(/\bhover\b/) && |
|
target.classList.contains('minimum') !== target.classList.contains('maximum') |
|
) { |
|
fix_it = true; |
|
break; |
|
} |
|
} |
|
//style |
|
else if (record.attributeName === 'style' && target.classList.contains('split-view-view')) { |
|
const is_vertical = target.matches( |
|
'.monaco-split-view2.vertical > .monaco-scrollable-element > .split-view-container > .split-view-view' |
|
); |
|
if ( |
|
(is_vertical ? minimum_height : minimum_width) !== -1 && |
|
target.style[is_vertical ? 'height' : 'width'] === `${is_vertical ? minimum_height : minimum_width}px` |
|
) { |
|
fix_it = true; |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
if (fix_it) { fix_min_max_timed(); } |
|
}); |
|
data_ob.observer.observe(grid_view_container, { |
|
attributeFilter: ['class'].concat(minimum_height_or_width ? ['style'] : []), |
|
attributeOldValue: true, |
|
subtree: true, |
|
childList: true |
|
}); |
|
} |
|
|
|
//initial fix |
|
fix_min_max_timed(); |
|
})(); |